Rails 4 concerns: Give class instance variables to model
Asked Answered
F

1

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
Frizz answered 11/3, 2015 at 14:40 Comment(5)
Can you add an included block and put @question = ... inside?Taraxacum
You mean like included do; @question = "This is a generic question."; end ? No, I still get a NoMethodError on Video.question (I defined an attr_accessor :question in the video model.)Frizz
How about adding attr_accessor :question in the included blockTaraxacum
Nope, still the same. I doubted that would have changed anything.Frizz
Video.question is a class method, it should throw an errorTaraxacum
T
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
Taraxacum answered 12/3, 2015 at 22:4 Comment(9)
Isn't after_initialize called when an object is created? Wouldn't make your solution question an instance variable?Frizz
Yes - it would be an instance variable. when they start with @, they are also instance variables. Are you trying to create class variables?Taraxacum
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.Frizz
Sorry about that - I hadn't heard of class variables referred to as _class instance _variables, learned something new.Taraxacum
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.Frizz
Now unfortunately, your altered answer is about class variables and not class instance variables. ^^Frizz
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.Taraxacum
That's what I've been looking for and it works. As I will not do any subclassing this is perfect. Thank you!Frizz
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.Frizz

© 2022 - 2024 — McMap. All rights reserved.