I''m at the stage in learning Rails (and Ruby) where everything seems disorienting and awkward. My first self-assigned project is a links manager. I have a Topic model and a Link model. Topic is defined as acts_as_tree, while Link is acts_as_list. I have three tables in a database that I think make sense - one is a join table which I will use for links. But I haven''t even gotten to that point yet. A topic can be a parent to other topics or to links, so there are a number of parent/child relationships going on. I figured the way to assign a parent to a new topic or a new link would be with check boxes. Dealing first with topics, when one creates a new Topic one would be presented with a bunch of checkboxes, one for each existing topic. Checking a checkbox assigns that topic as the parent to the newly created topic. (Haven''t even gotten to links yet, but same idea). There is a "parent_id" column in the topics table. I want to populate that with the topic id of the checked checkbox. I have been scratching my head trying to figure out how to write the check_box form helper in the "create" and "modify" _form partials, and how to extract the value in the TopicAdmin controller. In the Topic _form.rhtml partial I have: <% for topic in @topics %> <li><%= topic.id %> <%= check_box("topic", "parent_id", {}, topic.id, "0") %> <%= topic.topic_title %> </li> <% end %> (I have defined @topics in the controller as Topic.find_all. I''ve got zero as the value for nothing checked, as some topics will be top level with no parents.) Now I don''t know if that''s the right syntax for the check_box helper, and if it is I can''t figure out how the controller extracts the value and puts it into the parent_id attribute of the topics table. The check boxes show up. They appear to carry their id correctly. I''m just not succeeding in getting those values inserted into the database table. Thank you in advance for any suggestions. -- Posted via http://www.ruby-forum.com/.
Try, <% @topics.each do |t| %> <%= check_box_tag ''link[topic_ids][]'', t.id, @link.topics.include?(t) %> <%= t.name %><br/> <% end %> Have you checked out this tutorial?: http://wiki.rubyonrails.com/rails/pages/CheckboxHABTM -Steven snlsn wrote:> I''m at the stage in learning Rails (and Ruby) where everything seems > disorienting and awkward. > > My first self-assigned project is a links manager. I have a Topic model > and a Link model. Topic is defined as acts_as_tree, while Link is > acts_as_list. I have three tables in a database that I think make sense > - one is a join table which I will use for links. But I haven''t even > gotten to that point yet. > > A topic can be a parent to other topics or to links, so there are a > number of parent/child relationships going on. I figured the way to > assign a parent to a new topic or a new link would be with check boxes. > Dealing first with topics, when one creates a new Topic one would be > presented with a bunch of checkboxes, one for each existing topic. > Checking a checkbox assigns that topic as the parent to the newly > created topic. (Haven''t even gotten to links yet, but same idea). > > There is a "parent_id" column in the topics table. I want to populate > that with the topic id of the checked checkbox. > > I have been scratching my head trying to figure out how to write the > check_box form helper in the "create" and "modify" _form partials, and > how to extract the value in the TopicAdmin controller. > > In the Topic _form.rhtml partial I have: > > <% for topic in @topics %> > <li><%= topic.id %> > <%= check_box("topic", "parent_id", {}, topic.id, "0") %> > <%= topic.topic_title %> > </li> > <% end %> > > (I have defined @topics in the controller as Topic.find_all. I''ve got > zero as the value for nothing checked, as some topics will be top level > with no parents.) > > Now I don''t know if that''s the right syntax for the check_box helper, > and if it is I can''t figure out how the controller extracts the value > and puts it into the parent_id attribute of the topics table. > > The check boxes show up. They appear to carry their id correctly. I''m > just not succeeding in getting those values inserted into the database > table. > > Thank you in advance for any suggestions.-- Posted via http://www.ruby-forum.com/.
Try, <% @topics.each do |t| %> <%= check_box_tag ''link[topic_ids][]'', t.id, @link.topics.include?(t) %> <%= t.name %><br/> <% end %> Have you checked out this tutorial?: http://wiki.rubyonrails.com/rails/pages/CheckboxHABTM -Steven -- Posted via http://www.ruby-forum.com/.
rooster; Thanks a million. I have read you code 6 times and it makes my head hurt so it MUST be good! Maybe on the 7th read it will make sense. And no. For all the googling I did I missed that wiki article. I will read it immediately. Thanks again. -- Posted via http://www.ruby-forum.com/.
Okay - I''m not getting anywhere. The example rooster provided and the link he pointed me to both assume I want to add the topic id to the link table. I''m not there yet. I''m working at a self referential join. I want to establish a link from one topic to another topic. I want to make one topic a child of another topic. I''ve got this code in my _form partial: <ul> <% Topic.find(:all).each do |t| %> <li><input type="checkbox" name="topic[parent_id][]" value="<%= t.id %>" /> <%= t.topic_title %></li> <% end %> </ul> Checkboxes show up okay but they aren''t writing the correct value to the parent_id field in the topics table. It appears I get a "0" if no checkbox is checked, and "1" if any checkbox is checked: in other words it appears the default value of the checkbox is being written tot he parent_id field, NOT the topic.id value I want. Is this a problem with how I have the model set up? Or with how I have the checkbox set up? The Topic class so far just has: class Topic < ActiveRecord::Base has_and_belongs_to_many :topics has_many :links, :order => "parent_id, topic_title" end Thanks for any thoughts. -- Posted via http://www.ruby-forum.com/.
Looks like you have your model definition mixed up. You need something like this: class Topic < ActiveRecord::Base belongs_to :parent_topic, :class_name => ''Topic'', :foreign_key => ''parent_id'' has_many :child_topics, :class_name => ''Topic'', :foreign_key => ''id'' end I''m assuming your topics table is defined as follows: ----------- topics | ----------| id | parent_id | ----------- I don''t have much experience doing self referential joins, and I''m not positive the above model definition is correct. The Agile Web Development w/Rails book has some good info on this. Maybe some other rubyists can verify if the above model definition is correct of a self referential join. There is more info on this here: http://wiki.rubyonrails.com/rails/pages/HowToCreateASelfReferentialManyToManyRelationship however the examples use a separate join table and it looks like you initially just want to get your thing working with the topics table. -- Posted via http://www.ruby-forum.com/.
Once again I thank you so much for your interest in this. I had a sneaky feeling the Topic model was wrong but nothing I tried fixed it. I have scoured the Agile Web book (the covers are about to fall off!), but Dave''s demonstration adds his Employee/manager/mentor data straight through code not dynamically with checkboxes and I just couldn''t reconcile the two. And I did just tonight read the SelfReferential wiki entry you mention. I considered that approach (since he documented it so well there and in the sitepoint message board) but I''m planning to use a join table to hook up links with topics (if I ever get that far...) and though it would get too awkward with two join tables flying around. Especially since Dave implied a single table self reference could be done. So I''ll give your suggestion a shot and see what new potholes I fall into. BTW - the topics table is set up like this: +-------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+---------+----------------+ | id | int(11) | | PRI | NULL | auto_increment | | parent_id | int(11) | | | 0 | | | topic_title | varchar(50) | | | | | | topic_descr | varchar(250) | | | | | +-------------+--------------+------+-----+---------+----------------+ Thanks again! -- Posted via http://www.ruby-forum.com/.
Actually - I did have the belongs_to part pretty much just as you have it, but I didn''t have the has_many part. Maybe that''s the secret. -- Posted via http://www.ruby-forum.com/.
Ok, I got it working, do: ''ruby script/generate scaffold Topic Topic'' using your topic DDL Use the below for _form.rhtml, show.rhtml, topic.rb ##### _form.rhtml <%= error_messages_for ''topic'' %> <!--[form:topic]--> <p><label for="topic_name">Name</label><br/> <%= text_field ''topic'', ''name'' %></p> <p><label>children topics</label><br/> <% Topic.find(:all).each do |t| %> <%= check_box_tag ''topic[child_topic_ids][]'', t.id, @topic.child_topics.include?(t) %> <%= t.name %><br/> <% end %> </p> <!--[eoform:topic]--> ##### ##### show.rhtml <% for column in Topic.content_columns %> <p> <b><%= column.human_name %>:</b> <%=h @topic.send(column.name) %> </p> <p> <b>Child Topics:</b><br/> <% @topic.child_topics.each do |ct| %> <%= ct.name %><br/> <% end %> </p> <% end %> <%= link_to ''Edit'', :action => ''edit'', :id => @topic %> | <%= link_to ''Back'', :action => ''list'' %> ##### ##### topic.rb class Topic < ActiveRecord::Base validates_uniqueness_of :name belongs_to :parent_topic, :class_name => ''Topic'', :foreign_key => ''parent_id'' has_many :child_topics, :class_name => ''Topic'', :foreign_key => ''parent_id'' end #### some things to note.... when you define the ''has_many'' in the model, rails automatically creates a method to get the associated ids. Example: class f < ActiveRecord::Base has_many :table1 end class f will now have a method called ''table1_ids'' to retrieve an array of ids on the has_many side of the relationship.....this is just part of the rails magic :) However, with the self referential join thing, we did some extra stuff like defining :child_topics so now the method that rails creates is ''child_topic_ids''....notice how in _form.rhtml I call ''topic[child_topic_ids][]'', then rails figures it out from there. Actually, the way I have it set up is more along the lines of associating child topics with an already existing topic. How is your UI flow working? [new topic]->[show list of topics]->[associate child topics] something like that? -- Posted via http://www.ruby-forum.com/.
rooster: Thank you SO MUCH! What an awesome surprise to find this morning. Haven''t had time to try it yet but I most especially appreciate the background you gave on the methods Rails builds automatically. Extremely helpful to me at this stage. Thanks again - I will most likely be back with more questions. Oh - quick answer to the UI flow. Your outline is pretty much it so far. I need to establish categories (topics) before I can begin adding links since the links will all be in categories. And the "public" will never see this end - this is strictly admin for me. Ultimately the public will see categories and their links but not be allowed to manipulate them. Anyway, in the TopicsAdmin one clicks "new topic", goes to a form with input areas for topic title (short text) and topic description (slightly longer text), and then all the checkboxes, one for each topic existing in the database. This is where the parent assignment occurs. I anticipate a similar structure for links with the addition of a URL field. In that case I did plan to use a join table and in that case one link can be assigned to many parents, so I expect it might get a bit tricky there. But thanks again for your involvement in this and I''ll let you know what happens when I try putting this code into mine. Steve -- Posted via http://www.ruby-forum.com/.
Sigh. It''s probably pretty obvious I have a "day job" and can only hack away at Ruby in the evenings, huh? :( Okay, turns out the code rooster gave me was effective but for the wrong thing. It allowed me to assign *children* to the newly created topic, but my intention was to establish the *parent* of the new topic. I can''t see any other way to do it in the beginning - you need to start the tree somewhere and you can''t assign children before there are any parents! So. I almost got it. In the _form partial I now have: <ul> <% Topic.find(:all).each do |t| %> <li> <%= check_box_tag ''topic[parent_id]'', t.id %><%= t.topic_title %> <% end %> </li> </ul> This works to write the id of the topic represented by a checked checkbox into the new topic''s "parent_id" field. Yeah! I say "almost" because I still can''t get the last argument in the form helper (the one that knows to put the check in the proper box when you edit a topic), and the children of a topic don''t show up in the "show" action. In "show.rhtml" I''ve got: <p>Topic Children:<br /> <% @topic.child_topics.each do |ct|%> <%= ct.topic_title %> <% end %> </p> but what displays is the topic itself, not the topics that have the current topic''s id in their "parent_id" field. What should I be telling you folk besides what I have to make it easier to pinpoint what I''d doing wrong? Argh. So - how do you know the stuff you wrote about the "methods that Rails creates"? Do you just know it from experience? Do you scour the api doc? Is there any means of looking somewhere in your Rails project to find the methods, ALL the methods including those generated, hand created AND automatically created? Being new to Rails (and Ruby) it''s making me absolutely crazy not knowing how to do diagnostics, to find out what variable is getting *really* getting passed, what method is being called. I''m sure the tools are in there but I don''t know where to look for them, how to employ them. Thanks. -- Posted via http://www.ruby-forum.com/.
I know how you feel about rails. It kicks ass but a lot intricate things are not well documented. Well, compared to some of the php crap I''ve used, it has tons of documentation! Anyhoo, I found out about those autogenerated methods in the rails wiki. This article: http://wiki.rubyonrails.com/rails/pages/CheckboxHABTM The wiki is actually loaded with great info. It''s just not organized so well. I usually spend a couple of hours a week reading through stuff on the wiki....reading things twice doesn''t hurt either ;) Well I think I got your situation solved: #### _form.rhtml <%= error_messages_for ''topic'' %> <!--[form:topic]--> <p><label for="topic_name">Name</label><br/> <%= text_field ''topic'', ''name'' %></p> <p><label>parent topics</label><br/> <% Topic.find(:all).each do |t| %> <%= check_box_tag ''topic[parent_id]'', t.id, @topic.parent_topic.eql?(t) %> <%= t.name %><br/> <% end %> </p> <!--[eoform:topic]--> #### #### show.rhtml <% for column in Topic.content_columns %> <p> <b><%= column.human_name %>:</b> <%=h @topic.send(column.name) %> </p> <p> <b>Parent Topic:</b> <%= @topic.parent_topic.name unless @topic.parent_topic.nil?%><br/><br/> <b>Child Topics:</b><br/> <% @topic.child_topics.each do |ct| %> <%= ct.name %><br/> <% end %> </p> <% end %> <%= link_to ''Edit'', :action => ''edit'', :id => @topic %> | <%= link_to ''Back'', :action => ''list'' %> #### #### topic.rb class Topic < ActiveRecord::Base validates_uniqueness_of :name belongs_to :parent_topic, :class_name => ''Topic'', :foreign_key => ''parent_id'' has_many :child_topics, :class_name => ''Topic'', :foreign_key => ''parent_id'' end #### Does this accomplish what you were shooting for? -Steven -- Posted via http://www.ruby-forum.com/.
rooster; This finally seems to work just right. THANKS! Boy, I was pecking away at every lame thing I could think of (empty? blank?) but I don;t think I would have ever stumbled onto eql? (Is that a streamlined if x == y sort of conditional?) I don''t "get" why Parent_id works as the has_many foreign key, but presumably that will sink in after a bit. So - I will start scouring the wiki. Thanks for that tip, and thanks for your interest and tenacity working this out. Now on to the next hurdle. Steve -- Posted via http://www.ruby-forum.com/.