我不是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预构建工具执行此操作,还是应该为此编写自定义库?
由于
答案 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
如果我花时间将这段代码包装在宝石或其他东西中,我会在这里报告。