I was bouncing around the Rails API documentation yesterday, and I noticed a few rails console
tricks I haven’t seen before. There’s been plenty of posts about irb
and Rails before, but I’m hoping you’ll learn something new here. The following console samples were taken with Basecamp Next on Rails version 3.2.3.
Dive into your app
Running the app
method in rails console
gives you an integration session instance, so you can use it just like when you’re a normal integration test for Rails.
>> app.class => ActionDispatch::Integration::Session
Generating routes was always a hassle. What module did I need to include again? Did you remember to set the default_url_options
? Stop googling and just use app
:
>> app.project_path(Project.first) => "/projects/130349783-with-attachments"
It can make requests inside of your app as well:
>> app.get "/735644780/projects/605816632-bcx.atom" => 200 >> app.response.body => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xml:lang=\"en-US\" ...
Check out ActionDispatch::Integration::Session and ActionDispatch::Integration::RequestHelpers to see what else this object can help you with.
Try out a helper
Getting a console session bootstrapped with Rails’ helpers is also a pain, which helper
can fix for you! You could also use it to play with building HTML tags, or any existing Rails helper that ActionView knows about.
>> helper.truncate("Testing", length: 4) => "T..." >> helper.link_to "Home", app.root_path => "<a href=\"/\">Home</a>"
One gotcha with helper
is using instance variables inside of helper methods. Yes, I’m aware this is a Bad Idea™ with helpers in general, but I haven’t worked in a single Rails app without one. Here’s a small example of a method with one:
def title_tag(title = nil)
if @project.present? && title.nil?
content_tag :title, @project.name
elsif @project.present?
content_tag :title, "#{@project.name}: #{title}"
else
content_tag :title, title
end
end
We can use our old friend Object#instance_variable_set
to violate a core principle of OOP and let us try this helper out in the console:
>> helper.title_tag "Testing!" => "<title>Testing!</title>" >> helper.instance_variable_set :@project, Project.first => #<Project id: 130349783, ... >> helper.title_tag => "<title>With attachments!</title>" >> helper.title_tag "Posts" => "<title>With attachments!: Posts</title>"
Dealing with a helper that uses params
is also not straightforward. However, we can trick ActionView into listening to us with a tiny hack. This is the console, after all! Let’s say we have this helper method:
def javascript_debugging_options
if params[:javascript_debugging] == "enabled"
{ debug: true, digest: false }
else
{}
end
end
Usually ActionView needs an entire ActionDispatch::Request
from the controller to figure out what parameters came in from the user. We can trick it with a little OpenStruct instead:
>> helper.controller = OpenStruct.new(params: {}) => #<OpenStruct params={}> >> helper.javascript_debugging_options => {} >> helper.controller = OpenStruct.new(params: {javascript_debugging: "enabled"}) => #<OpenStruct params={:javascript_debugging=>"enabled"}> >> helper.javascript_debugging_options => {:debug=>true, :digest=>false}
Where does that method come from?
Hunting down the exact location of a given method isn’t always easy. Luckily, Ruby can point you in the right direction with Method#source_location
:
>> Project.instance_method(:trash).source_location => ["/Users/qrush/37s/apps/bcx/app/models/project.rb", 90]
Whoa! You’ll get back an array with the full path of where the method was defined along with that method’s line number in the file.
I’ve used this when looking for code buried inside of gems as well. Let’s try it on app
:
>> app.method(:get).source_location => ["/Users/qrush/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/rails-7d95b814583b/actionpack/lib/action_dispatch/testing/integration.rb", 32]
This tip has saved me from an immense amount of source diving. Try it out!
More tips
Looking for more tips? JEG2 gave a neat talk at RailsConf about some of the hidden parts of Rails you might not know about. If you have some of your own, please share!
cmar
on 17 May 12The routing trick alone is worth reading this article. Thanks for the tips.
Tor
on 17 May 12if you are using pry instead of irb, you can use show-method “get” to see the source of a method
dharmarth
on 17 May 12Very useful tips..specially routing and helper…thanks for sharing
Wayne Robinson
on 17 May 12Always happy to learn something new. In 8 years of Ruby development I’ve never come across Method#source_location before. Seems extremely useful.
McPhage
on 17 May 12What order does it load the helpers into the helper object? In some cases, I have helpers with the same name in multiple FooHelpers (I don’t use helpers :all). Is there some way to make sure a particular one gets loaded or not loaded?
jipiboily
on 17 May 12Just like @cmar said, just the routing trick was worth the read. Thanks a lot!
Bradly Feeley
on 17 May 12Fyi.. source_location is only in Ruby 1.9
Joo Park
on 17 May 12just use a good ide and step through the code and use run evaluation to run some code.
André
on 17 May 12Somebody already recommended using Pry, but I’ll say it again. Check out pry! Use this to launch the console without having to install the separate pry-rails gem.
pry -r ./config/environment -r console_app -r console_with_helpers
Fareesh
on 17 May 12Pry is great! Can’t recommend it enough.
The 37Signals css for code blocks is a really tiny and unreadable font for me. Would be great if it were one font size bigger!
Cheers. Good post!
Ben
on 17 May 12Wow, I didn’t know about that instance variable in helper trick. I’ve always just used constants, the only annoying thing is all the warnings ruby spits at you.
Erik
on 17 May 12Wow, I did not know about the app and helper instances.. these will help me a ton!
ippa
on 18 May 12Where did the console-cmd “y” to print something as YAML go?
I used it all the time to inspect active record objects but it disappeared some minor versions ago? Is there a replacement I don’t know about? Getting by with the “awesome_print”-gem now but less dependencies are always a plus in my book.
Terence Ponce
on 18 May 12I’ve learned these earlier today on StackOverflow before I saw this article on HackerNews. What a strange coincidence. Here’s the link if anyone’s interested http://stackoverflow.com/questions/151030/how-do-i-call-controller-view-methods-from-the-console-in-rails
railwaymen
on 21 May 12Thanks for all recommendations. It’s always good to learn something new.
This discussion is closed.