Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What should I not include in the `included do ... end` block?

I am using Ruby on Rails 3.2.2. I am implementing a module and including that in a my class by using the RoR ActiveSupport::Concern feature. It makes available the included do ... end block making code stated inside that to be executed in the class context of the class where the module is included.

My doubt is: What should I not include in the included do ... end block? That is, for instance, is it a "common" / "good" practice to make the following?

module MyModule
  extend ActiveSupport::Concern

  class MyModuleClass
    attr_accessor :attr1, :attr2, :attr3

    def initialize(attrs)
     @attr1 = attrs[:attr1]
     @attr2 = attrs[:attr2]
     @attr3 = attrs[:attr3]
    end
  end

  included do
    @my_module_class = MyModuleClass.new(some_attrs)
  end
end

More, will be the @my_module_class variable available as an attribute in the including class of MyModule (BTW: I would like to make the @my_module_class to be "visible" only internally to MyModule since it is intended to be used only in that module)? Are there some "advanced" examples or tutorials on how to handle situations like that I am trying to instantiate in the included do ... end block of the above code? What do you advice about?

like image 407
user12882 Avatar asked Oct 18 '12 15:10

user12882


People also ask

What is ActiveSupport concern?

It is a bit of Rails carbohydrates sprinkled upon a Ruby module. What ActiveSupport::Concern does for you is it allows you to put code that you want evaluated inside the included block. For example, you want to extract the trashing logic out of your model.

What does Included do in Ruby?

include is the standard Ruby idiom for mixing in methods from a module to a class and you should stick to it.

Why do we use begin and end in Ruby?

Ruby's BEGIN and END blocks (in uppercase) are reserved keywords in Ruby and are pretty straightforward to use. They enable you to specify blocks of code that you want your program to run at the beginning and end of its execution, regardless of their position in the source file.


1 Answers

@my_class will be an instance of MyClass and not MyModule. If you want to make all instances of MyClass be an instance of MyModule you should write:

 include MyModule

inside the class definition.

I think my answer makes sense if you look at the original version of this question before it was edited.

EDIT 1:

Let's add on to your example and say you have a class called Foo:

class Foo
    include MyModule
end

You want to make an instance of MyModuleClass that is associated with Foo but it sounds like you don't really want to modify Foo or give it access to the MyModuleClass. I propose that you use a hash table:

module MyModule
    # ...

    @hash = {}
    class << self
        attr_accessor :hash
    end

    included do
        MyModule.hash[self] = MyModuleClass.new(some_attrs)
    end
end

I think that will work, and it avoids adding an instance variable to to the Foo class object. Technically, any part of the ruby code can access MyModule.hash but you should put a comment in the source code telling people NOT to do that, and don't advertise that the hash exists.

like image 162
David Grayson Avatar answered Oct 12 '22 23:10

David Grayson