Hi friends,
In my previous two blogs Rails Active Records Callbacks: Part 1 and Rails Active Records Callbacks: Part 2, I explained about available rails active records callbacks available. Now I will talk about some more callbacks methods available in rails:
a) after_initialize:
after_initialize callback is called whenever an active record object is created or initialized for the first time. Suppose you want to change some field during initialization of the object, it is best to use.
class TestUser < ActiveRecord::Base
after_initialize :call_after_initialize
def call_after_initialize
p "I am inside after initialize"
end
end
Now in console if you run:
# When an object is initialized
> t = TestUser.new
"I am inside after initialize"
=> #<TestUser id: nil, phone_number: nil, created_at: nil, updated_at: nil>
# When an object is fetched from DB:
> t = TestUser.first
TestUser Load (0.5ms) SELECT "test_users".* FROM "test_users" ORDER BY "test_users"."id" ASC LIMIT 1
"I am inside after initialize"
=> #<TestUser id: 1, phone_number: "+919876543210", created_at: "2016-06-08 16:19:04", updated_at: "2016-06-08 16:19:04">
b) after_find:
after_find is similar to after_initialize except that it gets called only when an object is fetched from DB and is not triggered when object is initialized. It gets called before after_initialize if both are defined for a model.
class TestUser < ActiveRecord::Base
after_initialize :call_after_initialize
after_find :call_after_find
def call_after_initialize
p "I am inside after initialize"
end
def call_after_find
p "I am inside after find"
end
end
Now in console try this:
# When an object is initialized after_find doesn't get invoked
> t = TestUser.new
"I am inside after initialize"
=> #<TestUser id: nil, phone_number: nil, created_at: nil, updated_at: nil>
# When an object is fetched from DB after_find gets called before after_initialize
t = TestUser.first
TestUser Load (0.5ms) SELECT "test_users".* FROM "test_users" ORDER BY "test_users"."id" ASC LIMIT 1
"I am inside after find" ## after_find gets triggered
"I am inside after initialize" ## after_initialize gets triggered
=> #<TestUser id: 1, phone_number: "124444+91", created_at: "2016-06-08 16:19:04", updated_at: "2016-06-08 16:19:04">
c) after_touch:
As its name suggests, It gets called whenever an active record is touched. As you can see in the example given:
class TestUser < ActiveRecord::Base
after_touch :call_after_touch
def call_after_touch
p "I am inside after touch"
end
end
Now try in console:
t = TestUser.first
TestUser Load (0.1ms) SELECT "test_users".* FROM "test_users" ORDER BY "test_users"."id" ASC LIMIT 1
=> #<TestUser id: 1, phone_number: "124444+91", created_at: "2016-06-08 16:19:04", updated_at: "2016-06-08 16:19:04">
> t.touch
(0.2ms) begin transaction
SQL (0.6ms) UPDATE "test_users" SET "updated_at" = '2016-06-11 09:47:34.498035' WHERE "test_users"."id" = ? [["id", 1]]
"I am inside after touch"
(199.4ms) commit transaction
=> true
Conditional Callbacks:
As a use case of adding a callback can be if in some cases we don't want a callback to be called and in same case we want it to be called, for this rails provides conditional callbacks methods that can be used to give a condition to the callback. they are :if and :unless.
a) :if is used where we want the callback to be called when the condition given after if returns true
b) :unless is used where we want the callback to be called when the condition given after unless returns false
They can be used with different types. Examples are given below:
## with symbol
class TestUser < ActiveRecord::Base
before_save :update_indian_phone_number, if: :is_indian?
before_save :update_international_phone_number, unless: :is_indian?
end
## with string
class TestUser < ActiveRecord::Base
before_save :update_indian_phone_number, if: "is_indian?"
before_save :update_international_phone_number, unless: "is_indian?"
end
## with procs
class TestUser < ActiveRecord::Base
before_save :update_indian_phone_number, if: Proc.new { |user| user.is_indian? }
before_save :update_international_phone_number, unless: Proc.new { |user| user.is_indian? }
end
0 Comment(s)