Possible to use `attribute` with `store_accessor`

时间:2016-07-11 19:25:56

标签: ruby-on-rails ruby-on-rails-5

In Rails 5, is it possible to use the new attributes API with a field exposed via store_accessor on a jsonb column?

For example, I have:

class Item < ApplicationRecord
  # ...
  store_accessor :metadata, :publication_date
  attribute :publication_date, :datetime
end

Then I'd like to call i = Item.new(publication_date: '2012-10-24'), and have metadata be a hash like: { 'publication_date' => #<DateTimeInstance> }.

However, the attribute call doesn't seem to be doing any coercion.

Hopefully I am missing something--it seems like being able to use these two features in conjunction would be very useful when working with jsonb columns. (Speaking of which, why doesn't the attributes API expose a generic array: true option? That would also be very useful for this case.)

1 个答案:

答案 0 :(得分:1)

在进一步挖掘之后,我发现属性API(因为它当前存在于ActiveRecord中)不适合处理jsonb数据 - attributes哈希中会有重复的信息等等。

我认为如果ActiveRecord为jsonb字段提供了类型转换/强制效果会很好。我看到有一个项目jsonb_accessor,但它似乎有点重量级。它似乎也是为Rails 4设计的(我还没有检查它是否支持Rails 5)。

我想这样的事情可能适用于Rails,因为ActiveRecord::Type值实际上是在ActiveModel中定义的。

目前我正在使用以下内容。我从来没有真正爱过Hashie,但它相对轻巧且易于使用:

class Item < ApplicationRecord
  class Metadata < Hashie::Dash

    include Hashie::Extensions::Dash::Coercion
    include Hashie::Extensions::Dash::IndifferentAccess

    property :publication_date, coerce: Time

    def self.dump(obj); obj.as_json; end
    def self.load(obj); new(obj); end

  end

  serialize :metadata, Metadata
  store_accessor :metadata, :publication_date
end