Suppose I have a simple to-do list application. The application contains two models:
- lists (have an owner and description)
- items (have name and due-date) that belong to a specific list
I would like to have a single edit screen for a list in which I update the list attributes (such as description) and also create/delete/modify associated items. There should be a single "save" button that will commit all changes. Unless save is pressed, any change to the list and the items should be forgotten.
I wasn't able to find an elegant best practice for this. Would greatly appreciate any sugges开发者_StackOverflow社区tions and/or references to existing implementations.
You should be able to make this work with accepts_nested_attributes_for
on the has_many
association. Quoting from the Rails API docs:
Consider a member that has a number of posts:
class Member < ActiveRecord::Base
has_many :posts
accepts_nested_attributes_for :posts
end
You can now set or update attributes on an associated post model through the attribute hash. For each hash that does not have an id key a new record will be instantiated, unless the hash also contains a _delete key that evaluates to true.
params = { :member => {
:name => 'joe', :posts_attributes => [
{ :title => 'Kari, the awesome Ruby documentation browser!' },
{ :title => 'The egalitarian assumption of the modern citizen' },
{ :title => '', :_delete => '1' } # this will be ignored
]
}}
member = Member.create(params['member'])
member.posts.length # => 2
member.posts.first.title # => 'Kari, the awesome Ruby documentation browser!'
member.posts.second.title # => 'The egalitarian assumption of the modern citizen'
There's also a good explanation in Railscast 196 which shows how to set up forms with nested attributes.
Try Something like following
@list = List.find(params[:id])
@item = @list.item
@list.attributes=params[:list]
@item.attributes=params[:item]
# (@list.valid? & @item.valid?) this is used for retrieving error message for both list and item
if (@list.valid? & @item.valid?) && @list.save && @item.save
flash[:notice] = "List updated successfully."
redirect_to :action => "list_details", :id => @list.id
else
return(render (:action => 'edit_list', :id =>@list.id))
end
精彩评论