heroxav
heroxav

Reputation: 1467

Share data between methods

I have this module, which gets included in a class:

module MyModule

    def self.included base
        base.extend ClassMethods
    end

    module ClassMethods
        def my_module_method data
            include MyModule::InstanceMethods

            after_save :my_module_process

            attr_accessor :shared_data
            shared_data = data
            # instance_variable_set :@shared_data, data
        end
    end

    module InstanceMethods

        private

        def my_module_process
            raise self.shared_data.inspect
            # raise instance_variable_get(:@shared_data).inspect
        end

    end

end

I want to use the data (parameter) passed to my_module_method within my_module_process. I've used attr_accessor as well as instance variables, but either of them return nil.

Upvotes: 0

Views: 144

Answers (1)

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230561

Since you're using rails, your module can be greatly simplified by making it a AS::Concern

module MyModule
  extend ActiveSupport::Concern

  included do
    # after_save :my_module_process # or whatever
    cattr_accessor :shared_data
  end

  module ClassMethods
    def my_module_method(data)
      self.shared_data = data
    end
  end

  def my_module_process
    "I got this shared data: #{self.class.shared_data}"
  end
end

The key points here are:

  • cattr_accessor, which is similar to attr_accessor, but defines class-level methods
  • self.class.shared_data to access that class-level data from the instances.

Usage:

class Foo
  include MyModule
end

f = Foo.new
f.my_module_process # => "I got this shared data: "
Foo.my_module_method({foo: 'bar'})
f.my_module_process # => "I got this shared data: {:foo=>\"bar\"}"

I've used attr_accessor as well as instance variables, but either of them return nil.

In ruby, it is super-important to know what is self at any given moment. This is what defines the methods and instance variables available to you. As an exercise, I offer you to find out, why user.name returns nil here (and how to fix it).

class User
  @name = 'Joe'

  def name
    @name
  end
end

user = User.new
user.name # => nil

Upvotes: 2

Related Questions