如何编写自定义的Rails协会?

时间:2019-03-02 20:06:37

标签: jsonb model-associations ruby-on-rails-5.2

如何为存储在jsonb中的关系编写Rails 5.2关联?

我在一些地方使用PostgreSQL jsonb来灵活地存储与其他模型的关系。例如,我们结合使用STI和jsonb来创建灵活的事件日志。

class Event < ApplicationRecord
  include HasJsonbAccessors
end

class Event::AddedUserToGroup < Event
  jsonb_belongs_to :user
  jsonb_belongs_to :group
end

class Event::UserPurchase < Event
  jsonb_belongs_to :user
  jsonb_belongs_to :order
end

借助jsonb_accessor,我们成功地将访问器和验证功能结合在一起。

module HasJsonbAccessors
  extend ActiveSupport::Concern

  class_methods do
    def jsonb_belongs_to(association, optional: false)
      association_id_field = "#{association}_id".to_sym
      association_class = association.to_s.classify.constantize

      jsonb_accessor :data,
        association_id_field => :integer

      validates association, presence: true unless optional

      define_method(association) do
        association_class.where(id: self.send(association_id_field)).first
      end

      define_method("#{association}=".to_sym) do |object|
        self.send("#{association_id_field}=".to_sym, object.id)
      end
    end
  end
end

另一个示例是一组灵活的过滤规则,可以潜在地使用任何模型的列表。我已经了解了has_many关系的基础。

class FilterRules < ApplicationRecord
  jsonb_accessor :rules,
    group_ids: [:integer, array: true],
    other_rule: :string,
    ...

  def groups
    return [] if !group_ids
    return Group.find(group_ids)
  end

  def groups=(groups)
    self.group_ids = groups.try(:map, &:id)
  end
end

但是,如果没有真正的联系,许多工具将无法在这些模型上使用。例如,ActiveAdmin和Formtastic需要一个真正的has_many关联。而且我们没有关系完整性或级联。

我看过activerecord-jsonb-associations,但它深入了Rails的胆量,被5.1-> 5.2超出我修复能力的更改所破坏。

是否有任何开始编写适当的自定义Rails关联的指针?

0 个答案:

没有答案