I've been experiencing a performance issue using Edge and it appears to be related to how Dependencies handles classes that are generated at runtime. I'll give a simplified scenario of my problem for the sake of clarity. These are the migrations:
001_create_publications.rb: class CreatePublications < ActiveRecord::Migration def self.up create_table :publications do |t| t.column :name, :string t.column :type, :string end end
def self.down drop_table :publications end end
These are the current values in the table: 1, 'A Tale of Two Cities', 'Book' 2, '1984', 'Book'
And the models...
app/models/publication.rb: class Publication < ActiveRecord::Base end
Now, Book would be a model that is generated at runtime (i.e., it is not found in a file). While it wouldn't necessarily make sense for this sort of setup, it does in a plugin like acts_as_versioned that generates a, for example, Publication::Version class at runtime.
So this is what I'm running in the console:
Loading development environment.
Object.const_set('Book', Class.new(Publication))
=> Book
Book.find(:all)
=> [#<Book:0x5966dd8 @attributes={"name"=>"A Tale of Two Cities", "type"=>"Book", "id"=>"1"}>, #<Book:0x5965898 @attributes={"name"=>"A Tale of Three Cities", "type"=>"Book", "id"=>"2"}>]
Book.find(:all)
=> [#<Book:0x5961ff4 @attributes={"name"=>"A Tale of Two Cities", "type"=>"Book", "id"=>"1"}>, #<Book:0x5960ab4 @attributes={"name"=>"A Tale of Three Cities", "type"=>"Book", "id"=>"2"}>]
This produces the right results, however a log from the dependencies shows the following:
Book Columns (0.000000) SHOW FIELDS FROM publications Book Load (0.016000) SELECT * FROM publications WHERE ( (publications.`type` = 'Book' ) ) Dependencies: called require_or_load("/book", nil) Dependencies: loading /book Dependencies: called load_file("/book.rb", ) Dependencies: called new_constants_in() Dependencies: called require_or_load("/book", nil) Dependencies: loading /book Dependencies: called load_file("/book.rb", ) Dependencies: called new_constants_in() Book Load (0.016000) SELECT * FROM publications WHERE ( (publications.`type` = 'Book' ) ) Dependencies: called require_or_load("/book", nil) Dependencies: loading /book Dependencies: called load_file("/book.rb", ) Dependencies: called new_constants_in() Dependencies: called require_or_load("/book", nil) Dependencies: loading /book Dependencies: called load_file("/book.rb", ) Dependencies: called new_constants_in()
As a result of how things are currently working, it appears as though it will try to look for a book file every single time an instance of Book is instantiated, regardless of whether it's looked for it before. This seems to be what is causing my performance issue.
My question is: Is this behavior expected? That is, should ActiveRecord classes that are generated at runtime be causing Dependencies to constantly look for the file?
A first crack at the issue shows that require_association_class in associations.rb is calling require_association, which in turn will cause the Dependencies to look for a file named 'book'. This is regardless of whether the constant already exists. I'm tempted to add a conditional that only calls require_association if the constant does not already exist (or even going deeper and having associate_with check if the constant exists). However, I haven't yet looked into the issues this could cause with other parts of ActiveRecord.
Thanks to anyone who might have insight into the issue.