12

With Rails concerns I can give my model class methods and instance methods through modules by including them. No blog entry or thread that I've found mentions how I can include variables in my model though.

Specifically I would like to give my including model a class instance variable @question, but I don't know where to put the declaration in the module so it is applied. I would also like the class instance variable to be overridden if the model itself declares that variable.

Does the ActiveSupport::Concern module actually care about variables at all?

module ContentAttribute
    extend ActiveSupport::Concern

    def foo
        p "hi"
    end

    module ClassMethods

        # @question = "I am a generic question." [doesn't work]

        def bar
            p "yo"
        end
    end
end 

class Video < ActiveRecord::Base
    include ContentAttribute

    # @question = "Specific question"; [should override the generic question]
end
ZeroMax
  • 369
  • 4
  • 13

1 Answers1

21
module ContentAttribute
  extend ActiveSupport::Concern

  included do
    self.question = "I am a generic question."
  end

  module ClassMethods
    attr_accessor :question
  end

end

Then, in video...

class Video < ActiveRecord::Base
  include ContentAttribute
  self.question = "Specific question"
end
Mark Swardstrom
  • 17,217
  • 6
  • 62
  • 70
  • Isn't `after_initialize` called when an object is created? Wouldn't make your solution `question` an instance variable? – ZeroMax Mar 13 '15 at 03:35
  • Yes - it would be an instance variable. when they start with @, they are also instance variables. Are you trying to create class variables? – Mark Swardstrom Mar 13 '15 at 18:13
  • Yes, I want to to create a _class_ instance variable (as stated in the title of my question). One that I can call with `Video.question`. – ZeroMax Mar 14 '15 at 18:43
  • Sorry about that - I hadn't heard of class variables referred to as _class instance _variables, learned something new. – Mark Swardstrom Mar 15 '15 at 21:44
  • In fact I had learned about this notion on stackoverflow. There are "real" class variables like `@@question` and there are class _instance_ variables (since in ruby even classes are objects), like `@question`. You have to distinguish between them because they behave different. – ZeroMax Mar 17 '15 at 11:23
  • Now unfortunately, your altered answer is about class variables and not class _instance_ variables. ^^ – ZeroMax Mar 17 '15 at 11:26
  • I see. Trying one last answer. This one has a slight problem, though. A subclass will not get the default question without including the concern. It's nil for a subclass, but otherwise works for the including classes. – Mark Swardstrom Mar 17 '15 at 17:47
  • That's what I've been looking for and it works. As I will not do any subclassing this is perfect. Thank you! – ZeroMax Mar 17 '15 at 18:16
  • Also I found out that this behaviour is indeed enabled by the `ActiveSupport::Concern` module. Doing something aequivalent with the `self.included(base)` method of a module will not work. – ZeroMax Mar 17 '15 at 21:43