I’m working with Spree, which uses Rails engines extensively. A common pattern I find is this. However I have trouble understanding this code.
class Engine < Rails::Engine
def self.activate
...
end
config.to_prepare &method(:activate).to_proc
end
- What does
.to_preparedo - What does the
&methodoperator do? - What is the overall effect of the code?
Many Thanks!
&method(:activate).to_procThis is best consumed one item at a time. (It should be noted that this portion of the code is 100% non-Rails-specific Ruby.)
methodis a Ruby method (it’s all very meta). It is documented thusly:Check out the following IRB session:
So the
methodcall is looking up (in your example) theactivatemethod and creating aMethodobject for it.Methodcontains a method calledto_proc, which “returns a Proc object corresponding to this method“. Continuing our IRB session:Finally, we use the ampersand operator, which, when preceding a
Procobject during a method call, will be replaced by the block theProccontains. One more time in IRB:So, in pseudocode, what the line you listed is saying is:
config.to_prepare[Edited based on schof’s comment]
config.to_preparetakes a block that should be run to set up your Railtie/Engine. It is run once in production mode and on every request in development, and is the only code guaranteed to be called on every single request in development mode. This is important if you are modifying classes (class_eval, etc.) as part of your engine initialization; otherwise, you’re going to see different behavior in development vs. production.But Why?
The reason this is a common idiom is so that you don’t have to define your preparation code inside the
to_prepareblock itself; you can define method(s) in your class and then convert them to a block (which remembers its scope) using the magic described above. The code is functionally equivalent to: