Project Ramon

A learning journey from a Ruby noob perspective

Exploring Rails: accepts_nested_attributes_for pt[1]

accepts_nested_attributes_header_img

Hello and welcome!

 

Today I’ll be continuing my exploration of the Rails form helper accepts_nested_attributes_for.

In my last post, I covered why I initially wanted to use accepts_nested_attributes_for, as an aid to create and update some nested resources that were recently built due to an extract class refactor on one of my monolithic models.

In this post, I’ll be going over using the form helper in a new sandbox application created for these demonstrations.

Setting the Stage

Ok, so first lets create a few classes for the purpose of having some objects that need to interact with one another.

accepts_nested_attributes_for2_img1

In addition to the 4 models shown in the image above, I’ve also created one polymorphic table for addressa regular has_one table for phone_number and email.

Now lets go over the 5 steps to implementing accepts_nested_attributes_for. I’ll provide some illustration along the way, as that will probably serve us better than just writing the steps alone.

The 5 steps are:

  1. Create the necessary associations
  2. Add the method accepts_nested_attributes_for :resource_name in the class whose form will be used to GET, PUT/PATCH and optionally DESTROY the nested resource’s attribute field values
  3. Whitelist the nested attributes
  4. In the controller of the class whose form you will use to store the nested attributes, build the associated objects in the new action
  5. In the view template of the class you’ll use to store the nested attributes add a fields_for :nested_model_name to the form in order to add the nested form fields

And here are some images of what each of those steps look like in this new sandbox application.

Steps 1, 2 and 3: Creating the associations and invoking accepts_nested_attributes_for for those associations.

accepts_nested_attributes_for2_img2

On lines 3 & 4 we are satisfying step 1, defining the relationships on the models. Line 12 is completing step number 2, which calls our Rails form helper method and passes in two parameters that represent the names of the first two classes that will need their attributes managed by the nested field sets of the Teacher class. Line 2 displays what step 3 is asking for, which is white-listing the associated model’s attributes.

Here, in the Rails Guides, is an excellent explanation of why we are white-listing our nested attributes as a hash of attributes of listing each attribute one by one:

accetps_nested_attributes_for2_img3

So if we wanted to view one of our nested resources from our console, we could do something like so:

accepts_nested_attributes_for2_img4

The white listing of :teacher_aids_attributes or :student_attributes just means that Rails is creating them as hashes that are nested under our Teacher class.

Returning to step 4 of our process, here’s an illustration of the parent controller, which in this case, is our controller named teachers_controller.rb.

accepts_nested_attributes_for2_img5

And now for some ERB action!

Here’s an illustration of a nested_form template using fields_for:

accepts_nested_attributes_for2_img7

So, lets see our newly created nested form perform.

Heres the freshly nested_form:

accepts_nested_attributes_for2_img8

Here’s a client, about to commit some data:

accepts_nested_attributes_for2_img9

And we can confirm that the above steps work, because now we’re retrieving that committed data into the following view template:

accepts_nested_attributes_for2_img10

Defining Boundaries

So, now that we have a basic implementation of accepts_nested_attributes_for working, lets see if we can’t replicate the same sort of conditions that were present in my personal project I showed yesterday, so we can work through this.

We may find that we’ve reached the limits of this Rails form helper, or more hopefully, find that there were just some errors to attend to in the way I attempted to build deeply nested forms. In either case, here we go.

The Polymorphic Attempt

Lets use a polymorphic model I’ve created and see if we can get our Teacher class to accept address fields for itself, and then we can try to have Teacher‘s template accept_nested_attributes_for an address for a TeacherAid.

Here’s the Address and Teacher class to illustrate the associations:

accepts_nested_attributes_for2_img11

accepts_nested_attributes_for2_img2

Following the steps that were outlined at the beginning of this post, heres a quick list of things I’ll be adding to get Address fields into the template of Teacher.

Add :address to the list of parameters on line: 12 in teacher.rb

Add :address_attributes to attr_accessible on line: 2 in teacher.rb

Add @teacher.address.build inside of teachers_controller.rb‘s new method.

Add f.fields_for :address block to the view template for Teacher along with the attribute names.

Now lets see if this works:

accepts_nested_attributes_for2_img12

accepts_nested_attributes_for2_img13

accepts_nested_attributes_for2_img14

In Closing

So these are the basics when you are in need of managing multiple objects in one form template.
Tomorrow I’ll be pushing the limits, so to speak, by trying to wrap my head around Teacher, TeacherAid and Student to be composed of classes such as Email, Address and PhoneNumber.

Some questions that I’m seeking answers to are:

In the form, can I use fields_for :students { |student| ... } , for example, to bring in a student object’s phone number or email like so?

Or would I need to nest a fields_for inside of Student‘s nested block and then spin up something like:

Looks like a single fields_for :students isn’t enough bring about it’s composed address object:

accepts_nested_attributes_for2_img15

So lets try changing the ERB code to nest TeacherAid‘s address object like this:

accepts_nested_attributes_for2_img16

And here is the sequence of results:

accepts_nested_attributes_for2_img17

Sweet, so we can confirm that we do-in-fact need to nest a fields_for inside another fields_for in order to have an ability to add a composed object’s composed object into the parent’s view template.

Next up, the commit.

accepts_nested_attributes_for2_img18

And…

accepts_nested_attributes_for2_img19

Defekt!

This is where I'll be picking things up in my next post đŸ™‚

Stay tuned…

Advertisements

Categories: Newbie, Ruby on rails

1 reply

Trackbacks

  1. Exploring Rails: accepts_nested_attributes_for pt[2] | Project Ramon

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s