Reputation: 467
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.
Upvotes: 0
Views: 65
Reputation: 62648
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.
Upvotes: 1