Callbacks are calling...
rockshellS
Posted on March 16, 2021
Writing my second blog for Flatiron has taken me down some worm holes. Which hasn't been a bad thing! While learning Ruby on Rails we came across Validations, and how/when to use them. Validations are used to ensure that only valid data is saved into your database. Seems like a secure way to handle information. A Callback is called before or after the Validation is called. These actions happen fast and are considered magic.
-Callbacks are methods that get called at certain moments of an object’s life cycle. With them is possible to write code that will run whenever an ActiveRecord object is created, saved, updated, deleted, validated or loaded from the database - Ruby on Rails Guide
In rails c,
run ActiveRecord::Callbacks::CALLBACKS
=> [:after_initialize, :after_find, :after_touch,
:before_validation, :after_validation, :before_save,
:around_save, :after_save, :before_create, :around_create,
:after_create, :before_update, :around_update, :after_update,
:before_destroy, :around_destroy, :after_destroy,
:after_commit, :after_rollback]
this is a list of available callbacks.
In order to use callbacks, you need to register them. Which means you need to add them to your Model using the correct method. You can do this four different ways:
- Method references (symbol)- recommended
- Callback objects -recommended
- Inline methods (using a proc)-when appropriate
- Inline evals methods (using a string)-deprecated
Here are some examples on how to use them. These code examples are from the ActiveRecords guide page
http://guides.rubyonrails.org/active_record_callbacks.html
class User < ApplicationRecord
validates :login, :email, presence: true
before_validation :ensure_login_has_a_value
private
def ensure_login_has_a_value
if login.nil?
self.login = email unless email.blank?
end
end
end
This callback before_validation is making sure that the user has a valid login before it will run the validates method. By calling the ensure_login_has_a_value method wrote in the private section in the User class. Everything happens here in the model.
You can pass blocks ( useful for short one-liner logic )
class User < ApplicationRecord
validates :login, :email, presence: true
before_create do
self.name = login.capitalize if name.blank?
end
end
Callbacks can also be registered to only fire on certain life cycle events:
class User < ApplicationRecord
before_validation :normalize_name, on: :create
# :on takes an array as well
after_validation :set_location, on: [ :create,
:update ]
private
def normalize_name
self.name = name.downcase.titleize
end
def set_location
self.location = LocationService.query(self)
end
end
Here before_validation is calling the normalize_name method on: :create. Which will make sure the User name is in downcase and titlized. The after_validation is calling the set_location method on: [ :create, :update ]
Relational Callbacks:
class User < ApplicationRecord
has_many :articles, dependent: :destroy
end
class Article < ApplicationRecord
after_destroy :log_destroy_action
def log_destroy_action
puts 'Article destroyed'
end
end
irb>
user = User.first
=> #<User id: 1>
irb>
user.articles.create!
=> #<Article id: 1, user_id: 1>
irb>
user.destroy
Article destroyed
=> #<User id: 1>
Here the user has many accounts and when they delete their account all their articles should be deleted as well by using dependent: :destroy.
Another example of registering callbacks with callback macros is that they are inheritable
class Sweet < ApplicationRecord
before_save :do_something_with_sweet
end
class Vendor < ApplicationRecord
before_save :do_something_with_vendor
end
Here when the save method is call on Vendor instance, both :do_something_with_sweet and :do_something_with_vendor are triggered.
class Comment < ApplicationRecord
after_create :send_email_to_author, if:
:author_wants_emails?,
unless: Proc.new { |comment|
comment.article.ignore_comments? }
end
Here the after_create will send_email_to_author if author_wants_emails.
unless (Proc is looping thorough all the comments) and the people who had comments wouldn't get an email.
It’s possible to skip callbacks with these methods: http://guides.rubyonrails.org/active_record_callbacks.html
- decrement!
- decrement_counter
- delete
- delete_all
- delete_by
- increment!
- increment_counter
- insert
- insert!
- insert_all
- insert_all!
- touch_all
- update_column
- update_columns
- update_all
- update_counters
- upsert
- upsert_all
Conclusion, There are so many different fun ways for Callbacks to be used. They are magical and should be used sparingly. Using too many could become a problem and hard to navigate. I hope this was helpful.
Posted on March 16, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 30, 2024
November 30, 2024