[SQL] 실제 HTML 트리로 중첩 된 세트에서 모든 레코드를 렌더링하는 방법
SQL실제 HTML 트리로 중첩 된 세트에서 모든 레코드를 렌더링하는 방법
내 레일 프로젝트에 awesome_nested_set 플러그인을 사용하고 있습니다. 이 같은 모습 (간체) 두 개의 모델을 가지고 :
class Customer < ActiveRecord::Base
has_many :categories
end
class Category < ActiveRecord::Base
belongs_to :customer
# Columns in the categories table: lft, rgt and parent_id
acts_as_nested_set :scope => :customer_id
validates_presence_of :name
# Further validations...
end
예상대로 데이터베이스에있는 나무가 구성된다. PARENT_ID, LFT와 RGT의 모든 값은 정확합니다. 나무는 (awesome_nested_set에서 허용 물론이다) 여러 루트 노드가.
지금, 나는 구조와 같은 올바르게 정렬 된 트리에서 해당 고객의 모든 범주를 렌더링 할 : 예를 들어 중첩 된
- 태그. 이것은 너무 어렵지 않을 것이다 그러나 나는 그것이 효율적으로해야 (적은 SQL은 더 나은 쿼리).
-
==============================
1.중첩 된 세트가 더 나은했다 밖으로 상자의 기능 그것을하지 않는다면 그것은 좋은 것입니다.
중첩 된 세트가 더 나은했다 밖으로 상자의 기능 그것을하지 않는다면 그것은 좋은 것입니다.
당신이 발견 한 것처럼 트릭은 평평한 세트에서 트리를 구축하는 것입니다 :
아래 참조 :
def tree_from_set(set) #set must be in order buf = START_TAG(set[0]) stack = [] stack.push set[0] set[1..-1].each do |node| if stack.last.lft < node.lft < stack.last.rgt if node.leaf? #(node.rgt - node.lft == 1) buf << NODE_TAG(node) else buf << START_TAG(node) stack.push(node) end else# buf << END_TAG stack.pop retry end end buf <<END_TAG end def START_TAG(node) #for example "<li><p>#{node.name}</p><ul>" end def NODE_TAG(node) "<li><p>#{node.name}</p></li>" end def END_TAG "</li></ul>" end
-
==============================
2.나는 최근에 PHP에 대한 비슷한 질문 (중첩 된 세트 == 수정 전순 트리 탐색 모델) 대답했다.
나는 최근에 PHP에 대한 비슷한 질문 (중첩 된 세트 == 수정 전순 트리 탐색 모델) 대답했다.
기본 개념은 노드가 이미 주문하고 하나 개의 SQL 쿼리를 이용하여 깊이 표시와 함께 얻을 수 있습니다. 쉽게 루비이 변환하는 것, 그래서 거기에서 그것은 루프 또는 재귀를 통해 출력을 렌더링 단지 질문입니다.
나는에서 awesome_nested_set 플러그에 익숙하지 해요,하지만 중첩 된 세트를 다루는 꽤 표준 작업 / 필요가 그대로 이미 주석 깊이, 주문 결과를 얻을 수있는 옵션이 포함되어있을 수 있습니다.
-
==============================
3.2009년 9월 멋진 중첩 된 세트가 포함되어 있기 때문에 특별한 방법은이 작업을 수행합니다 : https://github.com/collectiveidea/awesome_nested_set/commit/9fcaaff3d6b351b11c4b40dc1f3e37f33d0a8cbe
2009년 9월 멋진 중첩 된 세트가 포함되어 있기 때문에 특별한 방법은이 작업을 수행합니다 : https://github.com/collectiveidea/awesome_nested_set/commit/9fcaaff3d6b351b11c4b40dc1f3e37f33d0a8cbe
이 방법은 별도의 데이터베이스 쿼리를 필요로하지 않기 때문에 수준을 호출하는 것보다 훨씬 더 효율적이다.
예 : Category.each_with_level (Category.root.self_and_descendants) 할 | 오, 레벨 |
-
==============================
4.당신은 자신을 재귀 적으로 호출하는 부분을 렌더링해야합니다. 이 같은:
당신은 자신을 재귀 적으로 호출하는 부분을 렌더링해야합니다. 이 같은:
# customers/show.html.erb <p>Name: <%= @customer.name %></p> <h3>Categories</h3> <ul> <%= render :partial => @customer.categories %> </ul> # categories/_category.html.erb <li> <%= link_to category.name, category %> <ul> <%= render :partial => category.children %> </ul> </li>
이 레일 2.3 코드입니다. 당신은 경로를 호출하여 명시 적으로 그 전에 부분의 이름을 지정해야합니다.
-
==============================
5._tree.html.eb
_tree.html.eb
@set = Category.root.self_and_descendants <%= render :partial => 'item', :object => @set[0] %>
_item.html.erb
<% @set.shift %> <li><%= item.name %> <% unless item.leaf? %> <ul> <%= render :partial => 'item', :collection => @set.select{|i| i.parent_id == item.id} %> </ul> <% end %> </li>
당신은 또한 자신을 정렬 할 수 있습니다 :
<%= render :partial => 'item', :collection => @set.select{|i| i.parent_id == item.id}.sort_by(&:name) %>
하지만 경우에 당신은이 줄을 제거해야합니다 :
<% @set.shift %>
-
==============================
6.나는 때문에 그것을 위해 작성되었습니다 루비의 이전 버전의 허용 대답을 작동시킬 수 없습니다, 나는 가정한다. 다음은 나를 위해 일하는 솔루션입니다 :
나는 때문에 그것을 위해 작성되었습니다 루비의 이전 버전의 허용 대답을 작동시킬 수 없습니다, 나는 가정한다. 다음은 나를 위해 일하는 솔루션입니다 :
def tree_from_set(set) buf = '' depth = -1 set.each do |node| if node.depth > depth buf << "<ul><li>#{node.title}" else buf << "</li></ul>" * (depth - node.depth) buf << "</li><li>#{node.title}" end depth = node.depth end buf << "</li></ul>" * (depth + 1) buf.html_safe end
그것은 선택적인 깊이 정보를 이용하여 간단합니다. (이 방법의 장점은 잎의 전체 구조로 설정 입력에 대한 필요가 없다는 것입니다.)
깊이없이 더 복잡한 솔루션은 보석의 GitHub의 위키에서 찾을 수 있습니다 :
https://github.com/collectiveidea/awesome_nested_set/wiki/How-to-generate-nested-unordered-list-tags-with-one-DB-hit
-
==============================
7.어쩌면 조금 늦게하지만 난 closure_tree 보석 중첩 hash_tree 방법에 따라 awesome_nested_set에 대한 내 솔루션을 공유하고 싶습니다 :
어쩌면 조금 늦게하지만 난 closure_tree 보석 중첩 hash_tree 방법에 따라 awesome_nested_set에 대한 내 솔루션을 공유하고 싶습니다 :
def build_hash_tree(tree_scope) tree = ActiveSupport::OrderedHash.new id_to_hash = {} tree_scope.each do |ea| h = id_to_hash[ea.id] = ActiveSupport::OrderedHash.new (id_to_hash[ea.parent_id] || tree)[ea] = h end tree end
LFT으로 주문한 범위와이 의지 작업
사용 도우미보다 그것을 렌더링합니다 :
def render_hash_tree(tree) content_tag :ul do tree.each_pair do |node, children| content = node.name content += render_hash_tree(children) if children.any? concat content_tag(:li, content.html_safe) end end end
업데이트 : (- node.lft - 1 node.rgt) / 2 NUMBER_OF_CHILDREN =이 더욱 SQL 쿼리없이 트리의 특정 노드에 대한 아이들의 수를 계산하는 것이 가능하다는 것을 알아 냈다. 이 문제가 해결되지 않고 도움이 될 증명할 수 있습니다.
해결법
from https://stackoverflow.com/questions/1372366/how-to-render-all-records-from-a-nested-set-into-a-real-html-tree by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 약한 개체에 대한 데이터베이스 모델링 (0) | 2020.07.04 |
---|---|
[SQL] 카테고리의 큰 불확정 번호 교차 (0) | 2020.07.04 |
[SQL] 엔티티 프레임 워크는 2100 매개 변수 제한을 명중 (0) | 2020.07.04 |
[SQL] SQL에서 선택 특정 행 번호 [중복] (0) | 2020.07.04 |
[SQL] C #는 SQL 매개 변수 속기 (0) | 2020.07.04 |