正确答案不再适用于 rails 4。我相信我的答案是最简洁和最通用 的,只要您想省略任何属性(而不仅仅是密码),它就会起作用。如果您想在多个不同位置更新任何模型的单独属性,则需要这种方法。
例如,如果您想做 Stack Overflow 所做的事情并通过security
页面更新密码,则可以通过用户显示视图更新个人资料图像,并通过用户编辑视图更新大部分用户信息。
1)hash class
用类方法扩展删除空白值。我们将使用此方法删除未更新但仍存在于 params 哈希中的空白值:
1a)在您的目录中创建一个hash.rb
文件lib
,在一个ext
目录下:
命令行
$ mkdir lib/ext
$ touch lib/ext/hash.rb
1b)在内部hash.rb
,“创建”一个Hash
类并创建一个.delete_blanks!
方法:
lib/ext/hash.rb
class Hash
def delete_blanks!
delete_if { |k, v| v.nil? }
end
end
1c)将此文件(以及您的整个 lib 目录)放入在初始化程序中引用它的 rails 中:
配置/boot.rb
# other things such as gemfiles are required here, left out for brevity
Dir['lib/**/*.rb'].each { |f| load(f) } # requires all .rb files in the lib directory
2) 在 users#update 操作中,实现我们闪亮的新 delete_blanks!类方法从参数哈希中删除我们没有更新的属性。然后,通过方法更新用户实例update_attributes
,*不是update
方法!
2a)首先,让我们使用 delete_blanks!修复我们的 user_params 哈希的方法:
应用程序/控制器/users_controller.rb
new_params = user_params.delete_blanks!
2b)现在让我们使用方法更新实例update_attributes
,(同样,不是update
方法):
应用程序/控制器/users_controller.rb
@user.update_attributes(new_params)
以下是完成的users#update
操作的外观:
应用程序/控制器/users_controller.rb
def update
new_params = user_params.delete_blanks!
if @user.update_attributes(new_params)
redirect_to @user, notice: 'User was successfully updated.'
else
render action: 'edit' // or whatever you want to do
end
end
3)在User
模型中,将if: :<attribute>
选项添加到所有验证。这是为了确保仅当参数哈希中存在该属性时才触发验证。我们的delete_blanks!
方法将从 params 哈希中删除该属性,因此例如密码验证将不会运行。还值得注意的是,delete_blanks!
仅删除值为nil的哈希条目,而不是具有空字符串的哈希条目。因此,如果有人在用户创建表单(或任何带有密码字段的表单)上遗漏了密码,则存在验证将生效,因为哈希的 :password 条目不会为零,它将为空细绳:
3a)在所有验证中使用该if:
选项:
应用程序/模型/user.rb
VALID_EMAIL_REGEX = /[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9\-.]/
validates :first_name, presence: true, if: :first_name
validates :last_name, presence: true, if: :last_name
validates :user_name, presence: true, if: :user_name
validates :email, presence: true,
uniqueness: { case_sensitive: false },
format: { with: VALID_EMAIL_REGEX }, if: :email
validates :password, length: { minimum: 6, maximum: 10 }, if: :password
就是这样。现在,用户模型可以在整个应用程序中通过许多不同的形式进行更新。属性的存在验证仍然会在包含它的字段的任何表单上发挥作用,例如,密码存在验证仍然会在user#create
视图中发挥作用。
这可能看起来比其他答案更冗长,但我相信这是最可靠的方法。User
您可以在无限数量的不同模型上单独更新无限数量的实例属性。请记住,当您想使用新模型执行此操作时,您需要重复步骤2a)、2b)和3a)