【问题标题】:How to update multiple Models in single action? (Rails 4)如何一次更新多个模型? (导轨 4)
【发布时间】:2016-06-13 21:04:29
【问题描述】:

我有 4 个模型,我有一个非常重要的原因来更新所有模型(可能在单独的操作中,但在 1 个操作中,如果可能的话)。

如果我想更新 1 个模型,我可以使用

def update
  @modelA = ModelA.find(params[:id]
  respond_to do |format|
      if @modelA.update(modelA_params)
        format.html { redirect_to :back, notice: "" }
        format.json { head :no_content }
      else
        format.json { render json: @modelA.errors, status: :unprocessable_entity }
        format.html { render :show }
      end
    end
end

带有适当的参数。如果我有配置页面并且我想更新 4 个模型(当然是分开的),我将如何更改它?每个模型都有 4 列,我想从模型中更新每列的适当属性。就我而言,我使用x-editable gem 来更新属性。

问题是……有什么破解方法吗?像批量更新 案例条件还是我应该为每个模型创建更新操作 更新它们?(在 configuration_controller 中)

【问题讨论】:

  • 当然你可以在同一个表单中收集属于不同模型的不同参数。然后在单个控制器操作(#create 或 #update)中更新 4 个不同的模型。这不是什么特别的技巧,它是控制器从任何模型调用任何记录的能力..您可以使用嵌套表单。或者只是不加区别地收集,然后在控制器操作中手动分配。
  • 根据这些模型是否相关,您也许可以使用nested attributes
  • 您好,我面临着类似的情况,我的模型不相关,但我希望通过一个操作来更新它们,您能说一下您是如何解决的吗? @Skrpter

标签: ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

如果您可以将所有 4 个模型的参数传递给操作,您可以执行以下操作:

# app/controllers/configuration_controller.rb
def update
  @a = ModelA.find(params[:model_a][:id])
  @b = ModelB.find(params[:model_b][:id])
  @c = ModelC.find(params[:model_c][:id])
  @d = ModelD.find(params[:model_d][:id])

  @a.assign_attributes(model_a_params)
  @b.assign_attributes(model_b_params)
  @c.assign_attributes(model_c_params)
  @d.assign_attributes(model_d_params)

  respond_to do |format|
    if @a.save && @b.save && @c.save && @d.save
      format.html { redirect_to :back, notice: "" }
      format.json { head :no_content }
    else
      format.json { render json: [@a.errors, @b.errors, @c.errors, @d.errors], status: :unprocessable_entity }
      format.html { render :show }
    end
  end

  private

  def model_a_params
  params.require(:model_a).permit(:id) # and other permitted params
end

#... same for the other 3 models

我在这里使用了assign_attributes,因为您可能希望在操作中使用atomicity

[编辑]

另一方面,如果您想在单独的操作中更新模型,那么只需在控制器中设置 4 个单独的操作:

# app/controllers/configuration_controller.rb
def update_model_a
  @a = ModelA.find(params[:id])
  respond_to do |format|
    if @a.save
      format.html { redirect_to :back, notice: "" }
      format.json { head :no_content }
    else
      format.json { render json: [@a.errors, @b.errors, @c.errors, @d.errors], status: :unprocessable_entity }
      format.html { render :show }
    end
  end

  def update_model_b
    @b = ModelB.find(params[:id])
    respond_to do |format|
      if @b.save
        format.html { redirect_to :back, notice: "" }
        format.json { head :no_content }
      else
        format.json { render json: [@a.errors, @b.errors, @c.errors, @d.errors], status: :unprocessable_entity }
        format.html { render :show }
      end
    end

# ... etc.

private

def model_a_params
  params.require(:model_a).permit(:id) # and other permitted params
end

def model_b_params
  params.require(:model_b).permit(:id) # and other permitted params
end

# ... etc.

#... same for the other 3 models

【讨论】:

  • hmmm 你的解决方案很有趣......但我正在尝试实施并且我发现了一些问题......我忘了告诉你 x-editable 从适当的模型中获取 1 个属性并调用控制器请求更新,所以如果我想从 modelA 更新属性,它会响应“我还没有找到 modelB 对象:id,modelC 对象:id 等......所以我不想用所有模型“筛选整个包”,但我想要采取行动,从适当的模型中获取单个属性并更新它。
  • 当我想更新时我从 binding.pry 的响应:[1] pry(#)> params => {"modelA"=>{"name"=>"someNameToUpdate" }, "controller"=>"configurations", "action"=>"update", "id"=>"12"}
  • 对不起,如果我误解了你的问题。我也不熟悉您使用的宝石。如果您可以将上述参数中的action 更改为update_model_a,那么您可以为每个单独的模型调用一次。因此,ConfigurationsController 中需要 4 个更新操作,每个模型一个。
  • @Skrypter,为了让其他看到这个问题的人更清楚,上面的答案有帮助吗?还是评论?
  • 在评论中找到的答案......这就是为什么我说 ty 寻求帮助......以及其他人:“如果你有像我这样的问题,你应该考虑你的情况......如果你将在 1 个控制器中更新几个模型,并且该控制器仅来自单个模型的 1 个属性,那么每次更新每个模型都应该有 1 个操作...但是如果您使用 FORM 并且在那里放置了几个模型的属性,那么您应该创建 1同时处理少数模型更新的操作”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多