Ok. You asked a lot of questions in one. It will be hard to explain all ruby and rails magic in one answer but I'll try to give you some useful resources where you can find some answers.
1) About require statements. If you are new to ruby and rails it will be hard to understand how rails application is initialized. Here is a tutorial were you can some useful information:
http://guides.rubyonrails.org/initialization.html
If you need more information about particular method you can always look into documentation. For example redirect_to method info:
http://apidock.com/rails/ActionController/Base/redirect_to
2) About "Using methods that don't exist". This is one of the most beautiful feature of ruby language called metaprogramming. This is also advanced topic. Here are some useful resources:
http://www.amazon.com/Metaprogramming-Ruby-Program-Like-Pros/dp/1934356476
Ruby metaprogramming online tutorial
http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/
http://rubylearning.com/blog/2010/11/23/dont-know-metaprogramming-in-ruby/
Well, in first place, you have to understand that you are calling a class method, thus you are at a class level already. The .new method is a class method, so you can call it directly without calling self.class.new.
Why does self.class.new return Class?
Because the class of the class Car is Class (I know, sounds weird ;), because classes in Ruby are instances of Class.
This is actually a pretty deep concept, I recommend you read more about it. One nice reference I have read is the book Metaprogramming Ruby by Paolo Perrotta (ISBN-10: 1934356476) [1].
So, as it turns out, yield isn't used at all. The block we pass to Application.routes.draw is just being evaluated in the context of an instance of ActionDispatch::Routing::Mapper.
If we add puts self to our config/routes.rb, we can see this in action:
Application.routes.draw do
puts self
end
When we run rake routes we get something similar to the following:
def make_class(method_name, method_body, s_value)
Class.new {
define_method method_name do |*args|
eval(method_body)
end
define_method :to_s do
s_value
end
}
end
First read the article in Wikipedia about self (even if it does not mention Ruby at all).
To make a long story short:
Ruby has borrowed a lot of concepts from other languages, and self comes from Smalltalk.
self is called in Smalltalk a pseudo-variable, which means it is variable, but it is set by the runtime environment, not by the program or programmer.
self references all the time the receiver of a message. super references the superclass of that message that is implemented by the method the reference super is in. (Glad that you did not ask for super).
self in Ruby (as in Smalltalk) references all the time the current object, and that may be an instance of a class or even a class itself. So if you define methods on the class-side (only callable on the class), even there self references the object, which is the class. So it is possible in Ruby to use only self, you never have to write down the name of the class to denote the receiver. That helps a little bit when refactoring.
In Ruby local variables only accessible in the scope that they are defined. Whenever you enter/leave a Class, a Module or a Method definiton your scope changes in Ruby.
For instance :
v1 = 1
class MyClass # SCOPE GATE: entering class
v2 = 2
local_variables # => ["v2"]
def my_method # SCOPE GATE: entering def
v3 = 3
local_variables # => ["v3"]
end # SCOPE GATE: leaving def
local_variables # => ["v2"]
end # SCOPE GATE: leaving class
These entering and leaving points are called Scope Gates. Since you enter through Scope Gate via method definition you cannot access your local_var inside hello method.
You can use Scope Flattening concept the pass your variable through these gates.
For instance instead of using def for defining your method you can use Module#define_method.
local_var = "Hello"
define_method :hello do
puts local_var
end
In the same way you can define your classes via Class#New so that your scope does not change when you pass through class definition.
local_var = 'test'
MyClass = Class.new do
puts local_var #valid
end
instead of
class MyClass
puts local_var #invalid
end
In the same way you should use Module#New if you want to pass your local variables through Module gates.
Ok. You asked a lot of questions in one. It will be hard to explain all ruby and rails magic in one answer but I'll try to give you some useful resources where you can find some answers.
1) About require statements. If you are new to ruby and rails it will be hard to understand how rails application is initialized. Here is a tutorial were you can some useful information:
http://guides.rubyonrails.org/initialization.html
If you need more information about particular method you can always look into documentation. For example redirect_to method info:
http://apidock.com/rails/ActionController/Base/redirect_to
2) About "Using methods that don't exist". This is one of the most beautiful feature of ruby language called metaprogramming. This is also advanced topic. Here are some useful resources:
http://www.amazon.com/Metaprogramming-Ruby-Program-Like-Pros/dp/1934356476
Ruby metaprogramming online tutorial
http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/
http://rubylearning.com/blog/2010/11/23/dont-know-metaprogramming-in-ruby/
I don't understand your example. Are you generating the source for the method as well?
So I will start with an example from the book Perrotta: Metaprogramming Ruby
Instead of
just write
Why is this?
Well, in first place, you have to understand that you are calling a class method, thus you are at a class level already. The .new method is a class method, so you can call it directly without calling self.class.new.
Why does self.class.new return Class?
Because the class of the class Car is Class (I know, sounds weird ;), because classes in Ruby are instances of Class.
This is actually a pretty deep concept, I recommend you read more about it. One nice reference I have read is the book Metaprogramming Ruby by Paolo Perrotta (ISBN-10: 1934356476) [1].
root
is defined onActionDispatch::Routing::Mapper::Base
, which is included byActionDispatch::Routing::Mapper
.There is a little more going on behind the scenes than at first glance.
If we look at the definition of
draw
, we can see why:The block is converted to a proc (with
&
) and passed toeval_block
which is defined a bit farther down:So, as it turns out,
yield
isn't used at all. The block we pass toApplication.routes.draw
is just being evaluated in the context of an instance ofActionDispatch::Routing::Mapper
.If we add
puts self
to ourconfig/routes.rb
, we can see this in action:When we run
rake routes
we get something similar to the following:For further reading, see:
http://ruby-doc.org/core-1.8.7/Object.html#method-i-instance_exec https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/route_set.rb#LC296 https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/mapper.rb#LC336 http://www.amazon.com/Metaprogramming-Ruby-Program-Like-Pros/dp/1934356476
"Metaprogramming Ruby" is well worth adding to your bookshelf. http://www.amazon.co.uk/Metaprogramming-Ruby-Program-Like-Facets/dp/1934356476/
"Metaprogramming Ruby: Program Like the Ruby Pros" is a very good book to learn about ruby metaprogramming.
First read the article in Wikipedia about self (even if it does not mention Ruby at all).
To make a long story short:
self
comes from Smalltalk.self
is called in Smalltalk a pseudo-variable, which means it is variable, but it is set by the runtime environment, not by the program or programmer.self
references all the time the receiver of a message.super
references the superclass of that message that is implemented by the method the referencesuper
is in. (Glad that you did not ask forsuper
).self
in Ruby (as in Smalltalk) references all the time the current object, and that may be an instance of a class or even a class itself. So if you define methods on the class-side (only callable on the class), even thereself
references the object, which is the class. So it is possible in Ruby to use onlyself
, you never have to write down the name of the class to denote the receiver. That helps a little bit when refactoring.If you have get all that, take a look at Metaprogramming Ruby which tells you some more tricks how to use
self
, classes, eigenclasses and some other interesting things.In Ruby local variables only accessible in the scope that they are defined. Whenever you enter/leave a Class, a Module or a Method definiton your scope changes in Ruby.
For instance :
These entering and leaving points are called Scope Gates. Since you enter through Scope Gate via method definition you cannot access your
local_var
insidehello
method.You can use Scope Flattening concept the pass your variable through these gates.
For instance instead of using
def
for defining your method you can useModule#define_method
.In the same way you can define your classes via
Class#New
so that your scope does not change when you pass through class definition.instead of
In the same way you should use
Module#New
if you want to pass your local variables through Module gates.Example is taken from Metaprogramming Ruby