【问题标题】:Rails: How to retrieve the polymorphic '_type' column name for a polymorphic model dynamically?Rails:如何动态检索多态模型的多态“_type”列名?
【发布时间】:2015-11-12 15:14:43
【问题描述】:

我基本上想创建一个将包含在所有多态模型中的关注点。这个问题需要有一个动态的 setter 方法来设置 '_type' 列的值。

module StiPolymorphable
  extend ActiveSupport::Concern

  included do
    define_method "#{magic_method_to_get_type_column}=" do |type_field|
      super(type_field.to_s.classify.constantize.base_class.to_s)
    end
  end
end

我基本上想访问 Parent 实例而不是 Person 实例的所有地址。

示例 - 假设我有以下课程

class Person < ActiveRecord::Base
end

class Parent < Person end
class Teacher < Person end

class Address < ActiveRecord::Base
  include StiPolymorphable

  belongs_to :addressable, polymorphic: true
end

现在,如果我尝试访问 Parent 的地址,它会给我零个记录,因为 addressable_type 字段包含值“Person”。

 Parent.first.addresses => #<ActiveRecord::Associations::CollectionProxy []> 
 Person.first.addresses => #<ActiveRecord::Associations::CollectionProxy [#<Address id: .....>]> 

【问题讨论】:

  • 您能否详细说明您将如何使用该模块?
  • 我基本上是在尝试将这个模块包含在我的应用程序的所有多态模型中,这些模型可以属于 STI 模型。
  • @MaxWilliams 我试图让多态实例访问所属 STI 模型的基类。如果这有任何意义的话。我将编辑问题以提供更好的示例。
  • 您能否创建一个示例来说明您想要的结果。也许将 STI 模型示例添加到 OP。
  • @usmanali,为了清楚起见,我添加了一个示例

标签: ruby-on-rails ruby ruby-on-rails-4 polymorphism metaprogramming


【解决方案1】:

我们这样做:

module Shared::PolymorphicAnnotator
  extend ActiveSupport::Concern

  class_methods do
    # @return [String]
    #    the polymorphic _id column
    def annotator_id
      reflections[annotator_reflection].foreign_key.to_s
    end

    # @return [String]
    #    the polymorphic _type column
    def annotator_type
      reflections[annotator_reflection].foreign_type
    end 
  end

  included do
    # Concern implementation macro
    def self.polymorphic_annotates(polymorphic_belongs, foreign_key = nil)
      belongs_to polymorphic_belongs.to_sym, polymorphic: true, foreign_key: (foreign_key.nil? ? (polymorphic_belongs.to_s + '_id').to_s : polymorphic_belongs.to_s)
      alias_attribute :annotated_object, polymorphic_belongs.to_sym 

      define_singleton_method(:annotator_reflection){polymorphic_belongs.to_s} 
    end

    attr_accessor :annotated_global_entity 

    # @return [String]
    #   the global_id of the annotated object
    def annotated_global_entity
      annotated_object.to_global_id if annotated_object.present?
    end

    # @return [True]
    #    set the object when passed a global_id String
    def annotated_global_entity=(entity)
      o = GlobalID::Locator.locate entity

      write_attribute(self.class.annotator_id, o.id)
      write_attribute(self.class.annotator_type, o.class.base_class)
      true
    end
  end
end

在您的模型中:

class Foo
   include Shared::PolymorphicAnnotator
   polymorphic_annotates('belongs_to_name', 'foreign_key')
 end

【讨论】:

    【解决方案2】:

    您可能有兴趣查看Modularity gem,以便在包含模块时传递变量。虽然还没有真正尝试过。希望对您有所帮助。

    【讨论】:

    • 现在这对我帮助不大。不过还是谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    相关资源
    最近更新 更多