我想要一个具有以下属性的User
模型创建/验证/更新系统:
要求1
首次创建User
时,:name
,:email
和:password
属性都应该存在,否则创建保存将失败。
要求2
更新User
时,可以单独更新这三个属性,因此如果其中一个或两个空白,则可以继续更新保存。
简单,常见的要求对吗?我不确定。满足第一个要求的显而易见的方法是User
模型validations
,其中presence: true
为所有三个:
user.rb
validates :name, length: {maximum: 50}, presence: true
validates :email, uniqueness: {case_sensitive: false}, presence: true
validates :password, length: {minimum: 6}, presence: true
所以从这里开始,我们如何满足第二个要求?
尝试1
将on: :create
添加到验证中:
validates :name, length: {maximum: 50}, presence: true, on: :create
validates :email, uniqueness: {case_sensitive: false}, presence: true, on: :create
validates :password, length: {minimum: 6}, presence: true, on: :create
这是灾难性的。如果用户尝试通过使用新的name
但空白name
和email
字段提交更新表单来仅更新他的password
,则name
确实会已更新,但email
和password
属性也会更新为空值""
- 因为验证无法运行。
尝试2
将allow_nil: true
添加到验证中:
validates :name, length: {maximum: 50}, presence: true, allow_nil: true
validates :email, uniqueness: {case_sensitive: false}, presence: true, allow_nil: true
validates :password, length: {minimum: 6}, presence: true, allow_nil: true
同样灾难性的。您可以使用空白属性创建和更新用户。
尝试3
仅验证它是新记录还是该字段不为空:
validates :email, uniqueness: {case_sensitive: false}, presence: true, if: :should_validate?
def should_validate?
new_record? || email.present?
end
这已经被Stackoverflow上的其他地方接受为正确的解决方案但如果我错了就纠正我,是不是也是灾难性的?如果您使用空白email
字段更新模型,should_validate?
将返回false
,则不会运行电子邮件验证,并且数据库将使用空白email
进行更新。
如果我错了,请纠正我,但如果不是验证也意味着更新,这个“解决方案”会起作用,但事实并非如此吗?如果您没有运行验证,该属性仍将保存到数据库中吗?
尝试4
在控制器中,如果属性为空,请从params
中删除该属性:
user.rb
validates :name, length: {maximum: 50}, presence: true
validates :email, uniqueness: {case_sensitive: false}, presence: true
validates :password, length: {minimum: 6}, presence: true
users_controller.rb
def update
params[:user].delete(:name) if params[:user][:name].blank?
params[:user].delete(:email) if params[:user][:email].blank?
params[:user].delete(:password) if params[:user][:password].blank?
if @user.update_attributes(update_user_params)
flash[:success] = "Edit Successful."
redirect_to @user
else
@title = "Edit user"
render 'edit'
end
end
def update_user_params
params.require(:user).permit(:name, :email, :password)
end
由于验证中presence: true
,这不起作用。如果params
中没有任何属性,则验证失败,并且记录不会更新。
同样,这已被接受为Stackoverflow上其他地方的正确解决方案,所以我很确定我在某处遗漏了某些东西,请告诉我在哪里?!
尝试5
如果属性为空,则从params
移除该属性,并从验证中删除presence: true
:
user.rb
validates :name, length: {maximum: 50}
validates :email, uniqueness: {case_sensitive: false}
validates :password, length: {minimum: 6}
users_controller.rb
def update
params[:user].delete(:name) if params[:user][:name].blank?
params[:user].delete(:email) if params[:user][:email].blank?
params[:user].delete(:password) if params[:user][:password].blank?
if @user.update_attributes(update_user_params)
flash[:success] = "Edit Successful."
redirect_to @user
else
@title = "Edit user"
render 'edit'
end
end
这不起作用。我们已经达到要求2但已销毁要求1.使用此“解决方案”,您确实可以更新记录的各个属性,但您也可以创建具有空白属性的新记录。
尝试6
我能看到的唯一可行解决方案是对on: :create
和on: :update
进行不同的验证。如果您正在创建记录,则会坚持presence: true
,但如果您要更新记录,请删除presence: true
。您还需要在控制器中包含空白属性删除:
user.rb
validates :name, length: {maximum: 50}, presence: true, on: :create
validates :email, uniqueness: {case_sensitive: false}, presence: true, on: :create
validates :password, length: {minimum: 6}, presence: true, on: :create
validates :name, length: {maximum: 50}, on: :update
validates :email, uniqueness: {case_sensitive: false}, on: :update
validates :password, length: {minimum: 6}, on: :update
users_controller.rb
def update
params[:user].delete(:name) if params[:user][:name].blank?
params[:user].delete(:email) if params[:user][:email].blank?
params[:user].delete(:password) if params[:user][:password].blank?
if @user.update_attributes(update_user_params)
flash[:success] = "Edit Successful."
redirect_to @user
else
@title = "Edit user"
render 'edit'
end
end
这是允许的吗?会有用吗?我完全错过了解决这个问题的正确方法吗?
答案 0 :(得分:0)
您想保存名称,电子邮件在更新时为零吗?我认为没有必要单独更新名称和电子邮件。你只需在你想要的字段或电子邮件的字段中进行更改,就不要让其他字段变得简单。
如果您需要用户名,请单独使用电子邮件更新,只需在用户模型下创建setter方法,如下所示:
def name=(val)
val = name if val.blank?
self.write_attribute(name: val)
end
def email=(val)
val = email if val.blank?
self.write_attribute(email: val)
end
无需为更新用户编写单独的验证。
validates :name, length: {maximum: 50}, presence: true
validates :email, uniqueness: {case_sensitive: false}, presence: true
validates :password, length: {minimum: 6}, presence: true
更新记录时未允许用户参数。如果你使用rails 4,你可能会遇到异常。确保在创建或更新users_controller中的记录之前允许使用params:
def user_params
params.require(:user).permit(:name, :email, :password)
end
所以你更新动作将是:
def update
if @user.update_attributes(user_params)
flash[:success] = "Edit Successful."
redirect_to @user
else
@title = "Edit user"
render 'edit'
end
end