论坛首页 编程语言技术论坛

ActiveRecord::Base column_changed?

浏览 4266 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-09-28  
有一个需求。

需要在model的before_save里面判断某个column的值是否改过了(对于数据库中的值来讲)。然后在model的before_save里面用这样的语句:do_something if self.column_changed?(:name)

似乎Rails本身没有一个column_changed?方法,也没找到现成的plugin。

自己hack了一下ActiveRecord::Base,在find以后把当前对象的attributes再duplicate一份,虽然可以用,希望知道更好的方法。
   发表时间:2007-09-28  
忘了贴代码:
module Tracking
  def self.included(base) # hack by include
    base.extend(ClassMethods)
    base.class_eval do
      class << self
        alias_method_chain :instantiate, :tracking # to hack instantiate
      end
    end
  end

  module ClassMethods
    # find函数就是调用instantiate把db columns data转成attributes的
    def instantiate_with_tracking(record) 
      object = instantiate_without_tracking(record)
      object.instance_variable_set("@db_attributes", object.attributes.dup)
      object
    end
  end

  # instant method compares db_attributes and attributes
  def column_changed?(column)
    db_attributes[column.to_s] != attributes[column.to_s]
  end

  private
  attr_accessor :db_attributes
end

ActiveRecord::Base.class_eval do
  include Tracking
end
0 请登录后投票
   发表时间:2007-09-29  
有插件啊:http://agilewebdevelopment.com/plugins/acts_as_modified
只是不知道还有没有在继续维护
0 请登录后投票
   发表时间:2007-10-01  
找的就是它。谢谢啦!

看了下它的代码,做的方式跟我的一样,不过考虑得更周到。
0 请登录后投票
   发表时间:2007-10-05  
又发现一个类似的plugin: changed_attributes
http://blog.behindlogic.com/2007/08/rails-plugin-changedattributes.html

为ActiveRecord添加了以下实例方法:
引用

revert - forget all changes since the last save, reverting to the value each attribute originally had.

reset - an alias for revert.

revert_attribute - roll back the value of just one attribute to its original value.

reset_attribute - alias for revert_attribute.

original_attributes - returns all the attributes' values as of the last save, or the default values if the object is unsaved.

changed_attributes - returns only the attributes whose values have changed.

changed_attribute_names - returns an array of the attributes whose values have changed.

attribute_changed?(attr_name) - will tell you if the value of attribute 'attr_name' has been modified.

attr_changed?(attr_name) - alias for attribute_changed?.

has_attribute?(attr_name) - see if an object has this attribute.

exists? - see if an object exists in the database. This isn't commonly useful, but if you ever come across a case where you don't know if an object was deleted or not, #new_record? will return false, but exists? will tell you whether or not this record actually exists in the database.(刚好之前看到mail-list上有人问怎么判断一个ar object是否被删除了,正好这个一并解决了)



感觉有人会很喜欢其中的 save_if_modified 方法

作者说他主要用来实现一些validations,如:
引用

validate_attribute_not_changed
validate_attribute_changed
validate_attribute_incremented_by(some_number)


不过作者的实现似乎有点问题,他推荐用“替代”法来安装:
http://blog.behindlogic.com/2007/09/changedattributes-plugin-alternate.html

他应该比acts_as_modified 活跃,你可以试用看看然后谈谈用后感
0 请登录后投票
   发表时间:2007-10-08  
按照你的介绍,这个plugin应该是更强大的。revert,save_if_modified,validations都是卖点。可惜我这里连不上,过两天再试。

save_if_modified的确可以省一些数据库访问。但我认为理想的情况是应该由Rails本身来做这个判断。当我调用.save的时候,Rails判断if !modified就不执行sql。这样是更直观的方式。号称Rails目前的开发方向是更多考虑性能,不知道会不会考虑这种空间换时间的做法,如果考虑的话,就不用费心装插件了。

对于目前的需求来讲,自己写的那几行代码已经足够,等有更深需求的时候,会仔细研究它,先收藏了。谢谢。
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics