Basically I notice a big performance difference in dynamically overriding a getter for ActiveRecord::Base
models within an after_initialize
hook and simply within the model itself.
Say I have the following Concern:
Module Greeter
extend ActiveSupport::Concern
included do
after_initialize { override_get_greeting }
end
def override_get_greeting
self.class::COLS.each do |attr|
self.class.class_eval do
define_method attr do
"Hello #{self[attr]}!"
end
end
end
end
end
I then have the following model, consisting of a table with names.
CREATE TABLE 'names' ( 'name' varchar(10) );
INSERT INTO names (name) VALUES ("John")
class Name < ActiveRecord::Base
COLS = 'name'
include Greeter
end
john = Name.where(name: 'John').first
john.name # Hello John!
This works fine. However, if I try to do this a more Rails way it is significantly slower.
Essentially, I want to simply pass a parameter into Greeter
method that contains COLS
and then overrides the getters. It'll look something like:
# Greeter
Module Greeter
extend ActiveSupport::Concern
def override_get_greeting(cols)
cols.each do |attr|
self.class.class_eval do
define_method attr do
"Hello #{self[attr]}!"
end
end
end
end
end
# Name
class Name < ActiveRecord::Base
include Greeter
override_get_greeting :[name]
end
Now Name.where(name: 'John').first.name # Hello John!
is about 2 seconds slower on the first call.
I can't put my finger in it. I have an assumption that the the application is just slower to start with the first example, but not really sure.
I prefer the second example but the performance difference is a big no no.
Has anyone came across something like this?
Aucun commentaire:
Enregistrer un commentaire