Drzewo Kategorii Acts as tree for Rails 3 - Problem

Witam!
Chcialem stworzyc drzewo kategori. jak tutaj https://github.com/kristianmandrup/acts_as_tree_rails3
Mam Tabele Categories

create_table "categories", :force => true do |t|
    t.string   "title"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "parent_id"

W instrukcji napisane jest
Add ActAsTree to the model

app/models/category.rb

class Category “name”
end
Moj model wyglada tak

class Category < ActiveRecord::Base
has_many :ads
ActAsTree
validates :title, :presence => true
end

Ale wydaje mi sie ze cos jest nie tak bo dalej jak dodam do seed.rb to co jest w instrukcji wywala blad przy rake db:seed uninitialized constant Category::ActAsTree

Chcialbym wyswietlic Katoegorie w drzewie moze jest jakis inny lepszy sposob? Probowalem tez
http://railscasts.com/episodes/162-tree-based-navigation
Ale po wydaniu komendy rails plugin install git://github.com/rails/acts_as_tree.git Wyglada jakby instalacja nie zostala przeprowadzona. Dodaje potem acts_as_tree do category.rb i znow wywala blad.
Jakies wskazowki?

And boom. https://github.com/stefankroes/ancestry

Polecam: https://www.ruby-toolbox.com/search?utf8=✓&q=tree

Dzieki za odp!
Zainstalowalem Ancestry, Moj _form wyglada tak:

<%= form_for(@category) do |f| %>
  <% if @category.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@category.errors.count, "error") %> prohibited this category from being saved:</h2>

      <ul>
      <% @category.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </div>
	<div class="field">
	<%= f.label :ancestry %><br />
  <%= f.collection_select :ancestry, Category.all(:order => "title"), :id, :title, :include_blank => true %>
	</div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Moj index wyglada tak:

<ul id="menu">
  <% for category in @categories %>
    <li><%= link_to h(category.title), category %>
			<%= link_to "subcategory", new_category_path(:parent_id => category) %> |
      <%= link_to "Destroy", category, :confirm => "Are you sure?", :method => :delete %>
			<%= link_to 'Show', category %>
</li>
 			
  <% end %>
</ul>

Pierwsza podkategorie tworze bez problemow klikajac w link_to subcategory natomiast gdy chce dodac podkategorie do podkategorii gdy klikam w ten sam link nie wybiera mi automatyczne kategoii. Czy to dla tego ze ta kategoria nie moze byc rodzicem poniewaz ma juz rodzica? Jak w takim razie dodac kolejna podkategorie?

Udalo mi sie wyswietlic drzewo kategorii ale tylko pierwsze dwa poziomy.
Wyswietlam roots i children w taki sposob:

<ul id="menu">
  <% Category.roots.each do |category| %>
     <li> <%= link_to h(category.title), category %> (<%= category.ads.count %>)
				<% unless category.children.empty? %>
           <ul id="sub-menu"> 
             <% category.children.each do |subcategory| %>
                <li><%= link_to h(subcategory.title), subcategory %></li>
             <% end %>
           </ul>
        <% end %>
     </li>
  <% end %>
</ul>

Czy aby stworzyc kolejny poziom “Poziom2” czyli
PoziomRoot

  • Poziom1
    – Poziom2
    Moge stworzyc kolejna kategorie wybierajac parent jako Poziom1 ? Jesli tak to w jaki sposob zmodyfikowac widok aby pokazywal ten “Poziom2” ?

W Rails 3 nie musisz używać h helpera w link_to, jest on automatycznie dodawany (jak chcesz wyświetlić nie wyescapowanego korzystasz z raw).

@topic
Nie znam tego gemu, ale widzę, że możesz tworzyć tyle dzieci ile chcesz najprościej korzystając z node.children.create :name => 'Stinky'
.

musisz rekurencyjnie pobierać kolejne poziomy, tutaj masz railscast z przykładowym helperem - http://railscasts.com/episodes/262-trees-with-ancestry

Jeżeli chcesz wyświetlić pełne drzewo, niezależnie od tego ile toto ma poziomów, najłatwiej chyba zdefiniować rekurencyjną funkcję - albo jako metodę modelu, albo jako metodę w helperze widoku.

Może coś w ten deseń?:

