【问题标题】:How to update attributes without validation如何在没有验证的情况下更新属性
【发布时间】:2011-03-01 05:43:06
【问题描述】:

我有一个带有验证的模型,但我发现如果不验证之前的对象,我就无法更新属性。

我已经尝试在每个验证行的末尾添加 on => :create 语法,但得到了相同的结果。

我的公告模型具有以下验证:

  validates_presence_of :title
  validates_presence_of :description
  validates_presence_of :announcement_type_id

  validate :validates_publication_date
  validate :validates_start_date
  validate :validates_start_end_dates
  validate :validates_category
  validate :validates_province

  validates_length_of :title, :in => 6..255, :on => :save
  validates_length_of :subtitle, :in => 0..255, :on => :save
  validates_length_of :subtitle, :in => 0..255, :on => :save
  validates_length_of :place, :in => 0..50, :on => :save

  validates_numericality_of :vacants, :greater_than_or_equal_to => 0,  :only_integer => true
  validates_numericality_of :price, :greater_than_or_equal_to => 0,  :only_integer => true

我的 rake 任务执行以下操作:

  task :announcements_expiration => :environment do
    announcements = Announcement.expired

    announcements.each do |a|
      #Gets the user that owns the announcement
      user = User.find(a.user_id)
      puts a.title + '...'

      a.state = 'deactivated'

      if a.update_attributes(:state => a.state)
        puts 'state changed to deactivated'
      else
        a.errors.each do |e|
          puts e
        end

      end
    end

这会在输出中引发该模型的所有验证异常。

有人如何在不验证模型的情况下更新属性?

【问题讨论】:

    标签: ruby-on-rails validation


    【解决方案1】:

    你可以这样做:

    object.attribute = value
    object.save(:validate => false)
    

    【讨论】:

    • 其实它的 object.save(:validate => false)
    • object.attributes = hash 更符合这个问题。如果有人想知道,update_attributes(hash) 本身只是 self.attributes = hash; save
    • object.save(false) 是使用 Rails 2 及以下版本的所有功能
    • 这样更好,因为它仍然会执行更新时间戳的回调。该操作特别提到避免验证,而不是所有回调。
    • 通过这样做,下一个开发人员也更清楚明确不需要验证
    【解决方案2】:

    使用update_attribute 而不是update_attributes

    更新单个属性并保存记录,无需经过正常的验证过程。

    if a.update_attribute('state', a.state)
    

    注意:-“update_attribute”一次只更新一个属性,我认为它对你有用。

    【讨论】:

    • 无需验证即可使用 save(false)
    • update_attribute 在 Rails 4 中被弃用,仅供参考。尝试使用 a.attributes({ ... }).save(false) 代替。或者,如果您不关心(或不希望)运行回调,请查看 update_column
    • 对于 Rails 4,save(false) 不起作用,您必须使用 save(validate: false)
    • @JoshPinter Hm, update_attribute 在 Rails 4.2 中似乎没有被弃用(别名为 update_column):api.rubyonrails.org/classes/ActiveRecord/…
    • @TončiD。哇,你完全正确。看起来他们打算在 3.2 中弃用它并在 4.0 中删除它,但后来决定撤销他们的决定,因为它不能与 update_column 互换。两年可以改变很多! :) 感谢您指出。在此处阅读更多信息:groups.google.com/forum/?hl=en&fromgroups#!topic/…
    【解决方案3】:

    尝试使用

    @record.assign_attributes({ ... })
    @record.save(validate: false)
    

    为我工作

    【讨论】:

    • 这是 Rails 4 的有效答案,是当前接受答案的所有 cmets 的组合。
    • @record.tap { |r| r.assign_attributes({ ... }) }.save(validate: false) 如果您愿意,只需一行代码即可。
    【解决方案4】:

    你可以使用:

    a.update_column :state, a.state
    

    检查:http://apidock.com/rails/ActiveRecord/Persistence/update_column

    更新对象的单个属性,而不调用 save。

    【讨论】:

    • 如果您想跳过验证和回调,这是最好的方法。如果您要更新多个属性,还有update_columns
    【解决方案5】:

    当我们使用validate: false时,所有来自模型的验证都会被跳过

    user = User.new(....)
    user.save(validate: false)
    

    【讨论】:

      【解决方案6】:

      不应该是这样的

      validates_length_of :title, :in => 6..255, :on => :create
      

      所以它只在创建期间有效?

      【讨论】:

      • 操作员说:I already tried to add on => :create syntax at the end of each validation line, but I got the same results.
      猜你喜欢
      • 2018-04-15
      • 1970-01-01
      • 2012-09-28
      • 2011-09-02
      • 1970-01-01
      • 2021-02-10
      • 2014-12-04
      • 2018-08-29
      • 2018-03-06
      相关资源
      最近更新 更多