ruby 将参数传递给关注点,用于关联

wgeznvg7  于 2022-12-22  发布在  Ruby
关注(0)|答案(3)|浏览(127)

我有一个Concern来建立一些常用的关联(还有其他一些事情),但是我需要根据使用这个Concern的类做一些小的调整。

module Organizable
  extend ActiveSupport::Concern

  included do
    has_many :person_organizations

    has_many :organizations,
             through:     :person_organizations,
             class_name:  <STI CLASS NAME HERE>
  end
end

如您所见,我希望能够在组织关联中更改类名。
我想我可以包含一些类方法来提供这种支持,但是我不知道如何获取这个值,下面是我自己使用它的方法:

class Dentist < Person
include Organizable
organizable organization_class: DentistClinic
end


下面是我当前的代码版本:

module Organizable
extend ActiveSupport::Concern

module ClassMethods
attr_reader :organization_class

private

def organizable(organization_class:)
  @organization_class = organization_class
end

end

included do
has_many :person_organizations

has_many :organizations,
         through:     :person_organizations,
         class_name:  self.class.organization_class.name

end
end


我认为这至少有两个问题:
1)`.organization_class`方法似乎没有在设置关联时定义,因为当我加载Dentist模型时,我将为Class:Class获取一个`NoMethodError: undefined method` organization_class。
2)我猜想在我将类传递给关注点(`organizable organization_class: DentistClinic`行)之前,关注点内部的关联将被求值,因此它无论如何都不会包含值。
我真的不知道如何解决这个问题。有没有办法将这个参数传递给关注点,并使用这个值设置关联?
这不是[How to create a Rails 4 Concern that takes an argument](https://stackoverflow.com/questions/26900356)的副本
我所做的和那篇文章中所描述的差不多,我的用例是不同的,因为我试图使用参数来配置一个在关注点中定义的关联。
vsmadaxz

vsmadaxz1#

我也遇到过类似的问题,需要根据Model本身的参数在Concern内部定义自定义关联。
我找到的解决方案(在Rails5.2中测试过,但其他版本应该类似)是在类方法内部定义关系,类似于Mirza建议的答案。
下面是代码的一个示例:

require 'active_support/concern'

module Organizable
  extend ActiveSupport::Concern

  included do
    has_many :person_organizations
  end

  class_methods do
    def organization_class_name(class_name)
      has_many :organizations,
            through: :person_organizations,
            class_name: class_name
    end
  end
end

模型:

class Dentist < Person
  include Organizable
  organization_class_name DentistClinic
end

我也希望完全按照您在回答中建议的那样做,看起来更干净,但这需要在included do之前计算和使用类方法。
基本上,我需要的是一种在关联定义中使用关注点参数的方法,这是最直接的方法,如果有人需要,我就把它放在这里。

qhhrdooz

qhhrdooz2#

一种解决方案是将动态模块包含到类中。

module Organizable
  extend ActiveSupport::Concern

  def organizable(klass)
    Module.new do
      extend ActiveSupport::Concern

      included do
        has_many :person_organizations

        has_many :organizations,
                 through:     :person_organizations,
                 class_name:  klass
      end
    end
  end
end

还没有测试过,但应该可以。

class Dentist < Person
  extend Organizable

  include organizable(DentistClinic)
end
eni9jsuy

eni9jsuy3#

您可以尝试以下操作:

module Organizable
  extend ActiveSupport::Concern

  module ClassMethods
   included do
     has_many :person_organizations
   end

   def organizable(class_name)  
     has_many :organizations, through: :person_organizations, class_name: class_name
   end
  end
end

然后:

class Dentist < Person
  include Organizable
  organizable DentistClinic
end

相关问题