如何进行部分更新?

时间:2016-11-12 08:28:50

标签: ruby-on-rails-4

如何进行部分更新(即通过PATCH)? rake routes表示def update处理PUTPATCH。这就是我的Rails API的设置方式:

@user.first_name = user_params[:attributes][:'first-name']
@user.last_name = user_params[:attributes][:'last-name']

user模型中。 first_namelast_name都有validates … presence: true。但是,客户端正试图仅使用attributes[first-name]命中端点。请注意,attributes[last-name]未在请求中传递。 Rails认为@user.first_name有一个值,但@user.last_namenil。因此抛出了验证错误

我想到的一种方式是:

@user.first_name = user_params[:attributes][:'first-name'].present? ? user_params[:attributes][:'first-name'] : @user.first_name
@user.last_name = user_params[:attributes][:'last-name'].present? ? user_params[:attributes][:'last-name'] : @user.last_name 

这是一种可行的方法吗?或者我能考虑哪些更好的东西?

修改即可。更复杂的问题是我需要在实际保存对象之前预先计算。例如,一个产品试图更新其价格与折扣价值(如果存在)

def update
  product                        = Product.find(params[:id])
  product.amount_in_cents        = product_params[:attributes][:'amount-in-cents']
  product.discount_in_percentage = product_params[:attributes][:'discount-in-percentage'].present? ? product_params[:attributes][:'discount-in-percentage'].to_f : nil # Can be 0.10

  if product.discount_in_percentage.present?
    product.amount_in_cents = product.amount_in_cents + (product.amount_in_cents * product.discount_in_percentage)
  else
    product.amount_in_cents = product.amount_in_cents
  end

  if product.save
    # ...
  end
end

1 个答案:

答案 0 :(得分:0)

在Rails中,我们有一个约定,即模型中的属性应该被提取到Rails应用程序,如user[first_name]user[last_name],在控制器中,我们会构建一个像users_params这样的私有方法。表示要馈送到User模型的数据。像

# in controller
def update
  user = User.find(params[:id])
  user.update(users_params)
end

private

# This will prepare a whitelisted params data
def users_params
  params.require(:user).permit(:first_name, :last_name, ...)
end

不需要这个

@user.first_name = user_params[:attributes][:'first-name'].present? ? user_params[:attributes][:'first-name'] : @user.first_name
@user.last_name = user_params[:attributes][:'last-name'].present? ? user_params[:attributes][:'last-name'] : @user.last_name 

在您的情况下,您需要将params键重新格式化为first_name而不是first-name,依此类推。这将帮助您轻松完成您的工作。

  

提示:尽量使其更简单