如何为ActiveRecord模型定义合成属性?

时间:2009-09-07 06:26:39

标签: ruby-on-rails ruby activerecord model

我有一个ActiveRecord模型,其 字段来自数据库。还有其他属性,来自嵌套的序列化blob。这样做是为了让我可以使用表单中的这些属性,而不必跳过箍(或者我在开始时考虑过),同时允许向前和向后兼容,而无需编写复杂的迁移。

基本上我这样做:

class Licence < ActiveRecord::Base
  attr_accessor :load_worker_count
  strip_attributes!

  validates_numericality_of :load_worker_count,
    :greater_than => 2, :allow_nil => true, :allow_blank => true

  before_save :serialise_fields_into_properties

  def serialise_fields_into_properties
    ...
  end

  def after_initialize
    ...
  end

  ...
end

我注意到的问题是我无法在:load_worker_count中获得验证者接受的空值,因为:

  • 如果我省略:allow_blank,则无法通过验证将其归为空白
  • 如果我输入:allow_blank,它会将空白转换为0,而:greater_than => 2
  • 时会失败

在追踪这些空白值首先进入验证阶段的原因时,我发现了问题的根源: strip_attributes!仅影响{{1}返回的实际属性方法。因此验证时应为零的值不是。因此,感觉就像根本原因是在设置剥离属性时看不到我添加的合成属性,因此我要问:

是否有正确的方法来创建合成属性,这些属性被与ActiveRecord集成的其他代码识别为正确的属性?

2 个答案:

答案 0 :(得分:1)

我假设你在谈论strip_attributes插件;查看代码时,它使用在active_record / base.rb中定义的方法attributes,该方法使用@attributes,它被初始化(在initialize中)为@attributes = attributes_from_column_definition。< / p>

也许有可能以某种方式破解ActiveRecord :: Base,但这将是一项艰苦的工作:{/ 1}}在从/向db发送/放入内容时也会使用,所以你必须做很多黑客攻击

有一个更简单的解决方案:

@attributes

毕竟,这就是strip_attributes!确实

答案 1 :(得分:1)

在这里使用Rails的序列化宏会不会更容易?

class License < ActiveRecord::Base
  serialize :special_attributes
end

现在您可以为special_attributes分配一个哈希或数组或任何您需要的东西,Rails会将它序列化为数据库中的文本字段。

license = License.new
license.special_attributes = { :beer => true, :water => false }

这将保持您的代码清洁,您不必担心自己序列化/反序列化属性。