require 'initializer' unless defined? ::Rails::Initializer require 'action_controller/dispatcher' unless defined? ::ActionController::Dispatcher module HasManyPolymorphs =begin rdoc Searches for models that use has_many_polymorphs or acts_as_double_polymorphic_join and makes sure that they get loaded during app initialization. This ensures that helper methods are injected into the target classes. Note that you can override DEFAULT_OPTIONS via Rails::Configuration#has_many_polymorphs_options. For example, if you need an application extension to be required before has_many_polymorphs loads your models, add an after_initialize block in config/environment.rb that appends to the 'requirements' key: Rails::Initializer.run do |config| # your other configuration here config.after_initialize do config.has_many_polymorphs_options['requirements'] << 'lib/my_extension' end end =end MODELS_ROOT = "#{RAILS_ROOT}/app/models/" DEFAULT_OPTIONS = { :file_pattern => "#{MODELS_ROOT}**/*.rb", :file_exclusions => ['svn', 'CVS', 'bzr'], :methods => ['has_many_polymorphs', 'acts_as_double_polymorphic_join'], :requirements => []} mattr_accessor :options @@options = HashWithIndifferentAccess.new(DEFAULT_OPTIONS) # Dispatcher callback to load polymorphic relationships from the top down. def self.autoload _logger_debug "autoload hook invoked" options[:requirements].each do |requirement| _logger_warn "forcing requirement load of #{requirement}" require requirement end Dir.glob(options[:file_pattern]).each do |filename| next if filename =~ /#{options[:file_exclusions].join("|")}/ open(filename) do |file| if file.grep(/#{options[:methods].join("|")}/).any? begin modelname = filename[0..-4] modelname.slice!(MODELS_ROOT) model = modelname.camelize _logger_warn "preloading parent model #{model}" model.constantize rescue Object => e _logger_warn "#{model} could not be preloaded: #{e.inspect}" end end end end end end class Rails::Initializer #:nodoc: # Make sure it gets loaded in the console, tests, and migrations def after_initialize_with_autoload after_initialize_without_autoload HasManyPolymorphs.autoload end alias_method_chain :after_initialize, :autoload end ActionController::Dispatcher.to_prepare(:has_many_polymorphs_autoload) do # Make sure it gets loaded in the app HasManyPolymorphs.autoload end