加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – 如何在Rails before_save钩子中正确处理更改的

发布时间:2020-12-17 04:37:58 所属栏目:百科 来源:网络整理
导读:我有一个看起来像这样的模型: class StopWord ActiveRecord::Base UPDATE_KEYWORDS_BATCH_SIZE = 1000 before_save :update_keywords def update_keywords offset = 0 max_id = ((max_kw = Keyword.first(:order = 'id DESC')) and max_kw.id) || 0 while o
我有一个看起来像这样的模型:
class StopWord < ActiveRecord::Base
  UPDATE_KEYWORDS_BATCH_SIZE = 1000

  before_save :update_keywords

  def update_keywords
    offset = 0
    max_id = ((max_kw = Keyword.first(:order => 'id DESC')) and max_kw.id) || 0
    while offset <= max_id
      begin
        conditions = ['id >= ? AND id < ? AND language = ? AND keyword RLIKE ?',offset,offset + UPDATE_KEYWORDS_BATCH_SIZE,language]

        # Clear keywords that matched the old stop word
        if @changed_attributes and (old_stop_word = @changed_attributes['stop_word']) and not @new_record
          Keyword.update_all 'stopword = 0',conditions + [old_stop_word]
        end

        Keyword.update_all 'stopword = 1',conditions + [stop_word]

      rescue Exception => e
        logger.error "Skipping batch of #{UPDATE_KEYWORDS_BATCH_SIZE} keywords at offset #{offset}"
        logger.error "#{e.message}: #{e.backtrace.join "n    "}"

      ensure
        offset += UPDATE_KEYWORDS_BATCH_SIZE
      end
    end
  end
end

这个工作正常,因为单元测试显示:

class KeywordStopWordTest < ActiveSupport::TestCase
  def test_stop_word_applied_on_create
    kw = Factory.create :keyword,:keyword => 'foo bar baz',:language => 'en'
    assert !kw.stopword,'keyword is not a stop word by default'

    sw = Factory.create :stop_word,:stop_word => kw.keyword.split(' ')[1],:language => kw.language
    kw.reload
    assert kw.stopword,'keyword is a stop word'
  end

  def test_stop_word_applied_on_save
    kw = Factory.create :keyword,:language => 'en',:stopword => true
    sw = Factory.create :keyword_stop_word,:language => kw.language

    sw.stop_word = 'blah'
    sw.save

    kw.reload
    assert !kw.stopword,'keyword is not a stop word'
  end
end

但是使用@changed_attributes实例变量感觉很糟糕.是否有标准的Rails-y方法来获取正在保存时修改的属性的旧值?

更新:感谢Douglas F Shearer和Simone Carletti(显然更喜欢墨菲的吉尼斯),我有一个更清洁的解决方案:

def update_keywords
    offset = 0
    max_id = ((max_kw = Keyword.first(:order => 'id DESC')) and max_kw.id) || 0
    while offset <= max_id
      begin
        conditions = ['id >= ? AND id < ? AND language = ? AND keyword RLIKE ?',language]

        # Clear keywords that matched the old stop word
        if stop_word_changed? and not @new_record
          Keyword.update_all 'stopword = 0',conditions + [stop_word_was]
        end

        Keyword.update_all 'stopword = 1',conditions + [stop_word]

      rescue StandardError => e
        logger.error "Skipping batch of #{UPDATE_KEYWORDS_BATCH_SIZE} keywords at offset #{offset}"
        logger.error "#{e.message}: #{e.backtrace.join "n    "}"

      ensure
        offset += UPDATE_KEYWORDS_BATCH_SIZE
      end
    end
  end

多谢你们!

解决方法

你想要ActiveModel :: Dirty.

例子:

person = Person.find_by_name('Uncle Bob')
person.changed?       # => false

person.name = 'Bob'
person.changed?       # => true
person.name_changed?  # => true
person.name_was       # => 'Uncle Bob'
person.name_change    # => ['Uncle Bob','Bob']

完整文档:http://api.rubyonrails.org/classes/ActiveModel/Dirty.html

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读