Sometimes in life you just have to make your life easer. And the first step anybody can take to make their life easier is to not use Accepts_nested_attributes_for when making multiple model forms. The Problem with accepts_nested_attributes_for is that connecting more than two models in a single form is a headache. In Rails the more graceful way to conveniently connect multiple models is to use the Form Object Pattern.
It’s infinitely easier to set up and gives you a higher level of control when it comes to creating very complex forms. The Process goes like this:
- Create a PORO in the Model folder of your rails app
- Inside the PORO Include ActiveModel::Model
- Inside the PORO create attr_accessors representing all the fields of your form
- Add your validations for each accessor attribute
- Inside the PORO, Create a submit method specifying where you want your data to be submitted to.
- Call “FormObjectName”.new and “FormObjectName”.submit when you want to process your form.
The above process allows you to represent the form you want through a PORO not constrained by the rules of ActiveRecord. Its a very simple process and is extensible in a way, that accepts_nested_attributes_for is not. <> Here is an example of how you would setup a form object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
This is how you make the form object available in the controller:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Notice Above that you didn’t call save on the meetingform object. ActiveModel doesnt have a save method, it has an equivalent ActiveModel#valid? method. This method allows you to check that your validations are passing. Also notice that there is no strong paramters being included in the MeetingController. The Validations are happening on the ActiveModel Object themselves once you run the #valid? method.
And lastly, Here is the form that you need to create to use a FormObject:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Notice that this form is not a nested model form. It is a simple and straightforward form. Its purpose is solely to take in the requested data. It has no knowledge of multiple models, and its supported by one simple PORO. However this simple PORO is used to join 3 different models at one time - Meeting,Location,User.
So in Summary: