Forum: Ruby on Rails How to deal with these 3 model's association?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
3949b43a989430f9959e816e105cbbcc?d=identicon&s=25 Jette Chan (jette)
on 2008-10-17 05:35
(Received via mailing list)
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.
C5c0e0499446b84fd3bcc61cf7862539?d=identicon&s=25 Thani Ararsu (thaniyarasu)
on 2008-10-17 06:56
Jette Chan 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.



category.rb
has_many :sub_categories
has_many :items ,:through=>:sub_categories

sub_category.rb
belongs_to :category
has_many :items

item.rb
belongs_to :sub_category


by use of this association you can define get any of 2 by select of any
of 1 among three models

for that use Ajax Updater
84b661cb6bd8a870c1787968ee945962?d=identicon&s=25 Patrick Sullivan (ywp)
on 2008-10-17 10:02
(Received via mailing list)
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.
This topic is locked and can not be replied to.