What is the different between the following statements?
#(not working)
File.exists?("path to file")
#(working)
::File.exists?("path to file")
I used above statements in Chef framework of Ruby.
There is another constant named File in the scope where you are using File.exists?("path to file"). But when you use the :: operator, you are telling ruby to find the File constant in Object (Object::File)
Here is possible try to replicate your issue :
Not working :
class Foo< BasicObject
def self.file_size
File.size(__FILE__)
end
end
p Foo.file_size # uninitialized constant Foo::File (NameError)
The reason is File class is available to the top level ( i.e. in the scope of the class Object) and inside any class which is a direct/ indirect subclass of Object. But Foo has no relation with Object, you wouldn't be able to access it inside Foo, if you don't tell it, from where File class ( or constant ) actually accessible.
Working :
class Foo< BasicObject
def self.file_size
::File.size(__FILE__)
end
end
p Foo.file_size # => 132
Although here also, Foo has no relation with Object, but we are explicitly ( by using :: constant scope resolution operator ) telling Ruby that from where we are trying to access the File class ( Remember class(s) are also constant in Ruby) inside Foo class. Thus here is no objection from Ruby.
Check out if such situation is present in your code too.
On a side-note, File.exists? is deprecated - use File.exist?
According to maty, the question should be asked in this way:
"object, do you exist?"
"object.exist?"
Keep this in mind - yes, "if file exist" is not proper english,
but asking it that way would be wrong from the ruby object
point of view.
As for the leading :: - this refers to toplevel scope.
It is not often required, usually only when you have the same name
of a class or a module.
Related
I am in a position at the moment where I have a plugins folder where there there could be 1 or 100 plugins to be loaded.
Now the problem is, each plugin requires an instance of a class defined within the startup ruby file.
A really simplified example would be:
#startup.rb
def load_plugins
#... get each plugin file
require each_plugin
end
class MuchUsedClass
def do_something
#...
end
end
muchUsedInstance = MuchUsedClass.new
load_plugins
#some_plugin.rb
class SomePluginClass
def initialize(muchUsedInstance)
#muchUsedInstance = muchUsedInstance
end
def do_something_with_instance
#muchUsedInstance.do_something
end
end
somePluginInstance = SomePluginClass.new(muchUsedInstance)
somePluginInstance.do_something_with_instance
The main problem is that when you call require, it doesn't have any clue about what has happened before it is being required. So I find it nasty making a global variable within the startup file just to satisfy all other required files, but it seems like one of the only ways to be able to pass some data down to an included file, I could also make a singleton class to expose some of this, but that also seems a bit nasty.
As I am still new to ruby and am still looking through the statically typed glasses, I will probably be missing a decent pattern to solve this, in C# I would opt for dependency injection and just hook everything up that way...
Your example code does not have a global variable. Global variables have names that start with $. The code as you wrote it won't work, because muchUsedInstance is just a local variable and will not be shared between different Ruby files.
If you are not going to change the instance ever, you could easily store it as a constant:
MuchUsedInstance = MuchUsedClass.new
You could store it as a nested constant inside the class:
MuchUsedClass::Instance = MuchUsedClass.new
You could store it as an instance variable inside the class object, with a getter method that automatically creates it if it isn't there already:
def MuchUsedClass.instance
#instance ||= MuchUsedClass.new
end
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 some rb files, all with the same structure:
class RandomName < FooBar
end
The randomname is a random class name which changes in each rb file but all inherits from Foobar.
how i can load all randomclass from there rb files?
I think there are 2 parts to the solution:
How to dynamically instantiate a class
a. Using String#constantize from ActiveSupport
klass = "SomeNamespace::SomeClassName".constantize
klass.new
b. Use Module#const_get (which doesn't handle namespaces)
klass = const_get(:SomeClassName)
klass.new
How to detect a class name
A convention followed widely in ruby is to name the file after the class that it contains, so random_name.rb would contain the RandomName class. If you follow this convention, then you could do something like:
Dir["/path/to/directory/*.rb"].each do |file|
require file
file_name = File.basename(file.path, '.rb')
# using ActiveSupport for camelcase and constantize
file_name.camelcase.constantize.new
end
I think you should explain what you are trying to accomplish. The approach you are taking seems unconventional and there may be a much more effective way of reaching your goal without doing all this loading of files and dynamic instantiation of classes with random names.
Remember, just because ruby lets you do something, it doesn't mean it's a good idea to actually do it!
you can define a method called inherited in the FooBar class. look here
class FooBar
def self.inherited(subclass)
puts "New subclass: #{subclass}"
end
end
Every time a subclass is created, you will get it in the callback. Then you can do whatever you want with all those subclasses.
I have a similar requirement, passing a class name in as a string. One trick with require is that it doesn't have to be at the start, so I prefer to only load the class I need.
I used eval because it doesn't have any Rails dependencies (I'm writing pure Ruby code here).
The following relies on convention (that the Class is in a file of the same name), but if you do know the class and file, this approach has the advantage of not requiring every file in a directory and only dynamically loading the one you need at the time you need it.
klass = "classname"
begin
# Load the file containing the class from same directory I'm executing in
require_relative klass # Or pass a local directory like "lib/#{klass}"
# Use eval to convert that string to a Constant (also capitalize it first)
k = eval(klass.capitalize).new
rescue
# Do something if the convention fails and class cannot be instantiated.
end
k.foo # Go ahead and start doing things with your new class.
I'm dynamically defining a module name from an argument passed on the cli, for example Required::Module::#{ARGV.first}
Is there any way to check if that module exists? Also, how would I run methods on it not knowing it's exact name?
Use const_defined? for this.
Required::Module.const_defined?(:ModuleName)
returns true or false.
defined?(Required::Module)
gives "constant" if it exists, and nil if it doesn't.
Update: Sorry, didn't read your question properly.
defined?(eval("Required::Module::"+string))
should give you what you're after.
Check for module existence using the const_get method:
begin
mod = Required::Module::const_get "ModuleName"
#It exists
rescue NameError
#Doesn't exist
end
You have to check if:
a constant referring to a module exists,
an object that the constant holds reference to is a module.
Try that:
def module_exists?(name, base = self.class)
base.const_defined?(name) && base.const_get(name).instance_of?(::Module)
end
Then in your code:
module_exists?(ARGV.first, Required::Module)
It will return true if there is a module of the given name within a given namespace base. The difference from the examples given in other answers is that it will return false if the queried name reffers to a class, not to a module.
Include classes in a test
If you want to change that behavior and force the method to also return true for classes (not just modules) change instance_of? to is_a?.
OOP way
You can also code it in a more object-oriented way if your Required::Module module is the only module you're testing for submodules:
module Required::Module
def submodule_exists?(name)
const_defined?(name) && const_get(name).instance_of?(::Module)
end
end
module_function :submodule_exists?
Then in your code:
Required::Module.submodule_exists?(ARGV.first)
If you got ActiveSupport
mod = ("Required::Module::#{ARGV.first}".constantize rescue nil)
In the case where you require something that extends something else, you can't base your test on a constant because the extension may not define a new one. Instead, base it on the presence of something else, like a new method.
I use the below to test if open_uri_redirections has been required:
if OpenURI.methods.include?(:redirectable_safe?)
# extension loaded
else
# extension not loaded
fi
The currently selected answer is not correct. const_get and const_defined look for any constant name, regardless of the object calling that method. For example, if I wanted to check for MyModule::Rails inside a Rails application, using const_get would return the normal Rails module.
To check for a constant within a specific namespace, use the constants method and check for your class:
MyModule.constants.include?("Rails") # => false
Get the class if it exists:
dynamic_klass = "Required::Module::#{ARGV.first}".classify.safe_constantize
Call a method on the class if it does:
dynamic_klass.send("some_method") if dynamic_klass.present?
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)