Hi, this is Greg with the second issue of Rails Tricks!
This week, I want to share a few Rails console tricks I use regularly.
The first one is the _
command, which always holds the return value of the last evaluated command in IRB, which is the default for Rails` console. For instance, if you run an Active Record query to find a record, then you realize that you want to keep the result around, you can easily assign it to a variable:
irb(main):001:0> User.find_by(email: 'looking_for_you@gmail.com')
=>
#<User:0x00007f4b0fa3e150 ...
...
irb(main):002:0> user = _
=>
#<User:0x00007f4b0fa3e150 ...
...
Another thing I regularly do is, look up the definition of methods or the location of their definition.
This comes in handy when you are debugging an issue and can be helpful to see what a method actually does or where it is defined. Because maybe a gem overrides it, and that causes unexpected behavior.
In a Rails console, to see the definition, you can use Object.method(:name).source
:
irb(main):009:0> puts User.method(:all).source
def all
scope = current_scope
if scope
if self == scope.klass
scope.clone
else
relation.merge!(scope)
end
else
default_scoped
end
end
=> nil
And if you want to verify that all
is defined in Active Record and nothing overrides it in your application, you can check the location of the definition:
irb(main):010:0> puts User.method(:all).source_location
/home/gregmolnar/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activerecord-7.0.4.2/lib/active_record/scoping/named.rb
22
=> nil
The source
method is actually added by a gem called method_source
, which was part of Rails between 7.1, but it will be removed with that release, so if you still want to be able to see the definition of methods in your console, you will need to add that gem to your Gemfile.
The next thing I want to share is the --sandbox
option. If you pass this option when you start your console, every database modification will be rolled back on exit. This can be useful when you are debugging something in production, and you want to make sure you are not messing up something accidentally.
You can also read the documentation of Ruby classes inside the console by typing help('String')
for instance.
And the final thing is to have some fun! Type IRB.send(:easter_egg, :dancing)
or IRB.send(:easter_egg, :logo)
in your IRB session and enjoy the result!
You can exit by pressing CTRL+C.
P.S.: I just came across this blog post recently from Jemma about the measure
command in IRB: https://jemma.dev/blog/irb-measure. I haven’t used this one yet, but probably will in the future.
This week I have a special guest trick!
Hello there, I'm Adrian, the author of Avo, and I'm excited to share a neat trick with you today. In this tutorial, I'll be demonstrating how to attach hooks and business logic to Avo's controllers using a Current
model.
You may already be familiar with Rails' Current model, which is used to set the current user, multi-tenancy accounts, or other pieces of information. Typically, before_action
is used in your ApplicationController
to demonstrate how Current
works. However, if you attempt to apply the same changes to your app the action will not work in Avo's context. This is because Avo has its own ApplicationController
.
So how do we apply this behavior inside Avo? Let me walk you through it.
Firstly, we configure the Current
model and create the concern that holds the business logic.
# app/models/current.rb
class Current < ActiveSupport::CurrentAttributes
attribute :account, :user
end
# app/controllers/concerns/authentication.rb
module Authentication
extend ActiveSupport::Concern
included do
before_action :set_current
end
def set_current
Current.user = current_user
Current.account = user.account
end
end
Next, we add this concern to Avo's ApplicationController
using Rails' to_prepare
hook:
# config/initializers/avo.rb
Rails.configuration.to_prepare do
Avo::ApplicationController.include Authentication
end
With this setup, our Authentication
concern will be applied to the Avo::ApplicationController
, and it will be executed within Avo's context.
This technique can also be applied to other classes, such as including all helpers inside Avo's field declarations:
# app/avo/concerns/field_extensions.rb
module FieldExtensions
# Include all helpers
helper_names = ActionController::Base.all_helpers_from_path Rails.root.join("app", "helpers")
helpers = ActionController::Base.modules_for_helpers helper_names
helpers.each do |helper|
send(:include, helper)
end
end
# config/initializers/avo.rb
Rails.configuration.to_prepare do
Avo::Fields::BaseField.include FieldExtensions
end
Adrian ✌
That’s it for this week, see you next time!
Greg
Did you enjoy reading this? Sign up to the Rails Tricks newsletter for more content like this!
Or follow me on Twitter
I run an indie startup providing vulnerability scanning for your Ruby on Rails app.
It is free to use at the moment, and I am grateful for any feedback about it.If you would like to give it a spin, you can do it here: Vulnerability Scanning for your Ruby on Rails app!