I’m sure we’ve all been there; trying to save a list of associated objects together with the instance they belong to. Fortunately with the right tools this can be really simple.
Let’s assume we have a question in a questionnaire and need to specify an arbitrary number of options to this question. We could construct the following database schema.
There are basically three ways I know about to assign multiple options to a question from one page. The first option is to create a Question instance in the database before rendering the form so we can use remote_form to send an Ajax request and directly associate the Option instance. An advantage of this solution is that all data is directly saved to the database, which makes losing any data less likely. Another advantage is that the functionality is spread nicely over the responsible controllers. First you perform a create on the QuestionsController, after that you perform multiple creates on the OptionsController. The disadvantage is that you have to create a Question with default values or by circumventing the initial validation. This could generate some ‘blank’ Question instances in the database which you will have to garbage collect.
The second option is a slight variation on the first option. Instead of creating a Question to link the Options to you keep all the generated Option id’s in the session and link them to the Question after validation. This solution also benefits from nice separation of concern in the controllers, but on the downside it also leaves you with unlinked Option objects you will have to garbage collect.
We just mentioned that we want to send the entire form at once, we can use validates_associated to make sure the Question is never saved when the options aren’t valid. This allows you to easily validate all the information from the form at once. The models to go with the database look something like this.