验证和更新单一属性轨

发布于 2024-12-01 01:31:25 字数 708 浏览 4 评论 0原文

我的一个控制器的用户模型中有以下内容

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]) ,但这也会跳过 avatar 字段的验证。

I have the following in my user model

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? }

in one of my controllers, I ONLY want to update and validate the avatar field without updating and validating email.

How can I do this?

for example (this won't work)

if @user.update_attributes(params[:user])
 # do something... 
end

I also tried with update_attribute('avatar', params[:user][:avatar]), but that would skip the validations for avatar field as well.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

仄言 2024-12-08 01:31:25

您可以手动验证属性并使用update_attribute,即 跳过验证。如果添加 将此信息发送给您的用户

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

,并使用它来更新你的单个属性。

You could validate the attribute by hand and use update_attribute, that skips validation. If you add 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

And then update the attribute thusly:

if(!User.valid_attribute?('avatar', params[:user][:avatar])
    # Complain or whatever.
end
@user.update_attribute('avatar', params[:user][:avatar])

You should get your single attribute updated while only (manually) validating that attribute.

If you look at how Milan Novota's valid_attribute? works, you'll see that it performs the validations and then checks to see if the specific attr had issues; it doesn't matter if any of the other validations failed as valid_attribute? only looks at the validation failures for the attribute that you're interested in.

If you're going to be doing a lot of this stuff then you could add a method to User:

def update_just_this_one(attr, value)
    raise "Bad #{attr}" if(!User.valid_attribute?(attr, value))
    self.update_attribute(attr, value)
end

and use that to update your single attribute.

隔纱相望 2024-12-08 01:31:25

有条件吗?

validates_presence_of :email, :if => :email_changed?

A condition?

validates_presence_of :email, :if => :email_changed?
攀登最高峰 2024-12-08 01:31:25

您是否尝试过在 validates_presence_of :email 上设置条件?

http://ar.rubyonrails.org/classes/ActiveRecord/Validations/ ClassMethods.html#M000083

配置选项:

if - 指定要调用的方法、过程或字符串以确定是否应进行验证(例如 :if => :allow_validation 或 :if => Proc.new { |user| user.signup_step > 2 })。方法、过程或字符串应返回或计算为 true 或 false 值。

unless - 指定要调用的方法、过程或字符串以确定是否不应进行验证(例如 :unless => :skip_validation 或 :unless => Proc.new { |user| user.signup_step

= 2 })。方法、过程或字符串应返回或计算为 true 或 false 值。

Have you tried putting a condition on the validates_presence_of :email ?

http://ar.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M000083

Configuration options:

if - Specifies a method, proc or string to call to determine if the validation should occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The method, proc or string should return or evaluate to a true or false value.

unless - Specifies a method, proc or string to call to determine if the validation should not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The method, proc or string should return or evaluate to a true or false value.

我喜欢麦丽素 2024-12-08 01:31:25

我假设您需要这个,因为您有一个多步骤向导,您首先上传头像,然后填写电子邮件。

据我所知,根据您的验证,我认为没有好的可行解决方案。要么验证全部,要么更新头像而不进行验证。如果它是一个简单的属性,您可以单独检查新值是否通过验证,然后在不验证的情况下更新模型(例如使用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

希望这会有所帮助。

I am assuming you need this, because you have a multi-step wizard, where you first upload the avatar and the e-mail is filled in later.

To my knowledge, with your validations as they are, I see no good working solution. Either you validate all, or you update the avatar without validations. If it would be a simple attribute, you could check if the new value passes the validation seperately, and then update the model without validations (e.g. using update_attribute).

I can suggest two possible alternative approaches:

  • either you make sure that the e-mail is always entered first, which I believe is not a bad solution. And then, with each save, the validation is met.
  • otherwise, change the validation. Why would you declare a validation on a model, if there are records in the database that do not meet the validation? That is very counter-intuitive.

So I would propose something like this:

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

Hope this helps.

浅黛梨妆こ 2024-12-08 01:31:25

这是我的解决方案。
它与 .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"]}

Here is my solution.
It keeps the same behaviour than .valid? method, witch returns true or false, and add errors on the model on witch it was called.

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"]}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文