I have following setup:
app/models/my_module/service.rb
module MyModule
class Service < ActiveRecord::Base
def self.types
self.subclasses
end
def self.raw_types
self.types.map { |c| c.name.split("::").last }
end
end
end
require_dependency "my_module/service/rack"
require_dependency "my_module/service/rails"
require_dependency "my_module/service/sinatra"
app/models/my_module/service/rack.rb:
module MyModule
class Service::Rack < Service
end
end
app/models/my_module/service/rails.rb:
module MyModule
class Service::Rails < Service
end
end
app/models/my_module/service/sinatra.rb:
module MyModule
class Service::Sinatra < Service
end
end
That works so far, but now my question:
Why I have to add these three lines:
require_dependency "my_module/service/rack"
require_dependency "my_module/service/rails"
require_dependency "my_module/service/sinatra"
to my service.rb file?
If I don't add the three lines:
MyModule::Service.raw_types
=> []
If I add the three lines:
MyModule::Service.raw_types
=> ["Rack", "Rails", "Sinatra"]
Anybody an idea?
Btw: I use Ruby 2.0.0-preview1, Rails 4.0.0.rc1 and create a new Rails engine with
rails plugin new MyModule
By default, in the development environment, Rails will autoload constants in the usual subdirectories of app
, by looking in the conventional place (e.g., /app/models/my_module/service/rack.rb
for MyModule::Service::Rack
). This autoloading happens when the constant is referenced for the first time, not on app initialization.
But this means that before the constant is referenced, the file that defines it is not loaded unless it is explicitly required.
Thus, when you call MyModule::Service.raw_types
, MyModule::Service
is loaded from app/models/my_module/service.rb
if it isn't already defined. However, if no reference has yet been made to its subclasses, those constants won't be defined unless the files that define them are explicitly required. Thus, requiring those files in the file that is autoloaded on that method call makes them available.
Moral: if you want to ensure that the subclasses of MyModule::Service
are always defined whenever MyModule::Service
is, you need to require them in /app/models/my_module/service.rb
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With