A subcategory is always a child of a category. Lets set up your associations
as such. It will use only one db column instead of two. Each item will belong
to a subcategory; each subcategory will belong to a category. It will look
something like this:
Category
/ \
Subcategories
/ | \
Items Items Items
We will use ActiveRecord''s :through association. Your models will look
like
this:
Class Category
has_many :subcategories
has_many :items, :through => :subcategory
Class Subcategory
has_many :items
Class Item
belongs_to :subcategory
When you do this, Category will associate with an Item by tunneling through
Subcategory. These helpful methods will now be available:
Item.category
Item.subcategory
Subcategory.category
Category.items
Category.subcategories
Subcategory.items
Now, we need to do your drop down list (called a "select" in Rails)
magic. I''m
not much of a Javascript buff, so this is a dirty little hack that *should*
work. The idea is to have the "subcategory" select contained in a DIV.
The
contents on the DIV will originate from an action that only deals with
creating that select, likewise it will render a partial containing only the
select''s markup. We''ll have an observer watch the
"category" select, and send
whatever it changes to to the "subcategory" select handler, which will
in
turn re-render the select with the appropriate contents. Your controller,
model, view, and partial should look like this:
Item Controller:
def subcategory_handler
@subcategories = Category.find(params[:category_id]).subcategories
render :partial => "subcat_select", :locals => {:s =>
@subcategories}
end
### put this in the method "new":
@category = Category.find :all
@subcategories = @category[0].subcategories
Item model:
### add this virtual attribute, so that we don''t get NoMethod errors:
attr_accessor :category_id
Partial _subcat_select.html.erb
<%= select "item", "subcategory_id", s.collect {|s| [
s.name, s.id ] } -%>
View for Item#new:
(I assume that the values in your select options are the category and
subcategory IDs.)
<label>Category</label>
<%= select "item", "category_id", @category.collect
{|c| [ c.name,
c.id ] }, { }, { :id => "category" } -%>
...
<label>Subcategory</label>
<div id="subcategory_container">
<%= render :partial => "subcat_select", :locals =>
{:s =>
@subcategories} -%>
</div>
...
(This must be called AFTER your select fields are defined!)
<%= observe_field :category, :url => { :action
=> :subcategory_handler }, :with => :category_id, :update
=> "subcategory_container" %>
That''s a pretty rough hack, but I tested it on Rails 2.1.0 and it
works. It''ll
take some fine tuning on your part. There might be a completely different way
of handling such a thing, this is only one option to explore.
Hope it makes sense.
On Thursday 16 October 2008 22:34:57 Daniel wrote:> Now I have 3 models, item category and sub-category
> and 3 Tables in my database.
>
> I planed to set the association like this.
>
> Item
> Belongs_to :category
> Belongs_to :sub-category
>
> category
> Has_many :items
> Has_many :sub_category
>
> sub_category
> belongs_to :category
> Has_many :items
>
> And now I want to have some dynamic drop down list in the items/new
> page
> When I chose one category, and the sub-category will dynamically
> updated.
> what other move do I need?
>
> Is that right? It makes me feel confused with these associations.
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---