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

时间:2016-06-18 09:54:44

标签: ruby-on-rails ruby activesupport-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方法,因为当我加载时,我得到了Class:Class`的NoMethodError: undefined method organization_class'牙医模型。

2)我想在我甚至将该类传递给关注点(organizable organization_class: DentistClinic行)之前,将评估关注点内的关联,因此它无论如何都不会包含值。

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

这不是How to create a Rails 4 Concern that takes an argument

的副本

正在做几乎就是那篇文章中概述的内容。我的用例不同之处在于我正在尝试使用该参数来配置在Concern中定义的关联。

2 个答案:

答案 0 :(得分:1)

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

我发现的解决方案(在Rails 5.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之前对类方法进行评估和使用。

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

答案 1 :(得分:0)

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

import React from 'react';
import { listConnectionNames } from './where-ever-the-list-connection-name-file-is.js';

class App extends React.Component {
  state = {
    data: null
  };
  componentDidMount() {
    listConnectionNames().then((data) => {
      this.setState({
        data,
      });
    });
  };
  render() {
    console.log(this.state.data);
    return <div>Hello World</div>;
  };
}

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

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