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

On 9 August 2012 14:27, Jean-Sbastien D. [email protected] wrote:

  • 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

On Aug 9, 2012, at 9:39 AM, Jean-Sbastien D. wrote:

You said above BookManager has many books and Book belongs_to 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

Colin L. wrote in post #1071797:

On 9 August 2012 14:27, Jean-Sbastien D. [email protected] wrote:

  • 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?

Walter D. wrote in post #1071811:

On Aug 9, 2012, at 9:39 AM, Jean-Sbastien D. wrote:

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 [email protected]
2 Heather Clark [email protected]
3 Mike Watson [email protected]

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.

On Aug 9, 2012, at 10:57 AM, Jean-Sbastien D. wrote:

have N book_managers, and each of those book_managers has N books? I’m
Customer
4 1 1 0
from BookManager and Books in the customer#edit.
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

On 9 August 2012 15:57, Jean-Sbastien D. [email protected] wrote:

have N book_managers, and each of those book_managers has N books? I’m
Customer
4 1 1 0
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

Colin L. wrote in post #1071823:

On 9 August 2012 15:57, Jean-Sbastien D. [email protected] wrote:

have N book_managers, and each of those book_managers has N books? I’m
Customer
4 1 1 0
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

A customer has many BookManager
A bookManager has one book

Therefore the relationship if i am correct should be has follow

Customer
has_many :BookManagers
BookManager
belongs_to :Customer
has_one :Book
Book
belongs_to :BookManager

I think

On 9 August 2012 16:14, Jean-Sbastien D. [email protected] wrote:

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

Colin L. wrote in post #1071831:

On 9 August 2012 16:14, Jean-Sbastien D. [email protected] wrote:

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.

Colin L. wrote in post #1071834:

On 9 August 2012 16:34, Jean-Sbastien D. [email protected] wrote:

associated with each manager and how many book managers are associated
belongs_to :book_manager
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

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

I agree it would make life easier, but maybe in the future the
relationship could change (“slight possibility”). Also a friend of mine
encourage me to take ruby has its one of the best language in the world.
Sorta agree except relationship on ror seem to be a tricky subject. The
rule someone told me in SQL his make the more table, has its make the
query easier and vice-versa.

On 9 August 2012 16:47, Jean-Sbastien D. [email protected] wrote:

:email_confirmation, :password, :password_confirmation, :image,
Sorta agree except relationship on ror seem to be a tricky subject. The
rule someone told me in SQL his make the more table, has its make the
query easier and vice-versa.

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

On 9 August 2012 16:34, Jean-Sbastien D. [email protected] wrote:

associated with each manager and how many book managers are associated
belongs_to :book_manager
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

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 L. wrote in post #1071842:

On 9 August 2012 16:47, Jean-Sbastien D. [email protected] wrote:

:email_confirmation, :password, :password_confirmation, :image,
Sorta agree except relationship on ror seem to be a tricky subject. The
rule someone told me in SQL his make the more table, has its make the
query easier and vice-versa.

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

It would be each manager has many books. Yeah i am considering merge for
the moment, although i find it ackward in the following example

A customer has_many School
School has many type_of_school.

On 9 August 2012 17:58, Jean-Sbastien D. [email protected] wrote:

sure it all still works after refactoring. I don’t understand how
It would be each manager has many books. Yeah i am considering merge for
the moment, although i find it ackward in the following example

A customer has_many School
School has many type_of_school.

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

Colin

Colin L. wrote in post #1071869:

On 9 August 2012 17:58, Jean-Sbastien D. [email protected] wrote:

sure it all still works after refactoring. I don’t understand how
It would be each manager has many books. Yeah i am considering merge for
the moment, although i find it ackward in the following example

A customer has_many School
School has many type_of_school.

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

Colin

Yeah i figure out the problem, and yeah has nothing to do with this type
of relationship.

Thank for you help! :smiley:

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

Book

<%= render 'book_managers/form' %>
BookManagers/Forms

<%= form_for(@book_manager) do |f| %>

<%= f.label :description %> <%= f.text_field :description %> <%= f.check_box :visible %> <%= f.label :visible %>
<%= f.submit %>
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