run script after initialize

hi there!!

I'm just trying to run a script that adds certain methods to all ActiveRecord::Base descendants, but what happens is that it seems that all models are loaded after the application runs

ActiveRecord::Base.send(:descendants).each do |subclass| #do stuff end

ActiveRecord::Base.send(:descendants) and ActiveRecord::Base.send(:subclasses) is allways empty .

I've tried it on config/environment.rb and config/application.rb with no success, can someone tell me what i can do about it?

Thanks!

hi there!!

I'm just trying to run a script that adds certain methods to all ActiveRecord::Base descendants, but what happens is that it seems that all models are loaded after the application runs

ActiveRecord::Base.send(:descendants).each do |subclass| #do stuff end

ActiveRecord::Base.send(:descendants) and ActiveRecord::Base.send(:subclasses) is allways empty .

I've tried it on config/environment.rb and config/application.rb with no success, can someone tell me what i can do about it?

You could just reopen ActiveRecord::Base. Create a new initializer (a ruby file in config/initializers) with:

class ActiveRecord::Base   def new_method     # do stuff   end end

Does that help? Jeremy Walker http://www.ihid.co.uk

Jeremy Walker wrote in post #1059748:

ActiveRecord::Base.send(:descendants) and ActiveRecord::Base.send(:subclasses) is allways empty .

I've tried it on config/environment.rb and config/application.rb with no success, can someone tell me what i can do about it?

You could just reopen ActiveRecord::Base. Create a new initializer (a ruby file in config/initializers) with:

class ActiveRecord::Base   def new_method     # do stuff   end end

Does that help? Jeremy Walker http://www.ihid.co.uk

Not in my case. What I want to do is define different method names depending on its relation, for example:

ActiveRecord::Base.send(:descendants).each do |subclass|         subclass.reflect_on_all_associations.each do |association|           macro = association.macro #:has_one, :has_many...           subclass.send(:define_method, "#{association.name}_tokens") do             read_attribute(__method__[0..-8])           end        end end

tryied something different, but no success again:

Dir[Rails.root.join('app/models/*.rb').to_s].each do |filename|         require filename #Connection not stablished...         klass = File.basename(filename).sub(/.rb$/, '').classify.safe_constantize         next unless klass.nil? || klass.ancestors.include?(ActiveRecord::Base)         klass.reflect_on_all_associations.each do |association|           klass.send(:define_method, "#{association.name.to_s}_tokens") do             read_attribute(__method__)           end         end       end

It raises connection not stablished.

Guillem Vidal wrote in post #1059754:

Jeremy Walker wrote in post #1059748:

ActiveRecord::Base.send(:descendants) and

ActiveRecord::Base.send(:subclasses) is allways empty .

I’ve tried it on config/environment.rb and config/application.rb with no

success, can someone tell me what i can do about it?

You could just reopen ActiveRecord::Base. Create a new initializer (a

ruby file in config/initializers) with:

class ActiveRecord::Base

def new_method

# do stuff

end

end

Does that help?

Jeremy Walker

http://www.ihid.co.uk

Not in my case. What I want to do is define different method names

depending on its relation, for example:

ActiveRecord::Base.send(:descendants).each do |subclass|

subclass.reflect_on_all_associations.each do |association|

      macro = association.macro #:has_one, :has_many...

      subclass.send(:define_method, "#{[association.name](http://association.name)}_tokens") do

        read_attribute(__method__[0..-8])

      end

   end

end

OK, so two more suggestions:

  1. Use an after_initialize block in your config (http://guides.rubyonrails.org/configuring.html#rails-general-configuration) to call your method_creation code.

  2. Re-open the class (as per my prev suggestion) but write a create_association_tokens method that contains the code to define your reflected methods, and use ActiveRecord::Base’s after_initialize method to call that method on an object, thus creating your methods on an object-by-object basis, rather than for the class.

I’m intrigued by the point of all this?

Well, I'd create a file and put it in /lib and include/initialize that file in the config.ru file before the actual app initialization (run YourApp::Application).

Jeremy Walker wrote in post #1059759:

> You could just reopen ActiveRecord::Base. Create a new initializer (a > http://www.ihid.co.uk       end end

OK, so two more suggestions: 1) Use an after_initialize block in your config ( Configuring Rails Applications — Ruby on Rails Guides) to call your method_creation code. 2) Re-open the class (as per my prev suggestion) but write a create_association_tokens method that contains the code to define your reflected methods, and use ActiveRecord::Base's after_initialize method to call that method on an object, thus creating your methods on an object-by-object basis, rather than for the class.

I'm intrigued by the point of all this?

Sorry about the delay, I couldn't access to a computer since now :(.

Done it, but it raises me an error because i have a attr_writer, i need to initialize the method.

module MyModule def self.included(base)   base.send(:extend, InstanceMethods)   base.send(:after_initialize, :set_reader_writer_tokens) end

module InstanceMethods   def set_reader_writer_tokens     class.reflect_on_all_associations.each do |association|       class.send(:define_method,"#{association.name.to_s}_tokens") do         attribute(__method__)       end       self.class.send(:define_method, "#{association.name.to_s}_tokens=") do |value|         write_attribute(__method__, self.another_custom_method)       end     end   end end

ActiveRecord::Base.send(:include, MyModule)

Loading development environment (Rails 3.2.2) class OptionType < ActiveRecord::Base belongs_to :type end

OptionType.new(:type_tokens => "ba,b") raises an unknown attribute :type_tokens.

But if I first initialize the record withouth accessing to the attribute:

OptionType.new

=> #<OptionType ...>

OptionType.new(:type_tokens => "ba,b")

=> #<OptionType id: nil, name: nil, presentation: nil, created_at: nil, updated_at: nil>

Then I can done it. The problem is that I need to set up that attribute before the initialitzation of the class.

Is a very good approach, but still not enogh for a ruby on rails application.

Maybe it can be done using method_missing... but I'm a little bit scared of overwriting activerecord method_missing, also it's not clear.

Rodrigo Vieira wrote in post #1059873:

Well, I'd create a file and put it in /lib and include/initialize that file in the config.ru file before the actual app initialization (run YourApp::Application).

That worked! The problem is that this is only working when rails app starts, not on rake tasks or test/units.

But from now on, what I need for my application is ok.

Just to know... Is it possible to do add those methods on the entire application? (not only on the middleware)

If the config.ru trick doesn't work for you, you should try the same but only initializing the file in config/boot.rb, instead. This should work for sure.