Reputation: 638
I have to set the table name of an associated model (limesurvey), because the table name is dynamic and depends on an attribute (survey_id) of the model (task).
My current implementation sets the table name, when the task is initialized:
class task < ActiveRecord::Base
after_initialize :setTablename
has_one :limesurvey
def setTablename
Limesurvey.table_name = "lime_survey_#{self.survey_id}"
end
end
This implementation works, but it has the disadvantage, that the setTablename-method is called for every task, although it isn't needed.
How can I execute setTablename only before the association limesurvey is loaded?
Upvotes: 2
Views: 177
Reputation: 6644
Associations are just methods defined in a module that is included in your model, so you can override them as you would other methods
class Task < ActiveRecord::Base
has_one :limesurvey
def limesurvey
# do something here...
super
end
end
However, as people have mentioned in the comments on the question, what you're doing is a really bad idea. What would happen if you have two tasks available at once, and attempted to access the limesurvey
on both of them?
t1 = Task.first
t2 = Task.last
l1 = t1.limesurvey
l2 = t2.limesurvey
l1.update_attributes(foo: "bar")
# Oops... saves into the wrong table...
Even if you manage to avoid doing this explicitly anywhere in your whole app, if you have two concurrent requests it could potentially happen accidentally!
Upvotes: 0
Reputation: 10099
Caveat: I agree that you are taking on a sea of troubles as the commenters have mentioned. Further, this will likely be worse, since before at lease setTablename was getting called for every task.
class Task < ActiveRecord::Base
has_one :limesurvey
def lime_survey
@table_name || = (Limesurvey.table_name = "lime_survey_#{self.survey_id}")
limesurvey
end
end
This defines a version of limesurvey with an underscore, but checks first if the table name has been set. Call lime_survey instead of limesurvey, and you will have the effect you asked for.
Similar to the approach suggested by Andy. However, although the association is just a method, I'm not sure you can redefine it and call super, since it's not a method in the parent class (or module).
Upvotes: 2