class MyClass
def mymethod
MYCONSTANT = "blah"
end
end
gives me the error:
SyntaxError: dynamic constant assignment error
Why is this considered a dynamic constant? I'm just assigning a string to it.
Your problem is that each time you run the method you are assigning a new value to the constant. This is not allowed, as it makes the constant non-constant; even though the contents of the string are the same (for the moment, anyhow), the actual string object itself is different each time the method is called. For example:
def foo
p "bar".object_id
end
foo #=> 15779172
foo #=> 15779112
Perhaps if you explained your use case—why you want to change the value of a constant in a method—we could help you with a better implementation.
Perhaps you'd rather have an instance variable on the class?
class MyClass
class << self
attr_accessor :my_constant
end
def my_method
self.class.my_constant = "blah"
end
end
p MyClass.my_constant #=> nil
MyClass.new.my_method
p MyClass.my_constant #=> "blah"
If you really want to change the value of a constant in a method, and your constant is a String or an Array, you can 'cheat' and use the #replace method to cause the object to take on a new value without actually changing the object:
class MyClass
BAR = "blah"
def cheat(new_bar)
BAR.replace new_bar
end
end
p MyClass::BAR #=> "blah"
MyClass.new.cheat "whee"
p MyClass::BAR #=> "whee"
Because constants in Ruby aren't meant to be changed, Ruby discourages you from assigning to them in parts of code which might get executed more than once, such as inside methods.
Under normal circumstances, you should define the constant inside the class itself:
class MyClass
MY_CONSTANT = "foo"
end
MyClass::MY_CONSTANT #=> "foo"
If for some reason though you really do need to define a constant inside a method (perhaps for some type of metaprogramming), you can use const_set:
class MyClass
def my_method
self.class.const_set(:MY_CONSTANT, "foo")
end
end
MyClass::MY_CONSTANT
#=> NameError: uninitialized constant MyClass::MY_CONSTANT
MyClass.new.my_method
MyClass::MY_CONSTANT #=> "foo"
Again though, const_set isn't something you should really have to resort to under normal circumstances. If you're not sure whether you really want to be assigning to constants this way, you may want to consider one of the following alternatives:
Class variables
Class variables behave like constants in many ways. They are properties on a class, and they are accessible in subclasses of the class they are defined on.
The difference is that class variables are meant to be modifiable, and can therefore be assigned to inside methods with no issue.
class MyClass
def self.my_class_variable
##my_class_variable
end
def my_method
##my_class_variable = "foo"
end
end
class SubClass < MyClass
end
MyClass.my_class_variable
#=> NameError: uninitialized class variable ##my_class_variable in MyClass
SubClass.my_class_variable
#=> NameError: uninitialized class variable ##my_class_variable in MyClass
MyClass.new.my_method
MyClass.my_class_variable #=> "foo"
SubClass.my_class_variable #=> "foo"
Class attributes
Class attributes are a sort of "instance variable on a class". They behave a bit like class variables, except that their values are not shared with subclasses.
class MyClass
class << self
attr_accessor :my_class_attribute
end
def my_method
self.class.my_class_attribute = "blah"
end
end
class SubClass < MyClass
end
MyClass.my_class_attribute #=> nil
SubClass.my_class_attribute #=> nil
MyClass.new.my_method
MyClass.my_class_attribute #=> "blah"
SubClass.my_class_attribute #=> nil
SubClass.new.my_method
SubClass.my_class_attribute #=> "blah"
Instance variables
And just for completeness I should probably mention: if you need to assign a value which can only be determined after your class has been instantiated, there's a good chance you might actually be looking for a plain old instance variable.
class MyClass
attr_accessor :instance_variable
def my_method
#instance_variable = "blah"
end
end
my_object = MyClass.new
my_object.instance_variable #=> nil
my_object.my_method
my_object.instance_variable #=> "blah"
MyClass.new.instance_variable #=> nil
In Ruby, any variable whose name starts with a capital letter is a constant and you can only assign to it once. Choose one of these alternatives:
class MyClass
MYCONSTANT = "blah"
def mymethod
MYCONSTANT
end
end
class MyClass
def mymethod
my_constant = "blah"
end
end
Constants in ruby cannot be defined inside methods. See the notes at the bottom of this page, for example
You can't name a variable with capital letters or Ruby will asume its a constant and will want it to keep it's value constant, in which case changing it's value would be an error an "dynamic constant assignment error". With lower case should be fine
class MyClass
def mymethod
myconstant = "blah"
end
end
Ruby doesn't like that you are assigning the constant inside of a method because it risks re-assignment. Several SO answers before me give the alternative of assigning it outside of a method--but in the class, which is a better place to assign it.
Many thanks to Dorian and Phrogz for reminding me about the array (and hash) method #replace, which can "replace the contents of an array or hash."
The notion that a CONSTANT's value can be changed, but with an annoying warning, is one of Ruby's few conceptual mis-steps -- these should either be fully immutable, or dump the constant idea altogether. From a coder's perspective, a constant is declarative and intentional, a signal to other that "this value is truly unchangeable once declared/assigned."
But sometimes an "obvious declaration" actually forecloses other, future useful opportunities. For example...
There are legitimate use cases where a "constant's" value might really need to be changed: for example, re-loading ARGV from a REPL-like prompt-loop, then rerunning ARGV thru more (subsequent) OptionParser.parse! calls -- voila! Gives "command line args" a whole new dynamic utility.
The practical problem is either with the presumptive assumption that "ARGV must be a constant", or in optparse's own initialize method, which hard-codes the assignment of ARGV to the instance var #default_argv for subsequent processing -- that array (ARGV) really should be a parameter, encouraging re-parse and re-use, where appropriate. Proper parameterization, with an appropriate default (say, ARGV) would avoid the need to ever change the "constant" ARGV. Just some 2¢-worth of thoughts...
Related
To test, whether a constant (say: a class) is known at a certain point in the code, I can write for instance:
if defined? :String
or I can write
if self.class.const_defined? :String
Is there a situation where I these two ways of testing would make a difference? Note that I don't ask about the case where I have an explicit receiver, such as MyModule.const_defined? :Something, but only for the case where I want to test whether a certain constant (which in my case happens to be a constant denoting a class) is already defined.
First things first, defined? is a keyword which behaves a bit similar similar to a method. It receives the name of the thing (variable, constant, ...) to check. What makes this method different from all others is that the parser will not resolve the value of the given name but rather check directly for whether it is defined (hence the keyword property). To check if a constant is defined, you thus have to pass the actual name (rather than a Symbol):
if defined?(String)
The const_defined? on the oither hand is more regular. It expects a Symbol or String with the name of a constant and checks whether it is defined on the receiver.
Now as for the differences between the two (when used correctly): if you use them both within the context of an instance method to check for the existence of a constant, they work the same.
When running e.g. in a class definition (such that self is e.g. a class), you need to make sure to use the correct receiver for your const_defined method, e.g. if self.const_defined? :String.
Also, defined? can check for a lot more than just constants (e.g. methods, expressions, variables, ...)
If you want to use this to make sure you actually have the name of a constant at hand in a given variable, you need to use const_defined?. If you want to "statically" check whether an constant was defined, you can use defined?.
defined? is a keyword that will check if an expression exists in the current scope.
const_defined? is a method that will check if a constant exists through the ancestor chain of the receiver.
planet = "Earth"
class Experiment
def diff
""
end
def show
puts "defined" if defined?(diff)
puts "Earth not found" if !defined?(planet)
puts "String constant defined" if self.class.const_defined?(:String)
end
end
Experiment.new.show
#=> defined
#=> Earth not found
#=> String constant defined
p Experiment.ancestors #=> [Experiment, Object, Kernel, BasicObject]
p String.superclass #=> Object
Here's an example of situations where this will make a difference:
Using defined?(Nothing's printed)
class Lab
class Coco
end
end
class Experiment
def diff
""
end
def show
puts "defined" if defined?(Coco) #=> Nothing printed
end
end
Experiment.new.show
Using self.class.const_defined? (Something's printed)
class Lab
class Coco
end
end
class Experiment < Lab
def diff
""
end
def show
puts "defined" if self.class.const_defined? :Coco #=> defined
end
end
Experiment.new.show
p Experiment.ancestors #=> [Experiment, Lab, Object, Kernel, BasicObject] We find 'Lab' class in the ancestor chain.
To test, whether a constant (say: a class) is known at a certain point in the code, I can write for instance:
if defined? :String
or I can write
if self.class.const_defined? :String
Is there a situation where I these two ways of testing would make a difference?
These two really do two completely different things. The first tests whether the Symbol literal :String is defined. Obviously, a literal will always be defined, so this expression will always be true.
The second will check whether the constant String is defined, but not starting at the current constant lookup scope, instead starting at the class of self.
TL;DR
There may be cases where you can use them interchangeably, but one is a keyword and the other a method. In addition, the semantics and return values of the two are quite different.
Keywords vs. Methods
Among other things, one key difference is that Module#const_defined? is a method on a class or module that looks up constants in a class and its ancestors, while defined? is a keyword that determines whether its argument is currently known at the calling point in your code.
For example:
char = 'a'
char.const_defined?
#=> NoMethodError (undefined method `const_defined?' for "a":String)
defined? char
#=> "local-variable"
Exceptions vs. Return Values
If you're only concerned about constants, then the main difference is that you can use defined? to determine whether a constant is currently in scope without triggering a NoMethodError exception. For example:
defined? String
#=> "constant"
defined? FooBarBaz
#=> nil
As a bonus, defined? will tell what type of object you're passing as an argument (e.g. "constant"), while #const_defined? returns a truthy value.
Float.constants
#=> [:ROUNDS, :RADIX, :MANT_DIG, :DIG, :MIN_EXP, :MAX_EXP, :MIN_10_EXP, :MAX_10_EXP, :MIN, :MAX, :EPSILON, :INFINITY, :NAN]
defined? Float::NAN
#=> "constant"
Float.const_defined? :NAN
#=> true
As a rule of thumb, it's often considered best practice to reserve exceptions for handling something unexpected that may require your application to halt. Introspection or branching should generally rely on return values or Booleans, so defined? is usually a better choice if you aren't already expecting a given class to already be defined and available within the current scope.
Is there a situation where I these two ways of testing would make a difference?
const_defined? only checks the receiver and its ancestors, but it doesn't take the current module nesting into account:
module Foo
ABC = 123
class Bar
def self.test
p defined?(ABC) #=> "constant"
p const_defined?(:ABC) #=> false
end
end
end
In order to do so, you have to traverse Module.nesting:
module Foo
ABC = 123
class Bar
def self.test
p defined?(ABC) #=> "constant"
p Module.nesting.any? { |m| m.const_defined?(:ABC) } #=> true
end
end
end
You can define classes as constants on Object, using the const_set method. Are there any interesting or instructive use cases where someone would pass arguments into the Class.new block?
Object.const_set(:Klass, Class.new do |can_i_use_this|
def ping
"pong"
end
end)
Klass.new.ping
Can you do anything with that?
It turns out that the block argument is the class you are creating. Run this snippet in irb
Class.new do |what|
p what
end
and you will see something like
#<Class:0x000000022b2698>
=> #<Class:0x000000022b2698>
The first line of output is given by p what, and the second line shows the return value of Class.new, which we know is the class. You can see that the what is the same object as the return value of Class.new.
Conclusion: the block argument is not very useful because you can get the class instance just using self in that class. The only usage I can imagine of is using the trick called flat scope to create methods.
Foo = Class.new do |klass|
define_method :class_name do
klass.name
end
end
Foo.new.class_name #=> "Foo"
Yet this is not very useful either because an object can easily access its class with self.class.
Everything is an object in Ruby. So if we have a class Hello it is an instance of a parent class Object.
If I do the following in Ruby:
Hello = Class.new
World = Class.new(Hello)
Does that translate into the following?
class Hello
class World < Hello
Since multiple inheritance can't be done in Ruby, the new method should take only one parameter?
Yes. Positive to both (except that your latter code is invalid).
Note that your "Hello it is an instance of a parent class Class." is wrong. Hello is an instance of Class, but its parent is not Class, it's Object.
Yes and no. Yes, because as you wrote, it would end up with the same result (assuming you would add missing ends). No, as there is small difference in general case. To define anything within Class.new, you need to pass a ruby block, which is carrying, and has a full access to, the context it has been created in. So:
value = :hello
Hello = Class.new do
define_method value do
value
end
end
Hello.new.hello #=> :hello
value = :world
Hello.new.hello #=> :world
Note that the name of the method did not change. However, the value it returns did. This is not ideal and is the reason why class Hello is preferred in most of the cases to avoid doing it by accident (same as def keyword being preferred over define_method).
This will not work with class keyword, as it does not create ruby block:
class Hello2
define_method value do
value
end
end
#=> undefined local variable or method `value`
One more interesting fact about classes and constants is a behaviour of name method:
my_variable = Class.new
my_variable.name #=> nil
Hello = my_variable
my_variable.name #=> "Hello"
World = my_variable
my_variable.name #=> "Hello"
New to programming and to Ruby, and I hope this question about symbols is in line. I understand that symbols in Ruby (e.g., :book, :price) are useful particularly as hash keys, and for all-around doing a lightweight, specific subset of the things that strings can do.
However, I am confused about symbols in one respect. Specifically, when they're used in the attr_accessor types of methods, it appears that they are behaving more like a variable. E.g., attr_reader :book, :price.
If true that they are variables in that usage, this is a bit puzzling because they are not typically listed among variable types (like the $global, #instance, local, ##class, and sometimes, CONSTANT, variable types) when variables types are described.
And if symbols are variables when used this way, what scope should be expected of them? Or are they still somehow lightweight strings in this context as well? (Or perhaps in some broader way, do symbols, strings, and variables all share a fundamental duck-like nature?) Thank you in advance for your insights and advice.
Symbols are not variables, but a type of literal value, like numerals and quoted strings. Significantly, symbols are used to represent variables and other named values in the Ruby runtime. So when the Ruby interpreter sees the name foo used as a variable or method name, what it looks up in the Hash of runtime values is the symbol :foo, not the string "foo". This was, in fact, the original use of the term "symbol" in programming language terminology; variables, functions, constants, methods, and so on are said to be stored in the compiler or interpreter's "symbol table".
Pretty much any time you're passing around the name of something in Ruby, you're going to use a symbol. If you use method_missing as a catch-all to implement arbitrary methods on your object class, a symbol is what it receives as an argument telling it the name of the method that was actually called. If you inspect an object with .methods or .instance_variables, what you get back is an array of symbols. And so on.
They aren't variables because they don't hold values, they are immutable. The thing is the value itself. It's similar to numbers. You can't set the value of 1. 1 = 2 doesn't work.
Symbols used in accessor methods are not variables. They are just representing the name of a variable. Variables hold some reference, so you cannot use a variable itself in defining accessor methods. For example, suppose you wanted to define an accessor method for the variable #foo in a context where its value is "bar". What would happen if Ruby's syntax were to be like this:
attr_accessor #foo
This would be no different from writing:
attr_accessor "bar"
where you have no access to the name #foo that you are interested in. Therefore, such constructions have to be designed to refer to variable names at a meta level. Symbol is used for this reason. They are not variables themselves. They represent the name of a variable.
And the variable relevant to accessor methods are instance variables.
attr_accessor and such are all methods that belong to the class, Class. They expect symbols as arguments. You could write your own version of attr_ that used strings, if you wanted. Its just a ruby idiom. Here's an example of attr_acessor that stores all the previous values of attr_accessor I made for a homework assignment.
class Class
def attr_accessor_with_history(attr_name)
attr_name = attr_name.to_s # make sure it's a string
attr_reader attr_name # create the attribute's getter
attr_reader attr_name+"_history" # create bar_history getter
class_eval %Q"
def #{attr_name}=(value)
if !defined? ##{attr_name}_history
##{attr_name}_history = [nil]
end
##{attr_name} = value
##{attr_name}_history << value
end
"
end
end
Ruby's attr_accessor, attr_reader, and attr_writer are just shorthand ways of avoiding writing a bit of repetitive code. The following question expands on how these work: Why use Ruby's attr_accessor, attr_reader and attr_writer?
Instead of thinking of attr_reader :book as a variable, just think of it as a name of an attribute that is specified using a symbol.
To address your "If true that they are variables" and "scope" questions, it would have been simpler to answer that accessor symbols have nothing to do with instance variables, even if it sounds iconoclastic. They don't point to instance variables. Accessors only define getter and setter methods. Under Object#instance_variables, the Pickaxe(*) says : Note that simply defining an accessor does not create the corresponding instance variable.
In Ruby, a variable does not exist until you assign a value to it. The following code demonstrates this.
class MyClass
attr_accessor :name
attr_reader :book
end
obj = MyClass.new # line 6
print '1) obj.instance_variables : '; p obj.instance_variables
print '2) obj.name : '; p obj.name
obj.name = 'xyz'
print '3) obj.instance_variables : '; p obj.instance_variables
print '4) obj.name : '; p obj.name
print '5) obj.book : '; p obj.book
class MyClass
def initialize(p_book)
#book = p_book
end
end
obj = MyClass.new('The Pickaxe') # line 21
print '6) [new] obj.book : '; p obj.book
class MyClass
method_name = 'title'
attr_accessor method_name # line 26
end
obj.title = 'Programming Ruby'
print '7) obj.instance_variables : '; p obj.instance_variables
print '8) obj.title : '; p obj.title
Output :
$ ruby -w t.rb
1) obj.instance_variables : []
2) obj.name : nil
3) obj.instance_variables : ["#name"]
4) obj.name : "xyz"
5) obj.book : nil
6) [new] obj.book : "The Pickaxe"
7) obj.instance_variables : ["#title", "#book"]
8) obj.title : "Programming Ruby"
1) empty array : accessors have not defined instance variables
2) asking for instance variable #name answers nil : it does not exist
3) assigning a value has created the instance variable.
Note that name = is a syntactic sugar for using the setter as an ordinary method with a parameter : obj.name=('xyz')
4) the getter method name answers the value of #name
5) the getter method book answers nil because the instance variable #book does not exist. Defining an accessor attr_reader :book has not defined the corresponding instance variable
6) the getter method book answers the value assigned in initialize, called by new on line 21. The instance variable #book has been created by #book = p_book
line 26) I have always believed that accessors accept only symbols. I discover that a variable is possible, but of limited interest.
7) the setter method title= has created #title. This also shows that instance variables belong to a single object. We often believe that they belong to all instances of the class, as in other languages. In this case, #name belongs only to the object created on line 6.
8) the getter method title answers the value of #title
class MyClass
def title # line 34
#book + ' (cheating !)'
end
end
print '9) obj.title : '; p obj.title
Output :
t.rb:34: warning: method redefined; discarding old title
9) obj.title : "The Pickaxe (cheating !)"
9) of course there is a tight correlation between an accessor symbol and the corresponding instance variable, because, behind the scene, Ruby creates methods which reference an instance variable of the same name. You could define your own getter and cheat.
Note that besides class variables (##var, some dislike them as ugly as global variables), classes can also have instance variables. I call them class instance variables :).
class MyClass : Ruby allocates a new instance of class Class, defines a constant MyClass, and assigns the new instance to that constant. Thus MyClass is an ordinary object (instance of Class) and as such can have instance variables.
if RUBY_VERSION[0..2] == '1.8'
class Object
def singleton_class
class << self
self
end
end
end
end
class MyClass
singleton_class.instance_eval do
attr_accessor :counter
end
#counter = 0
def initialize(p_book)
#book = p_book
self.class.counter += 1
end
end
print '10) MyClass.singleton_methods : '; p MyClass.singleton_methods
print '11) MyClass.instance_variables : '; p MyClass.instance_variables
obj = MyClass.new('Ruby')
print '12) [new] obj.book ', MyClass.counter, ': '; p obj.book
obj = MyClass.new('Metaprogramming')
print '13) [new] obj.book ', MyClass.counter, ': '; p obj.book
Output :
t.rb:55: warning: method redefined; discarding old initialize
10) MyClass.singleton_methods : ["counter", "counter="]
11) MyClass.instance_variables : ["#counter"]
12) [new] obj.book 1: "Ruby"
13) [new] obj.book 2: "Metaprogramming"
More on singleton methods here : What does def `self.function` name mean?
(*) http://pragprog.com/book/ruby3/programming-ruby-1-9
(Answer to your comment)
dog = 'dog' or String.new("dog")
After dog = String.new, the field class of instance dog points to class String.
class << dog
puts "inside #{self}" #=> inside #<Class:#<String:0x007fb38a83a820>>
def bark
puts 'woof'
end
end
dog.bark #=> "woof"
p dog.singleton_methods #=> ["bark"]
With class << dog or def dog.bark, Ruby creates an anonymous class, the field class of instance dog now points to this anonymous class, and from there to String. Methods defined in this context with def or define_method go into the methods table of the anonymous class.
Ruby 1.9.2 has introduced Object#singleton_class. [The Pickaxe] Returns the singleton class of obj, creating one if necessary. (I add) It is equivalent to class << self; self end.
The Ruby Programming Language (O'Reiily) simply says : to open the eigenclass [singleton class] of the object o, use class << o.
So I don't know how to read it loud. I have read that some would prefer o >> class. It's only recently that I have found how to figure out what this strange expression means. I pronounce : go from o to it's anonymous class.
class << MyClass
def dog
puts 'dog as class method'
end
end
MyClass.dog #=> dog as class method
The same is true for a class. With class MyClass, MyClass, as instance of Class, is an object with a pointer to its class Class. With def MyClass.some_method or class << MyClass, Ruby creates an anonymous class which is inserted between MyClass and Class, and class methods go into it.
Maybe something like: "from class, instantiate singleton object self
Yes for "from class/object" to anonymous singleton class/eigenclass/metaclass.
But we don't instantiate self. Self (in Smaltalk, this in C++/Java) is kind of a reserved word which designate the receiver of the message. dog.bark : in OO language we say that the message bark in sent to object dog. Inside the method bark, self will be set to dog, so that we can reference dog. This is more obvious with
o1 = MyClass.new; o2 = MyClass.new
o1.some_method; o2.some_method
some_method must be able to reference the receiver in a generic way, is it o1 or o2, this is what self is for.
Cool, I guess you understand them by now.
However why are they so important?
Symbols in Ruby are immutable whereas strings are mutable.
You think ok cool, so what?
Let's assume you have an array of strings, like so:
[ "a", "b", "a", "b", "a", "b", "c" ]
For each new string you create ruby is going to create a string/object which holds the value of "a" and because strings are mutable things ruby assigns a different id to each of them.
If you were to use symbols instead:
[ :a, :b, :a, :b, :a, :b, :c ]
Ruby now will point to those symbols and it will only create them once.
Let's do some benchmarking:
require 'benchmark'
Benchmark.bm do |x|
x.report("Symbols") do
a = :a
1000_000.times do
b = :a
end
end
x.report("Strings") do
a = "a"
1000_000.times do
b = "a"
end
end
end
ruby -w symbols.rb
Symbols 0.220000 0.000000 0.220000 ( 0.215795)
Strings 0.460000 0.000000 0.460000 ( 0.452653)
If you'd like to see all the symbols you have already created you could do:
Symbol.all_symbols
You can also send a message to them asking about their id:
:a.object_id #=> 123
:a.object_id #=> 123
"a".id #=> 23323232
"a".id #=> some_blob_number
Again that's because Strings in Ruby are mutable and Symbols are not.
Ruby Symbols represent names inside the Ruby Interpreter.
This video really helped me:
Ruby's Symbols Explained
I hope it helps you all.
I am reading the Module documentation but can't seem to understand their differences and which should be used where.
How is the eval different than exec?
I'm going to answer a bit more than your question by including instance_{eval|exec} in your question.
All variations of {instance|module|class}_{eval|exec} change the current context, i.e. the value for self:
class Array
p self # prints "Array"
43.instance_eval{ p self } # prints "43"
end
Now for the differences. The eval versions accepts a string or a block, while the exec versions only accept a block but allow you to pass parameters to it:
def example(&block)
42.instance_exec("Hello", &block)
end
example{|mess| p mess, self } # Prints "Hello" then "42"
The eval version does not allow to pass parameters. It provides self as the first parameter, although I can't think of a use for this.
Finally, module_{eval|exec} is the same as the corresponding class_{eval|exec}, but they are slightly different from instance_{eval|exec} as they change what is the current opened class (i.e. what will be affected by def) in different ways:
String.instance_eval{ def foo; end }
Integer.class_eval { def bar; end }
String.method_defined?(:foo) # => false
String.singleton_methods.include?(:foo) # => true
Integer.method_defined?(:bar) # => true
So obj.instance_{eval|exec} opens the singleton class of obj, while mod.{class|module}_{eval|exec} opens mod itself.
Of course, instance_{eval|exec} are available on any Ruby object (including modules), while {class|module}_* are only available on Module (and thus Classes)
To answer your last question first, eval (in all its variations) is completely different from exec. exec $command will start a new process to run the command you specify and then exit when that finishes.
class_eval and module_eval have the power to redefine classes and modules -- even those that you yourself did not write. For example, you might use class eval to add a new method that did not exist.
Fixnum.class_eval { def number; self; end }
7.number # returns '7'
class_eval can be used to add instance methods, and instance_eval can be used to add class methods (yes, that part is very confusing). A class method would be something like Thing.foo -- you're literally calling the foo method on the Thing class. An instance method is like the example above, using class_eval I've added a number method to every instance of Fixnum.
Okay, so that's the *_eval class of methods. The exec methods are similar, but they allow you to look inside a class and execute a block of code as though it was defined as a method on that class. Perhaps you have a class that looks like this:
class Foo
##secret = 'secret key'
##protected = 'some secret value'
def protected(key)
if key == ##secret
return ##protected
end
end
end
The class Foo is just a wrapper around some secret value, if you know the correct key. However, you could trick the class into giving you its secrets by executing a block inside the context of the class like so:
Foo.class_exec { ##secret = 'i'm a hacker' }
Foo.protected('i'm a hacker') #returns the value of ##protected because we overwrote ##secret
In general, with a lot of the tools in ruby, you could use any of these to solve a lot of problems. A lot of the time you probably won't even need to unless you want to monkey patch a class some library you use has defined (although that opens up a whole can of worms). Try playing around with them in irb and see which you find easier. I personally don't use the *_exec methods as much as the *_eval methods, but that's a personal preference of mine.
To avoid ambiguity I'm going to call a method that belongs to (owned by) a singleton class a singleton method. The rest are instance methods. Although one might say that a singleton method of an object is an instance method of its singleton class.
tl;dr Use class_eval/module_eval on a class/module to define instance methods, and instance_eval on a class/module to define class methods (or to be more precise, use instance_eval to define singleton methods). Additionally you can use instance_eval to access instance variables.
A terminology is a bit lacking in this case. ruby maintains a stack of class references (cref for short). When you open/reopen a class, the corresponding class reference is pushed to the stack. And the current class refernece affects where def defines methods (to which class/module they're added).
Now, class_eval/module_eval and class_exec/module_exec are aliases.
The *_exec() variants don't accept strings, and allow to pass arguments to the block. Since the *_eval() variants are mainly used I'll focus on them.
class_eval/module_eval changes cref and self to the receiver (Thing in Thing.module_eval(...)):
rb_mod_module_eval() -> specific_eval()
yield_under() (for blocks)
vm_cref_push()
eval_under() (for strings)
vm_cref_push()
instance_eval changes cref to the singleton class of the receiver, and self to the receiver.
Let's see them in action:
class A
p self #=> A
#a = 1
def initialize
#b = 2
end
end
p A.instance_variables #=> [:#a]
p A.new.instance_variables #=> [:#b]
#a on a class level adds an instance variable to the class A as an object. I'm adding it here for completeness. But that's not how you add a class variable.
A.instance_eval do
p self #=> A
p #a #=> 1
def m() puts 'm' end
end
sclass = A.singleton_class
p sclass.instance_methods(false).include? :m #=> true
A.m #=> m
a = A.new
a.instance_eval do
p self #=> #<A:0x00007fc497661be8 #b=2>
p #b #=> 2
def m2() puts 'm2' end
end
sclass = a.singleton_class
p sclass.instance_methods(false).include? :m2 #=> true
a.m2 #=> m2
So, inside instance_eval def adds a singleton method to the receiver (an instance method to the singleton class of the receiver). For a class/module that means a class/module method. For other objects, a method that is available for that particular object.
A.class_eval do
p self #=> A
p #a #=> 1
def m() puts 'm' end
end
p A.instance_methods(false).include? :m #=> true
A.new.m #=> m
And, inside class_eval def adds an instance method to the receiver itself (the class/module). class_eval is only available for classes/modules.
Also, when class_eval is passed a block, constant/class variable lookup is not affected:
module A
C = 1
##c = 1
class B
C = 2
##c = 2
end
A::B.class_eval { p [C, ##c] } #=> [1, 1]
A::B.class_eval 'p [C, ##c]' #=> [2, 2]
end
The naming is confusing. I might guess that instance in instance_eval suggests that receiver is treated as an instance (allows to change things for a particular instance), and class in class_eval as a class (allows to change things for a class of objects).