ruby-on-railsseparation-of-concerns

Rails: Including a Concern with a constant within a Concern


I have concern in which I store constants:

module Group::Constants
  extend ActiveSupport::Concern

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

And another concern that I wish to use these constants:

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

Unfortunately, this results in a routing error:

uninitialized constant User::Groupable::MEMBERSHIP_STATUSES

It looks like the first concern isn't loading properly in the second concern. If that's the case, what can I do about it?


Solution

  • It appears this behavior is by design, as explained nicely over here.

    What you'll need to do in this case is not have Group::Constants extend from ActiveSupport::Concern since that will block its implementation from being shared with other ActiveSupport::Concern extending modules (although it will be ultimately shared in a class that includes the second module):

    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'
    

    In short, you'll need to make Group::Constants a standard module and then all will be well.