Rails Nested Form

Hi everyone,

I have followed the tutorial given by Ryan at #196 Nested Model Form Part 1 - RailsCasts and it works great. However it doesn't do what I need and not sure if its a concept issues or I might need to change my models.

The models I have his

- Customer - Book, and - BookManager

Here are the relationship Customer     has_many :book_managers   accepts_nested_attributes_for :book_managers, allow_destroy: :true BookManager   attr_accessible :customer_id, :visible, :books_attributes   belongs_to :customer   has_many :books   accepts_nested_attributes_for :books, allow_destroy: :true Book   belongs_to :book_manager   attr_accessible :book_manager_id, :description

Here a diagram

-------------|1---------*|-------------|*---------1|-------------| Customer | | BookManager | | Book | -------------| |-------------| |-------------| ID | | ID | | ID | First | | customer_id | | Description | Last | | book_id | |-------------| Email | | isVisible | Password | | isDeleted | -------------| |-------------|

So what I am trying to do is when a customer goes into customer#edit then a form show up. But unlike the tutorial it doesn't create a new customer but a new bookmanager and keep the integrity and also create a new book. That his my problem, not sure how to do it and thank you. Here my customerController and when clicking the button it does say no BookManager controller but not sure how to approach it at the moment.

CustomerController   @book_manager = BookManager.new   @book_manager.books.build #Need to associate it with customer #Need to generate some control of bookManager because of BookManager.new

Hi everyone,

I have followed the tutorial given by Ryan at #196 Nested Model Form Part 1 - RailsCasts and it works great. However it doesn't do what I need and not sure if its a concept issues or I might need to change my models.

The models I have his

- Customer - Book, and - BookManager

Here are the relationship Customer     has_many :book_managers   accepts_nested_attributes_for :book_managers, allow_destroy: :true BookManager   attr_accessible :customer_id, :visible, :books_attributes   belongs_to :customer   has_many :books   accepts_nested_attributes_for :books, allow_destroy: :true Book   belongs_to :book_manager   attr_accessible :book_manager_id, :description

Here a diagram

>-------------|1---------*|-------------|*---------1|-------------| > Customer | | BookManager | | Book | >-------------| |-------------| |-------------| > ID | | ID | | ID | > First | | customer_id | | Description | > Last | | book_id | |-------------| > Email | | isVisible | > Password | | isDeleted | >-------------| |-------------|

You said above BookManager has many books and Book belongs_to book manager. In that case book manager should not have book_id, it is book that should have a book_manager_id. Though I suspect it is the model definitions that are wrong.

Colin

Colin Law wrote in post #1071797:

- Book, and   accepts_nested_attributes_for :books, allow_destroy: :true > First | | customer_id | | Description | > Last | | book_id | |-------------| > Email | | isVisible | > Password | | isDeleted | >-------------| |-------------|

You said above BookManager has many books and Book belongs_to book manager. In that case book manager should not have book_id, it is book that should have a book_manager_id. Though I suspect it is the model definitions that are wrong.

Colin

My bad yeah I must of not seen it when writing it

-------------|1---------*|-------------|*---------1|-----------------| Customer | | BookManager | | Book | -------------| |-------------| |-----------------| ID | | ID | | ID | First | | customer_id | | book_manager_id | Last | | isDeleted | | Description | Email | | isVisible | |-----------------| Password | |-------------| -------------|

The issue remains the same, how can i create a new instance from an other bookmanager, is it doable in ruby?

Colin Law wrote in post #1071797:

- Book, and accepts_nested_attributes_for :books, allow_destroy: :true > First | | customer_id | | Description | > Last | | book_id | |-------------| > Email | | isVisible | > Password | | isDeleted | >-------------| |-------------|

You said above BookManager has many books and Book belongs_to book manager. In that case book manager should not have book_id, it is book that should have a book_manager_id. Though I suspect it is the model definitions that are wrong.

Colin

My bad yeah I must of not seen it when writing it >-------------|1---------*|-------------|*---------1|-----------------| > Customer | | BookManager | | Book | >-------------| |-------------| |-----------------| > ID | | ID | | ID | > First | | customer_id | | book_manager_id | > Last | | isDeleted | | Description | > Email | | isVisible | |-----------------| > Password | |-------------| >-------------|

The issue remains the same, how can i create a new instance from an other bookmanager, is it doable in ruby?

It sounds to me as though you really want a has_many :through rather than what you have.

Customer has_many :book_managers has_many :books, :through => :book_manager

Then a customer can have multiple books, and each relationship to a book is through a corresponding book_manager. Or do you need each customer to have N book_managers, and each of those book_managers has N books? I'm not clear why book_manager is standing between the customer and her books. If it's the latter, then your nested form would have to be two layers deep, and I would be tempted to have a form_for :book_manager masquerade as the form for the customer to acquire books.

Walter

Walter Davis wrote in post #1071811:

Customer has_many :book_managers has_many :books, :through => :book_manager

Then a customer can have multiple books, and each relationship to a book is through a corresponding book_manager. Or do you need each customer to have N book_managers, and each of those book_managers has N books? I'm not clear why book_manager is standing between the customer and her books. If it's the latter, then your nested form would have to be two layers deep, and I would be tempted to have a form_for :book_manager masquerade as the form for the customer to acquire books.

