仅更新强参数

时间:2015-10-03 03:18:38

标签: ruby-on-rails validation strong-parameters

首先,我相信必定会有一些人,他们之前已经问过这个问题,但我不知道如何才能解决这个问题。所以,如果它重复,我很抱歉。

我正在社交媒体网站上工作。我有用户模型,我用它来注册用户到网站。它在注册时验证,姓名,电子邮件和密码。

我使用相同的模型让用户编辑他们的信息,比如用户名。

这是我在更新控制器中的内容:

  def update
    # Find an existing object using form parameters
    @profile = User.find_by_id(current_user.id)
    # Update the object
    if @profile.update_attributes!(settings_profile_params)
      # If save succeeds, redirect to itself
      redirect_to request.referrer
    else
      # If save fails, redisplay the form so user can fix the problems
      render('edit')
    end
  end

  private # user_params is not an action, that is why it is private.
  def settings_profile_params
    params.require(:user).permit(:first_name, :last_name, :username, :school, :program, :website, :information)
  end

问题是,我只想更新我在那里定义的强参数。但是由于密码验证,我得到了一个例外。我不知道为什么我会得到这个例外。如何设置系统以仅更新强参数中的值。

谢谢。

3 个答案:

答案 0 :(得分:2)

您可以通过更改密码验证来实现此目的。您需要在密码验证中添加条件。

# Password
  validates :password,
            :presence => {:message => 'Password cannot be blank'},
            :length => {:within => 8..99, :message => 'Password length should be within 8 and 99 characters'}
            :if => Proc.new { new_record? || !password.nil? }

答案 1 :(得分:0)

通过调用update_attributes,您隐式调用与其他更新相同的验证范围并保存。您需要更新您定位的特定参数(例如省略:password)。

在这里,我们可以将允许键列表存储在可重用的变量中。然后,我们会在每个密钥上调用update_attribute - 在reduce中执行此操作,为切换进行编辑或显示提供相同的true / false

  def update
    # Find an existing object using form parameters
    @profile = User.find_by_id(current_user.id)
    # Update the object
    if PERMITTED_KEYS.reduce(true) {|bool, key| bool &&= @profile.update_attribute(key, @profile.send(key)) }
      # If save succeeds, redirect to itself
      redirect_to request.referrer
    else
      # If save fails, redisplay the form so user can fix the problems
      render('edit')
    end
  end

  private 

  PERMITTED_KEYS = [:first_name, :last_name, :username, :school, :program, :website, :information]

  # user_params is not an action, that is why it is private.
  def settings_profile_params
    params.require(:user).permit(PERMITTED_KEYS)
  end

之前没有使用strong_parameters gem,我认为这对于使用gem更为惯用:

  def update
    # Find an existing object using form parameters
    @profile = User.find_by_id(current_user.id)
    # Update the object
    if settings_profile_params.keys.reduce(true) {|bool, key| bool &&= @profile.update_attribute(key, @profile.send(key)) }
      # If save succeeds, redirect to itself
      redirect_to request.referrer
    else
      # If save fails, redisplay the form so user can fix the problems
      render('edit')
    end
  end

  private 

  # user_params is not an action, that is why it is private.
  def settings_profile_params
    params.require(:user).permit(
      :first_name, :last_name, :username, 
      :school, :program, 
      :website, :information
    )
  end

尽管如此,我仍然认为这是一个重复的问题,因为它考虑了如何在没有所有定义的验证的情况下更新模型数据。我已经回答了update_attributes循环被认为是一个足够独特的解决方案以保证不重复的问题。

答案 2 :(得分:0)

好的,现在我发现了问题。首先,@ Muntasim找到了解决这个问题的方法。但我实际上并不需要使用此解决方案,因为还有另一种简单的方法可以解决这个问题。

在这种情况下,当我让用户更新他们的个人资料时,如果我没有要求,他们不应该验证我的密码或用户模型中的任何其他列。但为什么要验证呢?因为我有验证:用户模型中的密码。相反,它必须是验证:digest_password。因为我正在使用bcrypt。

我不知道为什么:即使我使用了bcrypt,密码在我注册时工作正常。