开发者

Ruby on Rails - updating multiple models from the one controller

开发者 https://www.devze.com 2023-04-01 09:29 出处:网络
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'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.

0

精彩评论

暂无评论...
验证码 换一张
取 消