ActiveModel :: Dirty仅监视特定字段

时间:2015-06-01 11:25:26

标签: ruby-on-rails activerecord

我不是100%确定为什么ActiveModel::Dirty有它的名字。我猜这是因为 被认为是 dirty 才能使用它。

但在某些情况下,无法避免在特定领域观看。

例如:

if self.name_changed?
  self.slug = self.name.parameterize
end

如果没有ActiveModel::Dirty,代码将如下所示:

if old_name != self.name
  self.slug = self.name.parameterize
end

这意味着之前存储了old_name,并且它不可读,所以恕我直言,它比使用ActiveModel::Dirty 更脏。如果old_number是一个数字并且等于params[:user]['old_number'],则需要正确格式化(解析为int),而ActiveRecord会自动执行此操作,这会变得更糟。

所以我会发现在模型级别定义可观察字段的干净:

class User < ActiveRecord::Base
  include ActiveModel::Dirty

  watchable_fields :name

  before_save :generate_slug, if: name_changed?

  def generate_slug
    self.slug = self.name.parameterize
  end

end 

或者(甚至更好?)在控制器级别,在分配新值之前:

def update
  @user = current_user
  @user.watch_fields(:name)

  @user.assign_attributes(params[:user])

  @user.generate_slug if @user.name_changed?
  @user.save # etc.
end

这里的好处是它消除了使用ActiveModel::Dirty生成的内存重载。

所以我的问题是:

我可以使用ActiveRecord预构建工具执行此操作,还是应该为此编写自定义库?

由于

2 个答案:

答案 0 :(得分:1)

如果ActiveModel::Dirty解决了您的问题,请随时使用。该名称来自术语“脏对象”,并不意味着暗示它是一个脏/ hackish模块。 有关脏对象的更多详细信息,请参阅此答案:What is meant by the term "dirty object"?

答案 1 :(得分:0)

这就是我最终做的事情。我喜欢它:

class User < ActiveRecord::Base

  attr_accessor :watched

  def field_watch(field_name)
    self.watched ||= {}
    self.watched[field_name] = self.send(field_name)
    return self
  end

  def field_changed?(field_name)
    self.send(field_name) != self.watched(field_name)
  end
end

在控制器中

def update
  @user = current_user.field_watch(:name)
  @user.assign_attributes(params[:user])
  @user.generate_slug if @user.field_changed?(:name)
  @user.save
end

如果我花时间将这段代码包装在宝石或其他东西中,我会在这里报告。