Rails:包括对一个关注点内的常数的关注

时间:2013-04-11 15:50:51

标签: ruby-on-rails separation-of-concerns

我担心存储常量:

module Group::Constants
  extend ActiveSupport::Concern

  MEMBERSHIP_STATUSES = %w(accepted invited requested
    rejected_by_group rejected_group)
end

另一个关注我希望使用这些常量:

module User::Groupable
  extend ActiveSupport::Concern
  include Group::Constants

  MEMBERSHIP_STATUSES.each do |status_name|
    define_method "#{status_name}_groups" do
      groups.where(:user_memberships => {:status => status_name})
    end
  end
end

不幸的是,这会导致路由错误:

uninitialized constant User::Groupable::MEMBERSHIP_STATUSES

看起来第一个问题是在第二个问题中没有正确加载。如果是这样的话,我该怎么办呢?

2 个答案:

答案 0 :(得分:29)

看来这种行为是设计的,正如here所解释的那样。

在这种情况下,您需要做的是Group::ConstantsActiveSupport::Concern延伸,因为这会阻止其实现与其他ActiveSupport::Concern扩展模块共享(尽管它会最终在包含第二个模块的类中共享:

module A
  TEST_A = 'foo'
end

module B
  extend ActiveSupport::Concern
  TEST_B = 'bar'
end

module C
  extend ActiveSupport::Concern
  include A
  include B
end

C::TEST_A 
=> 'foo'
C::TEST_B 
=> uninitialized constant C::TEST_B

class D
  include C
end

D::TEST_A 
=> 'foo'
D::TEST_B 
=> 'bar'

简而言之,您需要将Group::Constants作为标准模块,然后一切都会好起来。

答案 1 :(得分:0)

如果要将所有内容保存在一个文件中,并且可以忍受一些样板,则可以将模块分为“关注”位和“无关”位:

module A
  FOO = [22]

  def self.included base
    base.include Concern
  end

  module Concern
    extend ActiveSupport::Concern

    class_methods do
      def foo_from_the_perspective_of_a_class_method_in_A
        {lexical: FOO, instance: self::FOO}
      end
    end
  end
end

module B
  extend ActiveSupport::Concern

  include A

  FOO += [33]

  def foo_from_the_perspective_of_an_instance_method_in_B
    FOO
  end
end

class C
  include B
end


C.foo_from_the_perspective_of_a_class_method_in_A
=> {:lexical=>[22], :instance=>[22, 33]}
C.new.foo_from_the_perspective_of_an_instance_method_in_B
=> [22, 33]
C::FOO
=> [22, 33]