Why are constants from extended module not available in class methods declared with self.?
In Ruby, constant lookup is not the same as method lookup. For method lookup, calling foo
is always the same as calling self.foo
(assuming it isn't private). Calling a constant FOO
is very different from self::FOO
or singleton_class::FOO
.
Using an unqualified constant (e.g. FOO
) will do a lookup in the currently opened modules. A module is opened with module Mod
, class Klass
, class << obj
, or module_eval
and variants. When defining m1
, these are B
, and then B.singleton_class
. When defining m2
, only B
is opened.
module Foo
X = 42
class Bar
def self.hello
X
end
end
end
In this code, Foo::Bar.hello
will return 42, even though X
is not a constant of Bar
, its singleton class or ancestor. Also, if you later add a constant X
to Bar
, then that value will be returned. Finally, the following definition is not equivalent:
module Foo
X = 42
end
class Foo::Bar
def self.hello
X
end
end
Foo::Bar.hello # => uninitialized constant Foo::Bar::X
Indeed, when hello
is defined, only the class Foo::Bar
is opened, while in the previous example, both Foo
and Foo::Bar
where opened.
A last example, to show the difference an explicit scope can have with inheritance:
class Base
X = 42
def self.foo
X
end
def self.bar
self::X
end
end
class Parent < Base
X = :other
end
Parent.foo # => 42
Parent.bar # => :other
In your case, you probably want to include
your module, instead of extending
it, no?
Otherwise, you could use singleton_class::VAR
, your code will work as you expect it.
module A
VAR = 'some_constant'
end
class B
extend A
class << self
def m1
puts singleton_class::VAR # not necessary here, as singleton_class is opened
end
end
def self.m2
puts singleton_class::VAR # necessary here!
end
end
B.m1 # => OK
B.m2 # => OK
(In Ruby) allowing mixed-in class methods access to class constants
This seems to work:
#! /usr/bin/env ruby
module CommonMethods
def shout_my_constant
puts self::Const.upcase
end
end
class NonInstantiableClass
Const = "hello, world!"
class << self
include CommonMethods
end
end
NonInstantiableClass.shout_my_constant
HTH
In Ruby, in a method defined in class self, why can't a constant defined on the superclass be access without self?
You have encountered a common Ruby gotcha - constant lookup.
The most important concept in constant lookup is Module.nesting
(unlike in method lookup, where the primary starting point is self
). This method gives you the current module nesting which is directly used by the Ruby interpreter when resolving the constant token. The only way to modify the nesting is to use keywords class
and module
and it only includes modules and classes for which you used that keyword:
class A
Module.nesting #=> [A]
class B
Module.nesting #=> [A::B, A]
end
end
class A::B
Module.nesting #=> [A::B] sic! no A
end
In meta programming, a module or class can be defined dynamically using Class.new
or Module.new
- this does not affect nesting and is an extremely common cause of bugs (ah, also worth mentioning - constants are defined on the first module of Module.nesting):
module A
B = Class.new do
VALUE = 1
end
C = Class.new do
VALUE = 2
end
end
A::B::VALUE #=> uninitialized constant A::B::VALUE
A::VALUE #=> 2
The above code will generate two warnings: one for double initialization of constant A::VALUE and a second for reassigning the constant.
If it looks like "I'd never do that" - this also applies to all the constants defined within RSpec.describe
(which internally calls Class.new), so if you define a constant within your rspec tests, they are most certainly global (unless you explicitly stated the module it is to be defined in with self::
)
Now let's get back to your code:
class SubExample < SuperExample
puts Module.nesting.inspect #=> [SubExample]
class << self
puts Module.nesting.inspect #=> [#<Class:SubExample>, SubExample]
end
end
When resolving the constant, the interpreter first iterates over all the modules in Module.nesting
and searches this constant within that module. So if nesting is [A::B, A]
and we're looking for the constant with token C
, the interpreter will look for A::B::C
first and then A::C
.
However, in your example, that will fail in both cases :). Then the interpreter starts searching ancestors of the first (and only first) module in Module.nesting. SubrExample.singleton_class.ancestors
gives you:
[
#<Class:SubExample>,
#<Class:SuperExample>,
#<Class:Object>,
#<Class:BasicObject>,
Class,
Module,
Object,
Kernel,
BasicObject
]
As you can see - there is no SuperExample
module, only its singleton class - which is why constant lookup within class << self
fails (print_constant_fails
).
The ancestors of Subclass
are:
[
SubExample,
SuperExample,
Object,
Kernel,
BasicObject
]
We have SuperExample
there, so the interpreter will manage to find SuperExample::A_CONSTANT
within this nesting.
We're left with print_constant_works_2
. This is an instance method on a singleton class, so self
within this method is just SubExample
. So, we're looking for SubExample::A_CONSTANT
- constant lookup firstly searches on SubExample
and, when that fails, on all its ancestors, including SuperExample
.
self.included – including class methods from a module in Ruby
What's the difference between the two examples?
The first code block adds the class methods in ClassMethods
to the including class and calls the scope
method on it as well. The second one does neither of these things and will result in a NoMethodError
because the module has no scope
class method. self.some_class_method
will not be available on the including class once the module is included.
For the full story on how module inclusion works in Ruby, read my answer here:
Inheriting class methods from modules / mixins in Ruby
What's the point of self.included
if a module's sole purpose is to be included?
Inclusion is not the only purpose of modules. They are also used for other things such as namespacing or simply storing various class methods that are then callable on the module itself.
Why doesn't Ruby include class methods automatically?
Theoretically Ruby could automatically add all class methods defined in a module to the including class, but in practice that would be a bad idea, because you would not get to choose anymore whether you want to include class methods — all class methods would be included every time, whether or not they are intended to be included. Consider this example:
module M
def self.class_method
"foo"
end
def self.configure_module
# add configuration for this module
end
end
class C
include M
end
Here, the configure_module
method is obviously not supposed to be added to C
, as its purpose is to set the configuration for the module object. Yet, if we had auto-inclusion for class methods, you would not be able to prevent it from being included.
But all instance methods are already included! How is that okay then?
Instance methods in a module are only really useful if they are included into a class, since modules cannot have instances, only classes can. So in a module every instance method is expected to be included somewhere to work.
A "class" method on a module is different, because it can be called on the module itself, so it can be used just fine regardless of whether it's also added to the including class. That is why it is better that you have a choice there.
Cython's Extension module's class's methods not visible/give a name Error when mentioned
Here is a simple example to help you get started with cython classes. First, I create my setup.py
file, which I use to compile my cython .pyx
file by calling python setup.py build_ext --inplace
.
from distutils.core import setup
from Cython.Build import cythonize
from distutils.core import Extension
extensions = [
Extension("mylist", sources=["mylist.pyx"], libraries=[], extra_compile_args=["-w"]),
]
setup(
ext_modules = cythonize(extensions)
)
Next, I would write up a .pxd
file. Like I mentioned in the comments, this is basically a header file that defines all of the "c-side" class properties and methods that you want to access that were defined with cdef
or cpdef
. An example mylist.pxd
would look like this:
cdef class MyList:
cdef public list _base_list
cpdef append(self, object item)
cpdef pop(self, int index=*)#Note: * is used in place of default values
cpdef get_data(self)
Now we are ready to create our mylist.pyx
file that actually does the work. To keep things simple, I will implement our cython list using python lists (which is pretty nonsensical performance-wise but will avoid the need to delve into arrays, which are a little trickier). The code might look like this:
cdef class MyList:
def __cinit__(self):#__cinit__ is preferred for cdef class constructors
self._base_list = []
cpdef append(self, object item):
self._base_list = self._base_list + [item]
cpdef pop(self, int index=-1):
self._base_list.pop(index)
cpdef get_data(self):
return self._base_list
Once this is all compiled, you can use this silly MyList
class in python. Here is MyList
in action in a main.py
file:
from mylist import MyList
a = MyList()
a.append("apple")
a.append("banana")
a.append("tomato")
a.append("pear")
a.pop(2)#one of these fruit is not like the others...
print a.get_data()
Let me know if you are having issues compiling or running this example. I tested this on my laptop using Python 2.7 and the latest Cython master (version 0.26b0).
Ruby module include, can't access included methods, only constants
The following is a common way to mix a module containing constants, instance methods, and class methods into a class, but it can also be used to include constants and class methods of one module in another module, which is what you want to do. It uses the "callback" or "hook" method Module#included. Object#extend adds the instance methods in the module that is the argument to the module that is extend
's receiver. Below it makes the instance methods (here just one) in Public::C_Meths
class methods in the module Child
.
module Parent
module I_Meths
PARENT_CONST = 'parent const'
end
module C_Meths
def cmeth
'cmeth'
end
end
def self.included(mod)
mod.include(I_Meths)
mod.extend(C_Meths)
end
end
module Child
include Parent
end
Child::PARENT_CONST
#=> "parent const"
Child.cmeth
#=> "cmeth"
It's more common to use this construct to mix a module containing constraints, instance methods and class methods into a class.
Suppose we were to add the instance method:
def imeth
'imeth'
end
to the module Parent::I_Meths
and include Parent
in a class:
class A
include Parent
end
then
A::PARENT_CONST
#=> "parent const"
A.cmeth
#=> "cmeth"
A.new.imeth
#=> "imeth"
Class instance variable initialize in extended module
You could move the variable initialization into the included
callback:
module MyModule
def self.included(base)
base.extend ClassMethods
base.include InstanceMethods
base.count = 0
end
module ClassMethods
attr_accessor :count
end
module InstanceMethods
def register
self.class.count += 1
end
end
end
Scope of Constants in Ruby Modules
The USER_KEY
you declared (even conditionally) in Auth
is globally known as Auth::USER_KEY
. It doesn't get "mixed in" to including modules, though including modules can reference the key in a non-fully-qualified fashion.
If you want each including module (e.g. ApplicationController
) to be able to define its own USER_KEY
, try this:
module Auth
DEFAULT_USER_KEY = 'user'
def self.included(base)
unless base.const_defined?(:USER_KEY)
base.const_set :USER_KEY, Auth::DEFAULT_USER_KEY
end
end
def authorize
user_id = session[self.class.const_get(:USER_KEY)]
end
end
class ApplicationController < ActionController::Base
USER_KEY = 'my_user'
include Auth
end
If you're going to go to all this trouble, though, you might as well just make it a class method:
module Auth
DEFAULT_USER_KEY = 'user'
def self.included(base)
base.extend Auth::ClassMethods
base.send :include, Auth::InstanceMethods
end
module ClassMethods
def user_key
Auth::DEFAULT_USER_KEY
end
end
module InstanceMethods
def authorize
user_id = session[self.class.user_key]
end
end
end
class ApplicationController < ActionController::Base
def self.user_key
'my_user'
end
end
or a class-level accessor:
module Auth
DEFAULT_USER_KEY = 'user'
def self.included(base)
base.send :attr_accessor :user_key unless base.respond_to?(:user_key=)
base.user_key ||= Auth::DEFAULT_USER_KEY
end
def authorize
user_id = session[self.class.user_key]
end
end
class ApplicationController < ActionController::Base
include Auth
self.user_key = 'my_user'
end
Why are constants declared inside an array, and assigned to other constants, accessible as Class constants in Ruby?
First, what happens when the following code is executed:
PARENTS = [
FATHER = :father,
MOTHER = :mother
]
PARENTS = ...
attempts to set the constantPARENTS
. But in order to do so, it has to evaluate the right-hand side of the assignment:[...]
attempts to create an array. But in order to do so, it has to evaluate its arguments:FATHER = :father
sets the constantFATHER
to:father
. The result of this assignment is:father
which becomes the first argument.MOTHER = :mother
sets the constantMOTHER
to:mother
. The result of this assignment is:mother
which becomes the second argument.
So in chronological order:
- The constant
FATHER
is set to:father
- The constant
MOTHER
is set to:mother
- An array with elements
:father
and:mother
is created - The constant
PARENTS
is set to that array
Your code is equivalent to:
FATHER = :father
MOTHER = :mother
PARENTS = [FATHER, MOTHER] # or [:father, :mother]
By declaring the constants inside of an array, I would expect them to to be scoped inside the array. Please cite the relevant docs in your answer.
You can use Module.nesting
to determine the current nesting, i.e. where a constant will be defined in: (more examples in the docs)
class Example
p outer_nesting: Module.nesting
PARENTS = [
p(inner_nesting: Module.nesting)
]
end
Output:
{:outer_nesting=>[Example]}
{:inner_nesting=>[Example]}
As you can see, an array literal doesn't affect the current nesting. Constants in both locations will be defined under Example
.
If you really wanted to declare the constants "inside" the array (i.e. inside the array's singleton class), you could do some like this:
class Example
PARENTS = []
class << PARENTS
FATHER = :father
MOTHER = :mother
PARENTS.push(FATHER, MOTHER)
end
end
p Example.constants #=> [:PARENTS]
p Example::PARENTS.singleton_class.constants #=> [:FATHER, :MOTHER]
The above is just for demonstration purposes, there's no need to actually do that.
Rails: Use constants from model for define instance methods into Concern
You can use self.included
hook to get a reference to the including class at include time.
module StatesHelper
extend ActiveSupport::Concern
def self.included(base)
base::STATES.each do |state|
define_method "#{state}?" do
self.state == state
end
end
end
end
class Item
STATES = %w(active disabled).freeze
include StatesHelper
end
item = Item.new
item.respond_to?(:active?) # => true
item.respond_to?(:disabled?) # => true
Related Topics
How to Convert an Existing Rails 3 Application into an Engine
Deleting Table from Schema - Rails
Multiple Robots.Txt for Subdomains in Rails
Augmenting a Model from an External Gem
Collect Values from an Array of Hashes
How to Uninstall Ruby on Rails and Do a Clean Install
MAC Os X Mountain Lion "Rails Is Not Currently Installed on This System."
How to Use Rails and Paperclip to Store Photos on Google Cloud Storage
Define a Method That Is a Closure in Ruby
How to Solve the Update Bundler Warning in Rails When Deploying to Heroku
Rails: Your User Account Isn't Allowed to Install to the System Rubygems
How to Use Define_Method Inside Initialize()
Object.Valid? Returns False But Object.Errors.Full_Messages Is Empty
How Might I Pass Text Data from the Ruby Console into My Clipboard Without Saving to a File
Rails - Finding Intersections Between Multiple Arrays
Xcode - Configure: Error: No Acceptable C Compiler Found in $Path