I was having trouble understanding an error while unit testing my module, which is a mixin.
Suppose the mixin to be tested is module A:
require 'path/b'
module A
def methodA()
puts methodB.attr1
end
end
And it depends on another mixin B which was defined in a file at path/b.rb
module B
def methodB
return someObject #that has property 'attr1'
end
end
Now, we have a class to unit test module A
require 'path/moduleA'
class TestA
include Path::moduleA
end
describe 'test moduleA.methodA'
it 'does something'
testObject = TestA.new
testObject.methodA()
expect(....)
end
end
I get following error on running the rspec test
NameError:
undefined local variable or method `methodB' for #<TestA:0x00007f77a03db9a8>
I am able to resolve it by one of following ways:
including module B in module A
including module B in class TestA
Questions
I am not clear why include is required to get access to methodB in
module A and class TestA when 'require' was already added in module A.
My intention is to use methods of module B in module A, but not let users of module A access module B methods automatically.
resolution 1 above gives users of A, access to B's methods
resolution 2 forces users of A (user -> the unit test class in this example) to include A's dependency B directly, even though user is only interested in accessing A's methods.
Hence, both resolutions don't achieve what I want. Is there a way to achieve it?
I'm new to Ruby so may be it doesn't support this. I'm from Java background where I would model A and B as two classes, make an instance of B as field of A, then expose A's own public methods to users of A. But since they are mixins, I need to use modules in ruby.
Just to be very explicit: require / require_relative / load and include / extend / prepend have absolutely nothing whatsoever to do with each other.
The former three simply run a Ruby file. That's it. That is all they do. They differ in how and where they search for the file, but after they found the file, they don't do anything else than just execute it.
The latter three add a module to the ancestor chain. include essentially makes the module the superclass, extend is really the same as singleton_class.include (i.e. makes the module the superclass of the singleton class), and prepend inserts the module at the beginning of the ancestor's chain, i.e. actually before the class that it is prepended to.
require just tells ruby to read / load the code inside the ruby file. In this case it will just define the module. However in order for code inside a module to be included inside another module or class, you must include it inside the module or class. So you should just as you mentioned do:
require 'path/b'
module A
include B
def methodA()
puts methodB.attr1
end
end
You should not need to change your test with this since module A already includes module B. However this is not a very good OOP design pattern here. But hopefully you understand why now.
After more googling, I found the answer to my 2nd question using suggestion from:
https://makandracards.com/makandra/977-calling-selected-methods-of-a-module-from-another-module
so basically i did:
require 'path/b'
module A
module B_RequiredMethods
include Path::B
module_function :methodB
end
def methodA
puts B_RequiredMethods.methodB.attr1
end
end
In my case, B_RequiredMethods could be named properly to represent the method of B which would be exposed by it. Ideally, I would make those methods class level methods of B, but it is managed by some other team.
I am new to Ruby. I am confused by some code that I am reading here:
http://hawkins.io/2012/03/defining_plugins_gems_railties_and_engines/
This is the code:
module Cashier
class Railtie < ::Rails::Railtie
config.cashier = Cashier
initializer "cashier.active_support.cache.instrumentation"
ActiveSupport::Cache::Store.instrument = true
end
end
end
I am surprised by this line, which would not be allowed in most languages:
config.cashier = Cashier
So I am inside the definition of the module Cashier, and yet I also get to instantiate an instance of the module Cashier and use it here? What is going on this line? How can I assign Cashier when I'm inside of the code that defines what Cashier is? In Java, I don't think I've ever instantiated a class inside the definition of the class.
You aren't instantiating Cashier here (you can't create instances of modules in Ruby anyhow); you're just referencing the Cashier constant, which refers to an instance of Module, which is already defined by the time you reach this line.
Ruby creates an empty Module instance and assigns it to the Foo constant by virtue of module Foo. The module body definition can be viewed as reopening the empty module and adding additional functionality to it. Ruby doesn't require the full module definition in order to "finalize" a module and assign it to a constant; it's created and assigned before the body definition is even considered.
That is, the code:
module Foo
puts Foo.object_id
end
is functionally equivalent to:
# Create a new Module instance and assign it to the Foo constant
Foo = Module.new
# Reopen the Module instance assigned to the constant Foo for modification
module Foo
# Do stuff in here to add functionality to the Foo module
# Since Foo is already defined, we can get its object_id.
puts Foo.object_id
end
This certainly doesn't make sense coming from a compiled language standpoint (after all, how do you know what Cashier is if you haven't finished its definition yet?), but Ruby's interpreted nature means that it tends to treat things like module and class definitions a bit more loosely, which is what is permitting this behavior.
I'm using a library that lays its library out like this:
module Lib
class A; end
class B; end
...
end
I know that I can use send on an object to "call" a method known only at runtime (e.g., foo.send(:bar, :baz_param=>42). How can I do this at the class level?
In other words, I suspect there's a way to write something like this:
label = :Klass
MyModule.some_method(label).new
that executes, in effect, as:
MyModule::Klass.new
Am I right?
As soon as I posted the question, I had a brainwave:
const_get
Class names are treated as constants, and the method is defined for all modules, too, so the lookup scope can be restricted to that module only. Just remember to get the capitalization right:
MyModule.const_get(:Klass).new # => #<Klass:> #CORRECT
MyModule.const_get(:klass).new # => NameError: wrong constant name
I have the following Structure:
module SomeMod::SubMod
module Mod1; end
module Mod2; end
end
I want to get all constants of SubMod, but I want a fully qualified reference to the Constant (ie. SomeMod::SubMod::Mod1) Currently I'm doing this:
SomeMod::SubMod.constants.map{ |constant| SomeMod::SubMod.const_get constant }
Can someone improve on this? Can I remove the duplicate reference to SomeMod::SubMod?
SomeMod::SubMod.module_eval{ constants.map{|c| const_get c} }
It's not really that much shorter, though.
What is this double-colon ::? E.g. Foo::Bar.
I found a definition:
The :: is a unary operator that allows: constants, instance methods and class methods defined within a class or module, to be accessed from anywhere outside the class or module.
What good is scope (private, protected) if you can just use :: to expose anything?
:: is basically a namespace resolution operator. It allows you to access items in modules, or class-level items in classes. For example, say you had this setup:
module SomeModule
module InnerModule
class MyClass
CONSTANT = 4
end
end
end
You could access CONSTANT from outside the module as SomeModule::InnerModule::MyClass::CONSTANT.
It doesn't affect instance methods defined on a class, since you access those with a different syntax (the dot .).
Relevant note: If you want to go back to the top-level namespace, do this: ::SomeModule – Benjamin Oakes
This simple example illustrates it:
MR_COUNT = 0 # constant defined on main Object class
module Foo
MR_COUNT = 0
::MR_COUNT = 1 # set global count to 1
MR_COUNT = 2 # set local count to 2
end
puts MR_COUNT # this is the global constant: 1
puts Foo::MR_COUNT # this is the local constant: 2
Taken from http://www.tutorialspoint.com/ruby/ruby_operators.htm
:: Lets you access a constant, module, or class defined inside another class or module. It is used to provide namespaces so that method and class names don't conflict with other classes by different authors.
When you see ActiveRecord::Base in Rails it means that Rails has something like
module ActiveRecord
class Base
end
end
i.e. a class called Base inside a module ActiveRecord which is then referenced as ActiveRecord::Base (you can find this in the Rails source in activerecord-n.n.n/lib/active_record/base.rb)
A common use of :: is to access constants defined in modules e.g.
module Math
PI = 3.141 # ...
end
puts Math::PI
The :: operator does not allow you to bypass visibility of methods marked private or protected.
What good is scope (private, protected) if you can just use :: to expose anything?
In Ruby, everything is exposed and everything can be modified from anywhere else.
If you're worried about the fact that classes can be changed from outside the "class definition", then Ruby probably isn't for you.
On the other hand, if you're frustrated by Java's classes being locked down, then Ruby is probably what you're looking for.
Surprisingly, all 10 answers here say the same thing. The '::' is a namespace resolution operator, and yes it is true. But there is one gotcha that you have to realize about the namespace resolution operator when it comes to the constant lookup algorithm. As Matz delineates in his book, 'The Ruby Programming Language', constant lookup has multiple steps. First, it searches a constant in the lexical scope where the constant is referenced. If it does not find the constant within the lexical scope, it then searches the inheritance hierarchy. Because of this constant lookup algorithm, below we get the expected results:
module A
module B
PI = 3.14
module C
class E
PI = 3.15
end
class F < E
def get_pi
puts PI
end
end
end
end
end
f = A::B::C::F.new
f.get_pi
> 3.14
While F inherits from E, the B module is within the lexical scope of F. Consequently, F instances will refer to the constant PI defined in the module B. Now if module B did not define PI, then F instances will refer to the PI constant defined in the superclass E.
But what if we were to use '::' rather than nesting modules? Would we get the same result? No!
By using the namespace resolution operator when defining nested modules, the nested modules and classes are no longer within the lexical scope of their outer modules. As you can see below, PI defined in A::B is not in the lexical scope of A::B::C::D and thus we get uninitialized constant when trying to refer to PI in the get_pi instance method:
module A
end
module A::B
PI = 3.14
end
module A::B::C
class D
def get_pi
puts PI
end
end
end
d = A::B::C::D.new
d.get_pi
NameError: uninitialized constant A::B::C::D::PI
Did you mean? A::B::PI
Adding to previous answers, it is valid Ruby to use :: to access instance methods. All the following are valid:
MyClass::new::instance_method
MyClass::new.instance_method
MyClass.new::instance_method
MyClass.new.instance_method
As per best practices I believe only the last one is recommended.
No, it is not to access every method, it is a "resolution" operator, that is, you use it to resolve the scope (or location you can say) of a constant/static symbol.
For example in the first of your line, Rails use it to find the Base class inside the ActiveRecord.Module, in your second one it is used to locate the class method (static) of the Routes class, etc, etc.
It is not used to expose anything, its used to "locate" stuff around your scopes.
http://en.wikipedia.org/wiki/Scope_resolution_operator
Ruby on rails uses :: for namespace resolution.
class User < ActiveRecord::Base
VIDEOS_COUNT = 10
Languages = { "English" => "en", "Spanish" => "es", "Mandarin Chinese" => "cn"}
end
To use it :
User::VIDEOS_COUNT
User::Languages
User::Languages.values_at("Spanish") => "en"
Also, other usage is : When using nested routes
OmniauthCallbacksController is defined under users.
And routed as:
devise_for :users, controllers: {omniauth_callbacks: "users/omniauth_callbacks"}
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
It is all about preventing definitions from clashing with other code linked in to your project. It means you can keep things separate.
For example you can have one method called "run" in your code and you will still be able to call your method rather than the "run" method that has been defined in some other library that you have linked in.
module Amimal
module Herbivorous
EATER="plants"
end
end
Amimal::Herbivorous::EATER => "plants"
:: Is used to create a scope . In order to access Constant EATER from 2 modules we need to scope the modules to reach up to the constant
In simple it is a namespace,
now namespace is container for modules, classes, function and other. and it also help to solve the problem name conflict.
and in ruby you can access namespace by module like
module A
class Article
def Base
end
module B
end
end
so to access the class Article we use A::Article.
and in some cases you see that
A::Article<Application::Base
this mean that the Article class of module A inherit the Base class from Application module.
Reviving this thread a little.
Can we create a 'ruby' name for this operator ::
Surprised that we haven't already since we have splats, spreads, hash rockets etc.
Surely we can come up with something more fun than 'double colon' or 'unary operator'
Thinking
quad dot
four eyes
tetra dot
Nibble (half a byte - 4 bits)