How to run arbitrary rails code when binding.pry is called - ruby-on-rails

Is there a way to run code just when binding.pry is called? I want to do ActiveRecord::Base.logger = Logger.new(STDOUT) to see sql queries.
I want this to run every time binding.pry is used, not just manually once.

A pry hook can be executed just before landing on the pry prompt
Pry.hooks.add_hook(:before_session, "my_hook") do |output, binding, pry|
ActiveRecord::Base.logger = Logger.new(STDOUT)
end
The pry folks have documented this well at github.com/pry/pry/wiki/Hooks

Related

How can I run an ActiveJob in Rails console for debugging?

I currently have an ActiveJob that I've created and use Sidekiq to queue it. I'm wanting to debug the job, but for me to see any messages I program into it I have to check my log files. I feel like it would be more convenient to be able to see my puts messages in my job in the Rails Console. When I run the perform_later method though in rails console it just queues the job up and I never see the messages in console. Is there a way to make it where I will see them in the console?
You can run a job with perform_now.
For example...
class Foo < ActiveJob::Base
def perform(arg1)
puts "Hello #{arg1}"
end
end
Foo.perform_now('world')
You can temporarily set your queue adapter to inline.
Right now your code in application.rb will look something like this:
Rails.application.config.active_job.queue_adapter = :sidekiq
Just comment out the line
# Rails.application.config.active_job.queue_adapter = :sidekiq
This will run your job inline, and you should see the results in the console.
You can run with new, Eg.Foo.new.perform(ar_1, ar_2)
There is a configuration line you can add in development.rb
require 'sidekiq/testing/inline'
This should enable inline testing for development.

How to run code automatically when launching a Rails console?

Let's say I wanted a greeting every time the Rails console comes up:
Scotts-MBP-4:ucode scott$ rails c
Loading development environment (Rails 4.2.1)
Hello there! I'm a custom greeting
2.1.5 :001 >
Where would I put the puts 'Hello there! I\'m a custom greeting' statement?
Another Stackoverflow answer suggested, and I've read this elsewhere too, that I can put that in an initializer like this:
# config/initializers/console_greeting.rb
if defined?(Rails::Console)
puts 'Hello there! I\'m a custom greeting'
end
That doesn't work for me though :(. Even without the if defined?(Rails::Console) I still don't get output. Seems like initializers are not run when I enter a console, despite what others suggest.
I use ~/.irbrc for similar purposes (I require a gem in each console session). For example, my .irbrc
if (defined? Rails)
# Rails specific
end
# common for all irb sessions
You could use your project name to limit executing code to only one project's console:
if (defined? Rails) && (defined? YourProject)
# code goes here
end
The following will work in Rails 6:
Just pass a block to Rails.application.console, e.g
# config/initializers/custom_console_message.rb
if Rails.env.production?
Rails.application.console do
puts "Custom message here"
end
end
Now when starting the rails production console, the custom message will be printed. This code will not be executed when you start rails server.
Remove the if Rails.env.production? if you want this to run in all environments.

How do I turn off Rails SQL logging in test?

For some reason (probably an updated gem) Rails is logging all my SQL commands now. I run autotest and they are being spammed during tests also. How do I turn it off?
I tried add this to config/environments/test.rb but it didn't work. logger was already nil.
# ActiveRecord::Base.logger = nil
# ActiveRecord::Base.logger.level = 1
Rails 4.0.0
Ok I found it. This worked:
config.after_initialize do
ActiveRecord::Base.logger = nil
end
Another thing you can do is call this code at runtime, it doesn't need to be in a config file.
For example, if you put in your specific test case
# test/functionals/application_controller_test.rb for example
ActiveRecord::Base.logger = nil
It would work just as well, and this way you can toggle it at runtime. Useful if you only want to stifle a few lines of code or a block.
In case someone wants to actually knock out SQL statement logging (without changing logging level, and while keeping the logging from their AR models):
The line that writes to the log (in Rails 3.2.16, anyway) is the call to 'debug' in lib/active_record/log_subscriber.rb:50.
That debug method is defined by ActiveSupport::LogSubscriber.
So we can knock out the logging by overwriting it like so:
module ActiveSupport
class LogSubscriber
def debug(*args, &block)
end
end
end

how to change the rails logger to use standard out from rake tasks (rails2)

When I do
Rails.logger.debug "hello world" from within my rake tasks I want it to log to standard out.
How do I set the rails logger to Logger.new(STDOUT) from within my rake task?
I want my app to log to the file when coming through controllers etc, just want the rake tasks to go to std out because of the way my monitoring is setup.
I was thinking I could define another environment and use that config, but probably overkill, I want all the same environment vars in each env, just want to change the location of my log destination.
For now I have a log helper that uses puts, but I want to take advantage of the formatting of rails logs and the buffering.
I just did Rails.logger = Logger.new(STDOUT) and that also worked (rails3)
You can reset the default logger this way:
RAILS_DEFAULT_LOGGER = Logger.new(STDOUT)
You can also set the logger for specific parts of your application (ActiveRecord, ActionController...) like this:
ActiveRecord::Base.logger = Logger.new(STDOUT)
With rails 4 you will be using the gem rails_12factor. Place this into your Gemfile and voilĂ !
gem 'rails_12factor_'

"Printf" testing in Rails

I'm new to Rails and I'm aware it has things such as unit-testing built in. But I'm interested in doing some more simple tests that are equivalent to your "printf" in C. So I'm testing a login page I've written and want to trace the code to see what each line like my find methods are returning. I try outputting with "puts" but I don't get anything in the command-line.
I use puts statements all the time as well as the ruby debugger! It's great.
In rails you can do a couple things. I put "puts" in my code and when I run script/server at the command line, the output appears in my Terminal.app. I am running a Mac, but I am sure that there is a similar way to trace the activity of your app on your platform of choice.
The other option is to use the logger statement. you can call
logger.debug("My #{variable}")
and find these statements right in your log/development.log file.
Also, if you are running on a *nix system, you can use the "tail" command to trace the last statement written to your log one at a time.
tail -f log/development.log
This way you could write your statements and see them as they are happening. There are several levels of logging:
logger.warn
logger.info
logger.debug
logger.fatal
each environment (development, testing, production) will determine what "level" of logging will be called, so you may write log statements willy nilly with logger.debug while in development, but those log statements won't be written when you deploy based on the default log levels.
User something like this:
logger.info "method called with #{params.inspect}"
(you can put any variable inside the #{})
Once you're having fun with that, check out ./script/console and ruby-debug
Are you familiar with ruby-debug?
Install the ruby-debug gem.
Start your server with the -u option.
script/server -u
Put a debugger statement in your code where you want to stop.
You will have console access to your variables as well as the ability to step through your code.
Check the ruby-debug documentation for more details.
I've done this before - with Passenger, you don't have script/server's output, so I wrote this:
# extras/sexy_logging.rb
module SexyLogging
def log(text)
return true if RAILS_ENV == 'production'
string = "\e[0;32mLog:\e[m #{text}"
(100 - string.length).times do
string << ' '
end
string << "(#{caller.first})"
logger.debug string
end
end
ActiveRecord::Base.send :include, SexyLogging
ActionController::Base.send :include, SexyLogging
Then you can write
log variable
or
log 'Testing user'
tail -f log/development.log |grep Log:
and only see what you're logging, line by line and with colours.

Resources