There are two semi-undocumented callbacks available to developers: after_find and after_initialize. Before we go any further explaining how these could be used and how to implement them, let me first echo the documentation:
Because after_find and after_initialize is called for each object instantiated found by a finder, such as Base.find_all, we’ve had to implement a simple performance constraint (50% more speed on a simple test case).
So, as you can see, using either of these callbacks can result in a huge performance hit, so continue at your own risk.
Say you are creating a system for managing insurance policies. Each policy has many different user types that may or may not be the same user depending on how differing companies run or policies are created. An example of this would be, a user Sally could be the introducing agent and the agent on a policy, but on a different policy she may only be the agent. You don’t want to have multiple Sally users in the system, so you sub-class your User class and create Agent, IntroducingAgent?, Adjuster, and Insured objects to represent the different types of users. You then create a has_and_belongs_to_many relationship between your Policy and User class and add a “type” column to your policies_users table. This will cause ActiveRecord to instantiate the different users when doing a find. You can now access these different types of users by iterating through the users array and checking the class type of that user. For example:
def agent
for user in policy.users
return user if user.is_a?(Agent)
end
end
This allows you to access the agent user using policy.agent, but it has the side effect of iterating through the users array everytime a call is made to the agent method. Wouldn’t it be nice if the Policy class could populate agent, referring_agent, insured, etc. instance variables immediately when the Policy object is being created? Implementing an after_find callback can make this happen.
Continuing from the example above we are going to create instance variables to the Policy class and then define an after_find callback to populate them so that they can be accessed later. The after_find callback needs to be explicitly defined inside the protected section of a model class. For example:
class Policy < ActiveRecord::Base
has_and_belongs_to_many :users
attr :adjuster, true
attr :agent, true
attr :introducing_agent, true
attr :insured, true
protected
def after_find
for user in users
case user
when Adjuster then @adjuster = user
when Agent then @agent = user
when IntroducingAgent @introducing_agent = user
when Insured then @insured = user
end
end
end
end
This example may not be the best, but hopefully you get the idea. In most cases, I think it’s still better (and faster) to build custom find methods that add on this type of additional functionality. But this document was more created to suppliment the documentation of these “hidden” callback methods.
category:Howto
There are two semi-undocumented callbacks available to developers: after_find and after_initialize. Before we go any further explaining how these could be used and how to implement them, let me first echo the documentation:
Because after_find and after_initialize is called for each object instantiated found by a finder, such as Base.find_all, we’ve had to implement a simple performance constraint (50% more speed on a simple test case).
So, as you can see, using either of these callbacks can result in a huge performance hit, so continue at your own risk.
Say you are creating a system for managing insurance policies. Each policy has many different user types that may or may not be the same user depending on how differing companies run or policies are created. An example of this would be, a user Sally could be the introducing agent and the agent on a policy, but on a different policy she may only be the agent. You don’t want to have multiple Sally users in the system, so you sub-class your User class and create Agent, IntroducingAgent?, Adjuster, and Insured objects to represent the different types of users. You then create a has_and_belongs_to_many relationship between your Policy and User class and add a “type” column to your policies_users table. This will cause ActiveRecord to instantiate the different users when doing a find. You can now access these different types of users by iterating through the users array and checking the class type of that user. For example:
def agent
for user in policy.users
return user if user.is_a?(Agent)
end
end
This allows you to access the agent user using policy.agent, but it has the side effect of iterating through the users array everytime a call is made to the agent method. Wouldn’t it be nice if the Policy class could populate agent, referring_agent, insured, etc. instance variables immediately when the Policy object is being created? Implementing an after_find callback can make this happen.
Continuing from the example above we are going to create instance variables to the Policy class and then define an after_find callback to populate them so that they can be accessed later. The after_find callback needs to be explicitly defined inside the protected section of a model class. For example:
class Policy < ActiveRecord::Base
has_and_belongs_to_many :users
attr :adjuster, true
attr :agent, true
attr :introducing_agent, true
attr :insured, true
protected
def after_find
for user in users
case user
when Adjuster then @adjuster = user
when Agent then @agent = user
when IntroducingAgent @introducing_agent = user
when Insured then @insured = user
end
end
end
end
This example may not be the best, but hopefully you get the idea. In most cases, I think it’s still better (and faster) to build custom find methods that add on this type of additional functionality. But this document was more created to suppliment the documentation of these “hidden” callback methods.
category:Howto