Walter

Yeah I might want more a has_many through, here a sample of the database it should be like

Customer ID First Last Email 1 John Smith example@example.com 2 Heather Clark example@example.com 3 Mike Watson example@example.com

BookManager Id CustomerID isVisible isDeleted 1 1 0 1 2 3 1 0 3 2 1 0 4 1 1 0

Book Id BookManagerID Description 1 1 Harry Potter 2 2 The Javascript Bible 3 3 Harry Potter 4 4 PHP

At the end however i want a form that the customer can create a new bookManager which his associated with a book and manipulate the data from BookManager and Books in the customer#edit.

You have to get the relationships right before worrying about forms. You still have not made it clear what the relationship between books and book_managers is. Is one book_manger associated with a number of books or is one book associated with a number of book_managers, or is it a one to one relationship?

Colin

It sounds like you really need to restructure this as has_many :through, since all your BookManager is adding to the Book is the visible and deleted flags. (And I would name them exactly that, since you can then use the visible? and deleted? meta methods that are automatically added to boolean columns.) Your customer#edit form would have a fields_for :books section, and the usual nested fields for books, so your users would not need to know anything about the BookManager model, only the Book, and you could add the checkboxes for the visible and deleted from your :through relationship. I realize, as I'm writing this, that I don't have a canonical example of how you would add a checkbox to toggle the attribute on the :through object, so I'm going to post a separate question about that...

Walter

Colin Law wrote in post #1071823:

That is only half of the associations. How many customers are associated with each manager and how many book managers are associated with each book?

Show us the model relationships that the above implies for each model.

Colin

Colin Law wrote in post #1071831:

it a one to one relationship?

Colin

A customer has many BookManager A bookManager has one book

That is only half of the associations. How many customers are associated with each manager and how many book managers are associated with each book?

Show us the model relationships that the above implies for each model.

Colin

Here what I build up with has many

class Book < ActiveRecord::Base         # RELATIONSHIP   belongs_to :book_manager   def customer     book_manager.customer   end   attr_accessible :book_manager_id, :description class BookManager < ActiveRecord::Base         # RELATIONSHIP   belongs_to :customer   has_one: :book   accepts_nested_attributes_for :books, allow_destroy: :true   attr_accessible :customer_id, :visible, :books_attributes class Customer < ActiveRecord::Base         # RELATIONSHIP   has_many :book_managers   has_many :books, :through => :book_managers   accepts_nested_attributes_for :book_managers, allow_destroy: :true   attr_accessible :admin, :first_name, :last_name, :middle_name, :email, :email_confirmation, :password, :password_confirmation, :image, :book_managers_attributes, :locale

I think his a correct relationship model.

If you have a one-to-one relationship between books and book managers why not just combine the two tables and make life easier?

Colin

Colin Law wrote in post #1071834:

If there is only a slight possibility then do it the easy way for the moment. You can always refactor it later if you need to. Make sure you have complete automated test coverage of course so that you can be sure it all still works after refactoring. I don't understand how having two tables with a one-to-one relationship can be easier than one table. If that were the case then you could split every field out into separate tables and life would be even easier.

But even if you keep them separate, if the slight possibility did eventually occur would it be each book has many managers or each manager has many books?

Colin

Colin Law wrote in post #1071842:

I am just wondering how I am suppose to build a bookManager has follow. The models his has follow

-------------|1---------*|-------------| Customer | | BookManager | -------------| |-------------| ID | | ID | First | | customer_id | Last | | isDeleted | Email | | isVisible | Password | | description | -------------| |-------------|

The association is as follow

class Customer < ActiveRecord::Base # RELATIONSHIP     has_many :book_managers     accepts_nested_attributes_for :book_managers, allow_destroy: :true     attr_accessible :admin, :first_name, :last_name, :middle_name, :email, :email_confirmation, :password, :password_confirmation, :image, :book_managers_attributes, :locale end

class BookManager < ActiveRecord::Base     belongs_to :customer     attr_accessible :customer_id, :visible, :description end The form is like this Customer#edit view

  <h3>Book</h3>   <div><%= render 'book_managers/form' %></div> BookManagers/Forms

<%= form_for(@book_manager) do |f| %>   <fieldset>     <%= f.label :description %>     <%= f.text_field :description %>   </fieldset>

  <fieldset>     <%= f.check_box :visible %>     <%= f.label :visible %>   </fieldset>

  <div class="actions">     <%= f.submit %>   </div> and this is the big prize puzzle. The controllers At the moment i have nothing in the BookManager controller because its the caller that tend to have the data information. But i am really confused on the customer Controller.

What i want is to associate and fill up the BookManager with customer and its attribute. here what i have for now.

CustomerController

        @customer = Customer.find(params[:id])

# @book_manager = BookManager.new # bm = @customer.book_managers.build # bm.books.build

        @book_manager = @customer.book_managers.build

What has that got to do with merging book and book manager which is a one to one relationship?

Colin

Colin Law wrote in post #1071869: