【问题标题】:Ruby on Rails - updating multiple models from the one controllerRuby on Rails - 从一个控制器更新多个模型
【发布时间】:2011-08-29 17:56:24
【问题描述】:

我正试图从一个控制器保存到多个模型,这可能真的很简单,但我想不通。

我有一个用户模型,其中有许多 loanitemsloanitems 属于设置的用户关联。

在我的loanitems 控制器中,我希望每个loanitem 创建操作来更新user.points

所以目前我有以下代码,它不会引发任何错误,但也不会更新用户模型。

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

我也在尝试以下主题的变体

  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

但是我应该改为向userupdate 控制器发送一些消息吗?目前看起来是这样的......

def update
  @user = User.find(params[:id])
  if
    @user.update_attributes(params[:user])
    redirect_to @user, :flash => { :success => "Profile has been updated!"}
  else
    @title = "Edit Profile"
    render 'edit'
  end
end

或者我听说业务逻辑真的应该全部包含在模型中,所以也许该方法应该写在User.rb 中,然后由Loanitems 控制器创建方法调用?

我知道这是一个真正的菜鸟问题,但我们非常欢迎任何建议。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3


    【解决方案1】:

    听起来您需要使用事务,因此您可以将多个项目修改为单个原子单元:

    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
    

    这允许您拥有一个简单的快乐路径,其中更新/创建多个对象并在出现任何问题时回滚到目前为止的所有更改并呈现您的错误处理逻辑。这些对象将具有您可以向用户显示的验证消息。

    【讨论】:

    • 我以前没有遇到过这个交易——不过看起来不错——会试一试,然后回来找你。为帮助干杯!
    • 嘿 Winfield - 试了一下 - 但它在 @loanitem.user.update_attributes!(:points => @loanitem.user.points + 50) 行上失败了。我尝试在 User 模型中创建点 attr_accessor ,但是当你没想到它时会抛出你有一个 nil 对象!您可能期望有一个 Array 的实例。评估 nil.+ 时发生错误(我真的只是在那里猜测)
    • Winfield 我让它工作了 - 感谢您的帮助 - 我做了一点改动,因为我在用户模型上验证了电子邮件和密码 - 我需要使用 update_attributes 方法将这些值传递给 - 谢谢再次帮助我。
    猜你喜欢
    • 1970-01-01
    • 2017-11-08
    • 2012-12-31
    • 2012-01-09
    • 2017-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多