[code=ruby]def deep_list_of_categories(category)
rc = “

  • ”.html_safe + category_list_item(category)
    if ! category.children.empty?
    rc += “
      ”.html_safe + category.children.map {|kid| deep_list_of_categories(kid) }.join + “
    ”.html_safe
    end
    rc + “
  • ”.html_safe
    end

    def category_list_item(category)
    link_to( h(category.title), category ) + " (#{category.ads.count})"
    end[/code]
    Nie testowałem, nie sprawdzałem, pisałem z niczego, czyli z głowy. Ale idea powinna być widoczna.

    Aha - nie używaj id w podliście - id w obrębie dokumentu HTML ma być unikalne. Albo użyj klasy (pewnie tego właśnie chciałeś użyć) albo budując HTML-owe ID użyj np. id modelu:

    [code]


      …lub…
        [/code]

    Dzieki!
    Wyglada na to ze mam gdzies blad w kodzie. Po stworzeniu kolejnego poziomu nie jest on widoczny.
    Dokladniej i z przykladem
    Mam PoziomRoot tworze Podkategoria1 jest ok. Tworze kolejna kategorie i wybieram parent_id jako Podkategoria1 i nazwe jako Podkategoria2.
    W akcji show chce wyswietlic

    <% unless @category.children.empty? %> <ul id="sub-menu"> <% @category.children.each do |subcategory| %> <p>Dzieci: <%= subcategory.title %></p> <% end %> </ul> <% end %> Jak jestem w PoziomRoot wyswietla dzieci jako Podkategoria1. Jak jestm w Podkategoria1 nie wyswietla dzieci.

    W categories_controller.rb

    ... def new @category = Category.new(:parent_id => params[:parent_id]) ...
    Wyglada to jakbym okreslal ze dla Podkat.2 rodzicem jest Podkat1 ale Podkat2 nie koniecznie jest dzieckiem Podkat.1. Dziwne czy tak ma byc?

    w bazie wszystko zapisuje się ok? tzn parent_id w Podkat2 rzeczywiście wskazuje na Podkat1 i jak zrobisz

    Category.find_by_name('Podkat2').parent

    to zwraca Podkat1?

    btw. od unless #blank? czytelniejsze będzie if #present? tzn

    [code=ruby]<% if @category.children.present? %>

    <% end %>[/code]

    W bazie wyglada na to ze jest ok. Zapisuje rodzica i moge go wyswietlic problem jest gdy chce wyswietlic dzieci.

    Zaraz… Pokazałeś akcję :new, a nie :create. Jeżeli utworzyłeś @category, to przecież ona nie ma żadnych dzieci. Czy na pewno wyświetlasz dobry obiekt? Czy jesteś pewny, że wyświetlany obiekt MA dzieci? Twierdzisz, że w bazie wszystko jest OK, ale sprawdź, czy gdzieś nie ma jakiejś literówki, czy w konsoli rzeczywiście relacje działają w obie strony - a.children.first.parent == a itp. Gdzieś musisz pewnie mieć jakiś źle postawiony przecinek…

    Sorry, za takie insynuacje, ale kiedy rzeczy zaczynają być dziwne, trzeba zacząć sprawdzać od tego co wydaje się oczywiste - czy włożyłem wtyczkę do prądu?

    W akcji show dodalem pare rzeczy aby sprawdzic czy poprawnie sie zapisuje w bazie oto kod

    <p id="notice"><%= notice %></p>
    <p>
     <% if @category.parent %>
    <b>Parent Category: </b>
    <%= @category.parent.title %><br />
    <% end %>
     <b>Category name:</b>
      <%= @category.title %>
    </p>
     <% if @category.children.present? %>
               <ul id="sub-menu"> 
                 <% @category.children.each do |subcategory| %>
                  <p>Dzieci: <%= subcategory.title %></p>
                 <% end %>
               </ul>
            <% end %>
    <%= @category.descendants.count %><br />
    <%= display_tree @category %>
    
    <%= link_to 'Edit', edit_category_path(@category) %> |
    <%= link_to 'Back', categories_path %>

    Oto zrzut ekranu kategorii

    Nastepnie w akcji show pokazuje podkategorie Laptops

    Kategoria nr 17 ktora jest dzieckiem Netbooks nie jest wyswietlana gdy wejde w show

    A gdy otworze Owa kategorie 17 pokazuje ze Netbooks jest rodzicem

    def create
        @category = Category.new(params[:category])
    
        respond_to do |format|
          if @category.save
            format.html { redirect_to @category, :notice => 'Category was successfully created.' }
            format.json { render :json => @category, :status => :created, :location => @category }
          else
            format.html { render :action => "new" }
            format.json { render :json => @category.errors, :status => :unprocessable_entity }
          end
        end
      end
    

    Pewnie gdzies jest maly blad ale gdzie.
    Na poczatku podkategoria miala byc tworzona w taki sposob

    <%= link_to "Create Subcategory", new_category_path(:parent_id => category) %> |
          <%= link_to "Destroy", category, :confirm => "Are you sure?", :method => :delete %>

    Pozniej to usunalem i zapomnialem. Ale juz z tym kodem w momencie tworzenia poziomu 2 nie wybieralo za pomoca id automatycznie kategorii rodzica. Dzialo sie tak tylko na etapie pierwszej podkategorii. Tak wyglada form

    <%= form_for(@category) do |f| %>
      <% if @category.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@category.errors.count, "error") %> prohibited this category from being saved:</h2>
    
          <ul>
          <% @category.errors.full_messages.each do |msg| %>
            <li><%= msg %></li>
          <% end %>
          </ul>
        </div>
      <% end %>
    
      <div class="field">
        <%= f.label :title %><br />
        <%= f.text_field :title %>
      </div>
    	<div class="field">
    	<%= f.label :ancestry %><br />
      <%= f.collection_select :ancestry, Category.all(:order => "title"), :id, :title, :include_blank => true %>
    	</div>
      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>

    Udalo mi sie rozwiac problem.
    Problem byl w pliku _form.html.erb
    Bylo tak

    <div class="field">
    <%= f.label :ancestry %><br />
    <%= f.collection_select :ancestry, Category.all(:order => "title"), :id, :title, :include_blank => true %>
    </div>

    Zmienilem na

    	<%= f.label :ancestry %><br />
      <%= f.collection_select :parent_id, Category.all(:order => "title"), :id, :title, :include_blank => true %>
    	</div>

    W bazie mialem ancestry gdzie zapisywane byly id rodzicow.
    Root(id=3)
    -Poziom1(id=5)
    –Poziom2(id=6)

    W momencie gdy chcialem stworzyc Poziom2 ustawialem rodzica jako Poziom1 a w bazie zapisywal tylko id Poziom1 a powinien rowiez Root. Po zmianie w bazie zapisywane sa oba id oddzielone “/” Wyglada to tak Poziom2 anestry = 3/5
    Dziekuje za wszelkie proby pomocy i pozdrawiam!