2

I have a module like the following

module MyModule
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def foo
      @@var = 1
    end

    def bar
      puts @@var
    end
  end
end

class A
  include MyModule
  foo
end

class B < A; end

so that

 B.bar outputs '1'.

However, I would like to have .bar only be defined if .foo is called. I tried

module MyModule
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def foo
      @@var = 1
      extend SingletonMethods
    end

  module SingletonMethods
    def bar
      puts @@var
    end
  end
end

The problem is that

B.bar

returns the error "uninitialized class variable @@var in MyModule::SingletonMethods". How can I make it so that a variable defined in .foo is available to .bar?

2 Answers 2

1

use mattr_accessor instead

Sign up to request clarification or add additional context in comments.

3 Comments

Is mattr_accessor Rails only?
Yes, but the implementation is pretty straightforward - github.com/rails/rails/blob/master/activesupport/lib/…
this saved me a lot of time.
0

I was able to access class variables from a module using the self syntax

class User
  include Base
  @@attributes = [:slug, :email, :crypted_password]
end

module Base
  def self.included(base)
  base.extend ClassMethods
end

def headers
  if defined? self.attributes
    self.attributes
  end
 end
end

Now calling User.headers gives me the expected result of [:slug, :email, :crypted_password]

If anyone can shed more light on why this works exactly so in ruby, please let me know!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.