ActiveModel 字段未映射到访问器

发布于 2024-12-07 04:43:16 字数 1013 浏览 0 评论 0原文

使用 Rails 3 和 ActiveModel,我无法使用 self.语法来获取基于 ActiveModel 的对象内的属性值。

在下面的代码中,在 save 方法中, self.first_name 的计算结果为 nil,其中 @attributes[:first_name] 的计算结果为 'Firstname' (初始化对象时从控制器传入的值)。

在 ActiveRecord 中,这似乎有效,但在 ActiveModel 中构建相同的类时,却不起作用。如何在基于 ActiveModel 的类中使用访问器来引用字段?

class Card
  include ActiveModel::Validations
  extend ActiveModel::Naming 
  include ActiveModel::Conversion
  include ActiveModel::Serialization
  include ActiveModel::Serializers::Xml

  validates_presence_of :first_name

  def initialize(attributes = {})
    @attributes = attributes
  end

  #DWT TODO we need to make sure that the attributes initialize the accessors properyl, and in the same way they would if this was ActiveRecord
  attr_accessor :attributes, :first_name

  def read_attribute_for_validation(key)
    @attributes[key]
  end

  #save to the web service
  def save
    Rails.logger.info "self vs attribute:\n\t#{self.first_name}\t#{@attributes["first_name"]}"
  end

  ...

end

Using Rails 3 and ActiveModel, I am unable to use the self. syntax to get the value of an attribute inside an ActiveModel based object.

In the following code, in save method, self.first_name evaluates to nil where @attributes[:first_name] evaluates to 'Firstname' (the value passed in from the controller when initializing the object).

In ActiveRecord this seems to work, but when building the same class in ActiveModel, it does not. How do you refer to a field using accessors in an ActiveModel based class?

class Card
  include ActiveModel::Validations
  extend ActiveModel::Naming 
  include ActiveModel::Conversion
  include ActiveModel::Serialization
  include ActiveModel::Serializers::Xml

  validates_presence_of :first_name

  def initialize(attributes = {})
    @attributes = attributes
  end

  #DWT TODO we need to make sure that the attributes initialize the accessors properyl, and in the same way they would if this was ActiveRecord
  attr_accessor :attributes, :first_name

  def read_attribute_for_validation(key)
    @attributes[key]
  end

  #save to the web service
  def save
    Rails.logger.info "self vs attribute:\n\t#{self.first_name}\t#{@attributes["first_name"]}"
  end

  ...

end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七七 2024-12-14 04:43:16

我想通了。我在对 Marian 的答案的评论中提到的“黑客”实际上就是 ActiveRecord 类的访问器的生成方式。这就是我所做的:

class MyModel
  include ActiveModel::AttributeMethods

  attribute_method_suffix  "="  # attr_writers
  attribute_method_suffix  ""   # attr_readers

  define_attribute_methods [:foo, :bar]

  # ActiveModel expects attributes to be stored in @attributes as a hash
  attr_reader :attributes

  private

  # simulate attribute writers from method_missing
  def attribute=(attr, value)
    @attributes[attr] = value
  end

  # simulate attribute readers from method_missing
  def attribute(attr)
    @attributes[attr]
  end
end

如果您查看 ActiveRecord 的源代码 (lib/active_record/attribute_methods/{read,write}.rb),您可以看到相同的内容。

I figured it out. The "hack" that I mentioned as a comment to Marian's answer actually turns out to be exactly how the accessors for ActiveRecord classes are generated. Here's what I did:

class MyModel
  include ActiveModel::AttributeMethods

  attribute_method_suffix  "="  # attr_writers
  attribute_method_suffix  ""   # attr_readers

  define_attribute_methods [:foo, :bar]

  # ActiveModel expects attributes to be stored in @attributes as a hash
  attr_reader :attributes

  private

  # simulate attribute writers from method_missing
  def attribute=(attr, value)
    @attributes[attr] = value
  end

  # simulate attribute readers from method_missing
  def attribute(attr)
    @attributes[attr]
  end
end

You can see the same thing if you look in ActiveRecord's source code (lib/active_record/attribute_methods/{read,write}.rb).

﹏半生如梦愿梦如真 2024-12-14 04:43:16

您需要 ActiveModel::AttributeMethods 为此

You need ActiveModel::AttributeMethods for that

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文