Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct use of concern's constants

Tags:

I have one concern and two classes which include it. In the concern, I defined one variable. Here is the concern and the two models:

module UserInstance   extend ActiveSupport::Concern    included do      ACTIVE = 'active'   end end  class Guardian < ActiveRecord::Base    include UserInstance  end  class Student < ActiveRecord::Base    include UserInstance  end 

I'm getting this warnings:

/app/app/models/concerns/user_instance.rb:12: warning: already initialized constant UserInstance::ACTIVE /app/app/models/concerns/user_instance.rb:12: warning: previous definition of ACTIVE was here 

I guess that once it loads one class (like Guardian), it also loads the constant, and loading the other class tries to load the constant again, and then the warning is given. How can I avoid this without having to put the constants in the two models? Thanks

like image 685
sauronnikko Avatar asked Sep 18 '14 22:09

sauronnikko


People also ask

How do you convert a string to a constant in Ruby?

No need to require ActiveSupport. Usage example: class User; def self. lookup; const_get('SomeClassName);end; end User. lookup will return class itself.

Do not define constants this way within a block?

Overview. Do not define constants within a block, since the block's scope does not isolate or namespace the constant in any way. If you are trying to define that constant once, define it outside of the block instead, or use a variable or method if defining the constant in the outer scope would be problematic.

How do I use a module in Ruby?

The method definitions look similar, too: Module methods are defined just like class methods. As with class methods, you call a module method by preceding its name with the module's name and a period, and you reference a constant using the module name and two colons.


2 Answers

I just came across the same bug, when trying to implement concerns.

The guide I was following also but the Constant in the included block and seemed to have no error. But my log threw me exactly the same error you have.

After some trial and error, I just removed the Constant from the block and put it outside, like:

module UserInstance   extend ActiveSupport::Concern    included do    end    ACTIVE = 'active' end 

This way I could still access the Constant, but didn't get anymore errors. I'm not 100% sure that this is the right way, but it worked and I couldn't find any errors, so I will go with it.

I would like to now if this works for you too!

like image 191
Thomas Avatar answered Nov 09 '22 01:11

Thomas


Using base solved the problem for me.

 module UserInstance   extend ActiveSupport::Concern    # https://api.rubyonrails.org/v6.0.0/classes/ActiveSupport/Concern.html#method-i-included   included do |base|     base.const_set :ACTIVE, "active"      # direct const creation in this included block will attach the const to the concern module, not the including class     # so if you have multiple classes including the same concern, it will try to difine the same const to the same module     # ACTIVE = "active"     end  end 
like image 22
kukrt Avatar answered Nov 08 '22 23:11

kukrt