3

我有一个关注来设置一些常用的关联(除其他外),但我需要根据使用关注的类进行一些小的调整。我的基本顾虑是这样的:

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在建立关联时似乎没有定义该方法,因为NoMethodError: undefined method当我加载 Dentist 模型时,我得到了 Class:Class` 的 organization_class'。

2)我猜在我什至将类传递给关注点(organizable organization_class: DentistClinic行)之前,关注点内部的关联将被评估,所以它无论如何都不包含值。

我真的不确定如何解决这个问题。有没有办法将此参数传递给关注点并使用此值设置关联?


这不是如何创建带参数的 Rails 4 关注点的副本

所做的几乎与那篇文章中概述的完全一样。我的用例有所不同,因为我试图使用参数来配置在 Concern 中定义的关联。

4

2 回答 2

4

我遇到了类似的问题,我需要根据模型本身的参数在 Concern 中定义自定义关联。

我找到的解决方案(在 Rails 5.2 中测试,但其他版本应该类似)是在类方法中定义关系,类似于 Mirza 建议的答案。

这是代码的示例,The Concern:

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

基本上我需要的是一种在关联定义中使用关注参数的方法,这是最直接的方法,如果有人需要,我将它留在这里。

于 2018-08-25T16:02:54.083 回答
0

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

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
于 2018-08-25T18:00:03.043 回答