我的用户模型中有以下内容
attr_accessible :avatar, :email
validates_presence_of :email
has_attached_file :avatar # paperclip
validates_attachment_size :avatar,
:less_than => 1.megabyte,
:message => 'Image cannot be larger than 1MB in size',
:if => Proc.new { |imports| !imports.avatar_file_name.blank? }
在我的某个控制器中,我只想更新并验证头像字段而不更新和验证电子邮件。
我该怎么做?
例如(这不起作用)
if @user.update_attributes(params[:user])
# do something...
end
我也试过了update_attribute('avatar', params[:user][:avatar])
,但这也会跳过头像字段的验证。
答案 0 :(得分:13)
你可validate the attribute by hand使用update_attribute
skips validation。如果您添加this to your User
:
def self.valid_attribute?(attr, value)
mock = self.new(attr => value)
if mock.valid?
true
else
!mock.errors.has_key?(attr)
end
end
然后更新属性:
if(!User.valid_attribute?('avatar', params[:user][:avatar])
# Complain or whatever.
end
@user.update_attribute('avatar', params[:user][:avatar])
只有(手动)验证该属性时,才应更新单个属性。
如果你看一下Milan Novota的valid_attribute?
是如何工作的,你会看到它执行验证,然后检查特定的attr
是否有问题;如果任何其他验证失败并不重要,因为valid_attribute?
仅查看您感兴趣的属性的验证失败。
如果您要做很多这样的事情,那么您可以向User添加一个方法:
def update_just_this_one(attr, value)
raise "Bad #{attr}" if(!User.valid_attribute?(attr, value))
self.update_attribute(attr, value)
end
并使用它来更新您的单个属性。
答案 1 :(得分:8)
条件?
validates_presence_of :email, :if => :email_changed?
答案 2 :(得分:1)
您是否尝试过在validates_presence_of :email
上添加条件?
http://ar.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M000083
配置选项:
if - 指定要调用的方法,proc或字符串,以确定是否应进行验证(例如:if =>:allow_validation,或:if => Proc.new {| user | user.signup_step> 2 })。方法,proc或string应该返回或计算为true或false值。
除非 - 指定要调用的方法,proc或字符串以确定是否不应进行验证(例如:unless =>:skip_validation,或:unless => Proc.new {| user | user.signup_step< = 2})。方法,proc或string应该返回或计算为true或false值。
答案 3 :(得分:1)
我假设您需要这个,因为您有一个多步骤向导,您首先上传头像,稍后会填写电子邮件。
据我所知,通过您的验证,我认为没有好的解决方案。要么全部验证,要么在没有验证的情况下更新头像。如果它是一个简单的属性,您可以检查新值是否单独通过验证,然后更新模型而不进行验证(例如使用update_attribute
)。
我可以建议两种可能的替代方法:
所以我建议这样的事情:
validate :presence_of_email_after_upload_avatar
def presence_of_email_after_upload_avatar
# write some test, when the email should be present
if avatar.present?
errors.add(:email, "Email is required") unless email.present?
end
end
希望这有帮助。
答案 4 :(得分:1)
这是我的解决方案。 它与 .valid?方法保持相同的行为,返回true或false,并在调用模型时添加错误。
class MyModel < ActiveRecord::Base
def valid_attributes?(attributes)
mock = self.class.new(self.attributes)
mock.valid?
mock.errors.to_hash.select { |attribute| attributes.include? attribute }.each do |error_key, error_messages|
error_messages.each do |error_message|
self.errors.add(error_key, error_message)
end
end
self.errors.to_hash.empty?
end
end
> my_model.valid_attributes? [:first_name, :email] # => returns true if first_name and email is valid, returns false if at least one is not valid
> my_modal.errors.messages # => now contain errors of the previous validation
{'first_name' => ["can't be blank"]}