How can i use accepts nested attributes with the HABTM?
M

1

5

I have two models User and Category.

    class User < ActiveRecord::Base
        has_and_belongs_to_many :categories
        accepts_nested_attributes_for :categories
    end

similarly

    class Category < ActiveRecord::Base
        has_and_belongs_to_many :users
    end

i have a requirement where i have to add the categories to the categories table and add the reference so that i can get the categories related to user but if another user enters the same category then i have to make use of the id instead of creating new one. How can i do it?

And one more thing is i have to add an attribute type which refers that category type. for example

user1 ----> category1, category2
user2 ----> category2

here user1 and user2 has category2 but the type in category2 may differ.So how can i maintain this? please help me. I am ready to answer your question.

Macomber answered 2/9, 2013 at 14:1 Comment(2)
Category has_and_belongs_to_many :users not categories, right? Also, what you want to do with this type. I don't get it....Baresark
Thanks. I have changed and i need to have type field which says the user has category2 with type "type1" and user2 has same category2 with type "type2". where should i keep the type field. If i have type field in join table how can i add the entry and get that information?Macomber
B
10

You must use has_many :through instead of HABTM to add the field type to the relationship:

class User < ActiveRecord::Base
  has_many :lines
  accepts_nested_attributes_for :lines
  has_many :categories, through: :lines
end

class Line < ActiveRecord::Base
  belongs_to :users
  belongs_to :category
end

class Category < ActiveRecord::Base
  has_many :lines
  has_many :users, through: :lines
end

Add the type attribute to the class Line.

ref: http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

You will need two controllers with the restful actions: users and categories

Then, in your user form, something like:

<%= nested_form_for @user do |f| %>
...#user attributes
<%= f.fields_for :lines do |line| %>
<%= line.label :category %>
<%= line.collection_select(:category_id, Category.all, :id, :name , {include_blank: 'Select Category'} ) %>
<%= line.label :type %>
<%= line.text_field :type %>
...#the form continues

EDIT -

The category is independent of user, as well as user is independent of category.

The association class Line will join users and categories through the category_id and user_id:

________          _______________
| user |          |     line    |          ____________
|----- |          |-------------|          | category |
| id   |----------| user_id     |          |----------|
| name |1        *| category_id |----------| id       |
| email|          | type        |*        1| name     | 
|______|          |_____________|          |__________|

example:

git hub: https://github.com/gabrielhilal/nested_form

heroku: http://nestedform.herokuapp.com/

Baresark answered 2/9, 2013 at 14:50 Comment(4)
If i use accepts_nested_attributes_for :lines then how would the category information be stored in category table. It is bit unclear for me. Could you please explain more.Macomber
Also tell me if another user enters a new value to categories it should check if the category is present already and it should just add the id of the category along with type.Macomber
It took some time for me to understand. Anyway thank you and one small correction which is the join table model should have belongs_to :user and belongs_to :category.Macomber
sorry for the mistake, but the code is right in the repository I gave u: github.com/gabrielhilal/nested_form/blob/master/app/models/… please accept the answer if it answered your question.Baresark

© 2022 - 2024 — McMap. All rights reserved.