90

On a bash console, if I do this:

cd mydir
ls -l > mydir.txt

The > operator captures the standard input and redirects it to a file; so I get the listing of files in mydir.txt instead of in the standard output.

Is there any way to do something similar on the rails console?

I've got a ruby statement that generates lots of prints (~8k lines) and I'd like to be able to see it completely, but the console only "remembers" the last 1024 lines or so. So I thought about redirecting to a file - If anyone knows a better option, I'm all ears.

kikito
  • 51,734
  • 32
  • 149
  • 189

7 Answers7

158

A quick one-off solution:

irb:001> f = File.new('statements.xml', 'w')
irb:002> f << Account.find(1).statements.to_xml
irb:003> f.close

Create a JSON fixture:

irb:004> f = File.new(Rails.root + 'spec/fixtures/qbo/amy_cust.json', 'w')
irb:005> f << JSON.pretty_generate((q.get :customer, 1).as_json)
irb:006> f.close
user664833
  • 18,397
  • 19
  • 91
  • 140
Minimul
  • 4,060
  • 2
  • 21
  • 18
  • It gave me `NoMethodError: undefined method 'statements' for #` or `undefined method 'statements' for #` :( – Magne Jan 21 '15 at 14:29
  • 5
    Where is the file `statements.xml` get saved in the system. I cannot find the file. – SujitS May 28 '15 at 06:11
  • 2
    This is the better answer to show how to save specific record dump rather than telling someone to add yet another gem or plugin (SO tired of software recommendations when not needed) OR dumping everything in console to file. Voted up. – B. Shea Apr 17 '16 at 16:04
  • @SujitS - The file gets saved into the directory from which you executed `rails console` (most likely your app's root directory). (At least this was the case for me.) – user664833 Mar 07 '20 at 00:00
  • 1
    Variation on the solution is: `f = File.new('/tmp/statements.xml', 'w')` then `f.puts Account.find(1)` (or whatever is the query). Finally, closing the file: `f.close`. This worked properly when doing a query in gitlab-rails console. – frank_108 Jan 26 '22 at 09:58
116

You can use override $stdout to redirect the console output:

$stdout = File.new('console.out', 'w')

You may also need to call this once:

$stdout.sync = true

To restore:

$stdout = STDOUT
user664833
  • 18,397
  • 19
  • 91
  • 140
Veger
  • 37,240
  • 11
  • 105
  • 116
  • 2
    It didn't work for me until I added `$stdout.sync=true`. Edited. – Peter DeWeese Feb 10 '12 at 16:00
  • 2
    `$stdout.reopen("my.log", "w")` seems to be a more elegant solution, seen at: http://stackoverflow.com/a/2480439/21217 – dain Dec 13 '12 at 14:05
  • `$stdout = File.new('console.out', 'w')` taking really long time. I am using windows. Not sure if that is the reason! – dhrubo_moy Aug 26 '16 at 15:42
  • You may need to close the file to capture all the data. I use `std=$stdout ; f=File.new("/tmp/console.out", 'w')` followed by `$stdout=f ; pp Foo.where(id: [100..1234]); f.close; $stdout=std`. Otherwise final pieces of data do not appear. – Moshe Yudkowsky Jan 03 '22 at 19:33
20

Apart from Veger's answer, there is one of more way to do it which also provides many other additional options.

Just open your rails project directory and enter the command:

rails c | tee output.txt

tee command also has many other options which you can check out by:

man tee
  • 1
    this didn't work for me.. I tried running `rails server | tee file.txt` and there's no output to STDOUT or the file. I just think the server fails to start in this case. – kapad Aug 02 '18 at 11:49
  • server prints to stderr I think, there should be options in the tee command to redirect that as well. – Kevin Feb 20 '19 at 02:56
  • 1
    Yes, do something like `rails console 2>&1 | tee file.txt`. Not an option in tee, just simple redirection of stderr to stdout so both end up in your file.txt. – labyrinth Mar 06 '19 at 22:06
  • The file ended up full of console colour codes. Use `pp` to get output without colour codes. – Tim Abell Mar 03 '20 at 16:29
4

If you write the following code in your environment file, it should work.

if "irb" == $0
  config.logger = Logger.new(Rails.root.join('path_to_log_file.txt'))
end

You can also rotate the log file using

config.logger = Logger.new(Rails.root.join('path_to_log_file.txt'), number_of_files, file_roation_size_threshold)

For logging only active record related operations, you can do

ActiveRecord::Base.logger = Logger.new(Rails.root.join('path_to_log_file.txt'))

This also lets you have different logger config/file for different environments.

Chirantan
  • 15,304
  • 8
  • 49
  • 75
  • This is helpful, but the other answer does what I wanted in a simpler way. Thanks for taking the time to answer anyway. – kikito Mar 17 '10 at 13:12
3

Using Hirb, you can choose to log only the Hirb output to a text file. That makes you able to still see the commands you type in into the console window, and just the model output will go to the file.

From the Hirb readme:

Although views by default are printed to STDOUT, they can be easily modified to write anywhere:

# Setup views to write to file 'console.log'.
>> Hirb::View.render_method = lambda {|output| File.open("console.log", 'w') {|f| f.write(output) } }

# Doesn't write to file because Symbol doesn't have a view and thus defaults to irb's echo mode.
>> :blah
=> :blah

# Go back to printing Hirb views to STDOUT.
>> Hirb::View.reset_render_method
Magne
  • 16,401
  • 10
  • 68
  • 88
2

Use hirb. It automatically pages any output in irb that is longer than a screenful. Put this in a console session to see this work:

>> require 'rubygems'
>> require 'hirb'
>> Hirb.enable

For more on how this works, read this post.

cldwalker
  • 6,155
  • 2
  • 27
  • 19
  • Thanks for answering, but I wasn't looking for pagination; I wanted to see everything on a single page. – kikito Mar 17 '10 at 17:14
2

Try using script utility if you are on Unix-based OS.

script -c "rails runner -e development lib/scripts/my_script.rb" report.txt

That helped me capture a Rails runner script's very-very long output easily to a file.

I tried using redirecting to a file but it got written only at the end of script.

That didn't helped me because I had few interactive commands in my script.

Then I used just script and then ran the rails runner in script session but it didn't wrote everything. Then I found this script -c "runner command here" output_file and it saved all the output as was desired. This was on Ubuntu 14.04 LTS

References:

https://askubuntu.com/questions/290322/how-to-get-and-copy-a-too-long-output-completely-in-terminal#comment1668695_715798

Writing Ruby Console Output to Text File

Jignesh Gohel
  • 6,236
  • 6
  • 53
  • 89