Q: How do I make a form that handles multiple models?
This question is asked quite frequently. Scaffolding and simple Rails tutorials show you how to create one model per form. Unfortunately, sometimes this is not sufficient.
In this article we will make one form that creates two models: Project and Task (where a project has many tasks). What I would like to do is have the first task be created the same time the project is created (in the same form). Here's the new action in the controller:
Last edited by ryanb (2006-09-26 23:48:21)
Offline
Nice article! Just one thing: I prefer combining the new and the create action to a singel action. But I think thats just favor...
Offline
Dieter Komendera wrote:
Nice article! Just one thing: I prefer combining the new and the create action to a singel action. But I think thats just favor...
I actually like that better too, but it's not compatible with Simply RESTful, so I've gone back to using two actions.
Offline
Thank you Ryan for all your great Tutorials.
Offline
As a Rails newbie, I just wanted to extend a large THANK YOU for this tutorial -- it has helped me immensely.
Offline
Thanks for the tutorial for sure, clear and simple to follow.
I'm having a hard time though figuring out how to combine this with the RESTful stuff in edge rails (and SImply Restful).
I have a user, who has groups, with contacts in them. When I create a new contact, they choose what group to put the contact in, and also have the option of adding a new group.
To add a new group, in RESTful manner that should be a call to the create action on the groups_controller, and to add a new contact it should be a call to the create action on the contacts_controller. But I want it to all be in one call.
Do I have to break the RESTful model by folding group creation into contact creation, or can anybody suggest any other ways to do this!
Thanks in advance,
Cameron
Offline
cameron wrote:
Do I have to break the RESTful model by folding group creation into contact creation, or can anybody suggest any other ways to do this!
I don't think you are breaking the REST convention by doing this. The important thing is that you have one primary model which you are creating/editing. You can add/update as many other models in the same form as you want as long as they are directly related to the primary model.
If it helps, think of updating/creating these secondary models as altering the attributes of the primary model. You could have been storing the group as a string in the contacts table (but that wouldn't be as good of a design). This is a little oversimplifying the problem, but I hope you grasp the concept. I like to think of REST as more of a best practice/convention and shouldn't be taken too strictly.
Something you do need to be concerned about is duplicate code. In my experience, creating multiple models in one form does not lead to duplicate code because you are setting up the relationship at the same time. For example, creating the group in the GroupsController would look like this:
Offline
What about multiple tasks? And what if the tasks are related to the Project via has_many :through (ie. build won't work)?
Last edited by skwasha (2006-12-15 05:31:34)
Offline
In that case you would probably place checkboxes or something in the Task edit page to assign it to given projects. There are other ways to do this as well. If you do a search for "HABTM checkbox" on the site you will probably find a couple posts on the subject. I may write another tutorial for this specific case as well.
Offline
I seem to be doing something wrong.
I keep receiving this error when i submit:
undefined method `reviews' for #<Album:0x24f6c00>
Here is my code
Last edited by ldenman (2006-12-25 06:46:45)
Offline
Have you set up the association in the Album model?
Offline
Hi Ryan, thanks for the tutorial. Umm, one thing I want to learn is why do we use render instead of redirect_to when @project.save return false? Could you please explain a bit?
Offline
Certainly. The reason is if the validation fails, the errors are added to the model object (in this case @project). All instance variables are lost on a redirect because it's like an entirely new request. This means the error messages are lost as well as the data the user typed into the form. This is why we just do a render so the errors and other data is still there and we can display it on the rendered page.
Offline
Ahh, excellent. Thank you!
Offline
Offline
What a great find! I don't remember this before. I wonder if it's new in 1.2.
Offline
This is definitely a great tutorial !
I've a quick question.
Imagine you want each tasks of your project to be attached to this project. I think you will add
validates_presence_of :project_id within the task model.
However if you do that when there is a validation error you get two nasty messages not very user friendly :
Tasks is invalid
Project can't be blank
On a computer point of view these messages make total sense, however form the user side...
Is there someone knows how to hide validation messages which concerns database relations ?
Thanks
Cyrille
Last edited by scyrille (2007-02-03 20:34:52)
Offline
Not sure the best way to solve this. You an try setting the :message parameter to nil when setting up the validation.
Offline
scyrille wrote:
However if you do that when there is a validation error you get two nasty messages not very user friendly :
Tasks is invalid
Project can't be blank
On a computer point of view these messages make total sense, however form the user side...
Is there someone knows how to hide validation messages which concerns database relations ?
You could use conditional validation, e.g.:
Offline