I'm trying to get my head around saving to multiple models from the one controller and it's probably really simple but I can't figure it out.
I have a User Model that has many loanitems
and the loanitems
belong to the user associations set up.
In my loanitems
controller I want each loanitem
create action to update a the user.points
So at the moment I have the following code that doesn't throw any errors but doesn't update the user model either.
def create
@loanitem = current_user.loanitems.build(params[:loanitem])
respond_to do |format|
if @loanitem.save
@loanitem.user.points = @loanitem.user.points + 50
@loanitem.user.save
format.html {redirect_to root_path, :flash => {:success => "Loan Item created" } }
format.xml{render xml: root_path}
else
format.html {render 'pages/home' }
format.xml {render xml: 'pages/home'}
end
end
end
I'm also trying the following variation on a theme
def create
@loanitem = current_user.loanitems.build(params[:loanitem])
respond_to do |format|
if @loanitem.save
current_user.points = current_user.points + 50
current_user.save
format.html {redirect_to root_path, :flash => {:success => "Loan Item created" } }
format.xml{render xml: root_path}
else
format.html {render 'pages/home' }
format.xml {render xml: 'pages/home'}
end
end
end
But should I be sending some message instead to the userupdate
controller instead? That currently looks like this ...
def update
@user = User.find(params[:id])
if
@user.update_attributes(params[:user])
redirect_to @user, :flash => { :success => "Profile has been updated!"}
el开发者_如何学Gose
@title = "Edit Profile"
render 'edit'
end
end
Or I have heard that the business logic really should all be contained in the model so maybe the method should be written in User.rb
and then called by the Loanitems
controllers create method?
I know it's a real rookie question but any advice would be really welcome.
It sounds like you need to use a Transaction, so you can modify multiple items as a single atomic unit:
def create
respond_to do |format|
User.transaction do
begin
@loanitem = current_user.loanitems.create!(params[:loanitem]) # raises exception if it can't create
@loanitem.user.update_attributes!(:points => @loanitem.user.points + 50) # raises exception if it can't update
format.html {redirect_to root_path, :flash => {:success => "Loan Item created" } }
format.xml{render xml: root_path}
rescue ActiveRecord::RecordInvalid
format.html {render 'pages/home' }
format.xml {render xml: 'pages/home'}
raise ActiveRecord::Rollback
end
end
end
end
This allows you to have a simple happy-path where multiple objects are updated/created and roll-back all changes so far if anything goes wrong and render your error handling logic. The objects will have the validation messages you can display to the user.
精彩评论