Trying to write a temporary file on Heroku (Cedar), which seems like it should be possible, according to the documentation. Yet this code snippet fails:
get '/test' do
myfile = File.new("./tmp/testemp.txt", "w+")
myfile.puts("Abracadabra")
myfile.close
"End of test"
end
Any suggestions what I might be doing wrong? The "End of test" output shows up on the served web page, so this path is definitely getting followed.
Thanks!
The code you have is writing to the file /tmp/testemp.txt, but you are then returning "End of test" at the end of your method, which is why that is returned to the web browser.
That last thing you return will get rendered to the web browser by default.
Related
I've got a Thor based ruby CLI project to which I'm trying to add unit testing. It started as a pet project and is now rather large and important internally. Anyway, I have never really started unit testing, only grafted onto existing examples, and so I'm very much a noob when it comes to rspec.
I'm starting with a rather basic example, making sure that if I give it a file that doesn't exist, that it replies with an explanatory error and exits.
Here's the ways I have tried to compound them:
context 'with incorrect filename' do
it 'should fail cleanly' do
expect do
subject.format('bad_file_name')
end.to output(' ERROR Unable to load file bad_file_name, exiting...').to_stdout.and raise_error(SystemExit)
end
end
which works but doesn't capture the stdout properly output here.. also tried:
context 'with incorrect filename' do
it 'should fail cleanly' do
expect do
expect do
subject.format('fixtures/invalid.yaml')
end.to output(' ERROR Unable to load file bad_file_name, exiting...').to_stdout
end.to raise_error(SystemExit)
end
end
Which looks like it works, except (as this example shows) it's not actually testing the output because that output wouldn't match.
So what's the right way to check both an error that was raised and the output to stdout at the same time?
this works for me
expect { whatever }.to output('stderr message').to_stderr
.and output(Regexp.new('stdout message')).to_stdout
.and raise_error('Error message')
This is the contents of my .rspec_parallel file. I am using parallel_tests gem to run tests in multiple browser instances. To my knowledge, the gem uses the same formatter options available in RSpec.
--format html --out results<%= ENV['TEST_ENV_NUMBER'] %>.html
This works fantastic and I'm able to get the HTML output I normally see from RSpec. However, all of the 'puts' messages and basic standard output is logged to my console window, and not to the HTML files.
How can I get this output into each individual HTML file that I have set up?
puts will output to $stdout where as output is actually an instance variable of the RSpec::Core::Formatters::BaseFormatter class. output is defaulted to $stdout but when you pass in a string it determines that it should create a new StringIO and then output this to the given file name. Thus puts will not append to the #output variable.
You could do something ugly like create a runner file like
File.open('some_file_name.html','w+') do |file|
file << `rspec spec --format html`
end
Then this file will have the output from $stdoutbut your puts code will not be html formatted in this case. Other than that you could try building your own Custom Formatter but it will probably take quite a bit of source searching to make sure you can capture everything appropriately.
That being said it does seem the reporter was exposed for adding custom messages but I am uncertain of how to use this appropriately See Pull Request 1866
Seems it would be something like
it "has a name" do |ex|
ex.reporter.message("Custom Message Here")
#actual test
end
but the html formatter seems to ignore this. I can see the output in $stdout but not in the html file itself.
Best of luck.
I am using sinatra,ruby and MongoDB to export a CSV file from the MongoDB. I am able to create the CSV file and export it.
I delete the file after exporting it.
But it gets deleted only after I exit sinatra.
Can anybody explain why is this?
Suppose a file abc****.csv is created.
I am deleting this file using
file_path = '/home/Test_app';
file = Tempfile.new([##uname,'.csv'],file_path);
file_name = file.path();
puts file_name # gives /home/Test_app/xyz****.csv
send_file(file_name, :disposition => 'attachment', :filename =>File.basename(file_name));
File.delete(file_name);
File.unlink(file_name);
But it gets deleted only after I exit sinatra server. Can anyone explain please?
Your never call file.close, meaning the file will be kept open and therefore not deleted until your application exits.
Try following the suggestion given in the Tempfile documentation:
file = Tempfile.new('foo')
begin
...do something with file...
ensure
file.close
file.unlink # deletes the temp file
end
This will make sure the file is properly closed and deleted even in the event of exceptions being raised in the code between begin and ensure.
Perhaps this is a large file; since the HTTP connection does not close until the streaming is complete, the code after send_file is not getting executed. That might be a valid reason. Have you checked if the entire file is being downloaded to the client? If that is not the case, try it out with a smaller file. I'm assuming you've implemented (but haven't written it here) the code for the data getting written into the file_name from MongoDB.
I want to be able to read a currently open file. The test.rb is sending its output to test.log which I want to be able to read and ultimately send via email.
I am running this using cron:
*/5 * * * /tmp/test.rb > /tmp/log/test.log 2>&1
I have something like this in test.rb:
#!/usr/bin/ruby
def read_file(file_name)
file = File.open(file_name, "r")
data = file.read
file.close
return data
end
puts "Start"
puts read_file("/tmp/log/test.log")
puts "End"
When I run this code, it only gives me this output:
Start
End
I would expect the output to be something like this:
Start
Start (from the reading of the test.log since it should have the word start already)
End
Ok, you're trying to do several things at once, and I suspect you didn't systematically test before moving from one step to the next.
First we're going to clean up your code:
def read_file(file_name)
file = File.open(file_name, "r")
data = file.read
file.close
return data
end
puts "Start"
puts read_file("/tmp/log/test.log")
puts "End"
can be replaced with:
puts "Start"
puts File.read("./test.log")
puts "End"
It's plain and simple; There's no need for a method or anything complicated... yet.
Note that for ease of testing I'm working with a file in the current directory. To put some content in it I'll simply do:
echo "foo" > ./test.log
Running the test code gives me...
Greg:Desktop greg$ ruby test.rb
Start
foo
End
so I know the code is reading and printing correctly.
Now we can test what would go into the crontab, before we deal with its madness:
Greg:Desktop greg$ ruby test.rb > ./test.log
Greg:Desktop greg$
Hmm. No output. Something is broken with that. We knew there was content in the file previously, so what happened?
Greg:Desktop greg$ cat ./test.log
Start
End
Cat'ing the file shows it has the "Start" and "End" output of the code, but the part that should have been read and output is now missing.
What happening is that the shell truncated "test.log" just before it passed control to Ruby, which then opened and executed the code, which opened the now empty file to print it. In other words, you're asking the shell to truncate (empty) it just before you read it.
The fix is to read from a different file than you're going to write to, if you're trying to do something with the contents of it. If you're not trying to do something with its contents then there's no point in reading it with Ruby just to write it to a different file: We have cp and/or mv to do those things for us witout Ruby being involved. So, this makes more sense if we're going to do something with the contents:
ruby test.rb > ./test.log.out
I'll reset the file contents using echo "foo" > ./test.log, and cat'ing it showed 'foo', so I'm ready to try the redirection test again:
Greg:Desktop greg$ ruby test.rb > ./test.log.out
Greg:Desktop greg$ cat test.log.out
Start
foo
End
That time it worked. Trying it again has the same result, so I won't show the results here.
If you're going to email the file you could add that code at this point. Replacing the puts in the puts File.read('./test.log') line with an assignment to a variable will store the file's content:
contents = File.read('./test.log')
Then you can use contents as the body of a email. (And, rather than use Ruby for all of this I'd probably do it using mail or mailx or pipe it directly to sendmail, using the command-line and shell, but that's your call.)
At this point things are in a good position to add the command to crontab, using the same command as used on the command-line. Because it's running in cron, and errors can happen that we'd want to know about, we'd add the 2>&1 redirect to capture STDERR also, just as you did before. Just remember that you can NOT write to the same file you're going to read from or you'll have an empty file to read.
That's enough to get your app working.
class FileLineRead
File.open("file_line_read.txt") do |file|
file.each do |line|
phone_number = line.gsub(/\n/,'')
user = User.find_by_phone_number(line)
user.destroy unless user.nil?
end
end
end
open file
read line
DB Select
DB Update
In the cron job you have already opened and cleared test.log (via redirection) before you have read it in the Ruby script.
Why not do both the read and write in Ruby?
It may be a permissions issue or the file may not exist.
f = File.open("test","r")
puts f.read()
f.close()
The above will read the file test. If the file exists in the current directory
The problem is, as I can see, already solved by Slomojo. I'll only add:
to read and print a text file in Ruby, just:
puts File.read("/tmp/log/test.log")
I am using rspec for my test in a ruby project, and I want to spec that my program should not output anything when the -q option is used. I tried:
Kernel.should_not_receive :puts
That did not result in a failed test when there was output to the console.
How do I verify the absents of text output?
puts uses $stdout internally. Due to the way it works, the easiest way to check is to simply use: $stdout.should_not_receive(:write)
Which checks nothing is written to stdout as expected.
Kernel.puts (as above) would only result in a failed test when it
is explictely called as such (e.g. Kernel.puts "Some text"), where
as most cases it's call in the scope of the current object.
The accepted answer above is incorrect. It "works" because it doesn't receive a :write message but it might have received a :puts message.
The correct line should read:
$stdout.should_not_receive(:puts)
Also you need to make sure you put the line before the code that will write to STDIO. For instance:
it "should print a copyright message" do
$stdout.should_receive(:puts).with(/copyright/i)
app = ApplicationController.new(%w[project_name])
end
it "should not print an error message" do
$stdout.should_not_receive(:puts).with(/error/i)
app = ApplicationController.new(%w[project_name])
end
That's an actual working RSpec from a project