【问题标题】:validate and update single attribute rails验证和更新单个属性栏
【发布时间】:2011-08-23 03:36:28
【问题描述】:

我的用户模型中有以下内容

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

【问题讨论】:

标签: ruby-on-rails activerecord rails-activerecord


【解决方案1】:

您可以使用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? 只查看您感兴趣的属性的验证失败。

如果你要做很多这样的事情,那么你可以向用户添加一个方法:

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

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

【讨论】:

  • 这也将检查电子邮件验证,只是不检查头像。
  • @Madhusudhan:您可以手动设置验证并使用update_attribute。请查看我的更新。
  • 上述逻辑中的第 4 行不应该是“return !mock.errors.has_key?(attr)”吗?
  • @FelafelWaffle:是的,那里缺少!。感谢您的提醒。
【解决方案2】:

条件?

validates_presence_of :email, :if => :email_changed?

【讨论】:

  • 太棒了。谢谢,我什至没有意识到你有这些方便的辅助函数!
【解决方案3】:

您是否尝试在 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 })。方法、过程或字符串应返回或评估为真或假值。

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

【讨论】:

    【解决方案4】:

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

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

    希望这会有所帮助。

    【讨论】:

    • errors.add(:email, "Email is required") 生成错误 = "Email Email is required"。将“需要电子邮件”更改为“需要”
    【解决方案5】:

    这是我的解决方案。 它保持与 .valid? 方法相同的行为,witch 返回 true 或 false,并在其被调用的 ww 上的模型上添加错误。

    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"]}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-15
      • 2012-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多