I have a rails code snippet that does a rake file from a model.
Rake.application.rake_require '../../lib/tasks/master_load'
fork do
results = capture_stdout {Rake.application['db:seed:excel:to_yaml'].invoke}
end
capture_stdout is for printing out the logs
def self.capture_stdout
s = StringIO.new
oldstdout = $stdout
$stdout = s
yield
s.string
Rails.logger.info "#{s.string}"
ensure
$stdout = oldstdout
end
it works, but when the rake encounters error and fails.
it fails silently.
is there a way to know if error has occured and perhaps get the error log?
Use rescue to catch and handle error
def self.capture_stdout
s = StringIO.new
oldstdout = $stdout
$stdout = s
yield
s.string
Rails.logger.info "#{s.string}"
rescue Exception => e
# handle e - exception object
ensure
$stdout = oldstdout
end
Ensure in this case silently makes action after exception handling
Related
I have a rake task that loops through rows in CSV file, and inside that loop, there's a begin/rescue block to catch any possible raised exception. But when I run it, it keeps on saying 'rake aborted!' and it is not entering the rescue block
CSV.foreach(path, :headers => true) do |row|
id = row.to_hash['id'].to_i
if id.present?
begin
# call to mymethod
rescue => ex
puts "#{ex} error executing task"
end
end
end
...
def mymethod(...)
...
begin
response = RestClient.post(...)
rescue => ex
raise Exception.new('...')
end
end
Expected: It should finish looping all the rows of the CSV
Actual result: It stops after reaching the 'raise' exception saying that:
rake aborted!
Exception: error message here
...
Caused by:
RestClient::InternalServerError: 500 Internal Server Error
You can use next to skip the faulty step of loop:
CSV.foreach(path, :headers => true) do |row|
id = row.to_hash['id'].to_i
if id.present?
begin
method_which_doing_the_staff
rescue SomethingException
next
end
end
end
And raise the exception inside your method:
def method_which_doing_the_staff
stuff
...
raise SomethingException.new('hasd')
end
I solved this issue by just commenting out the line that is raising an exception because it seems like it the quickest fix for now.
# raise Exception.new('...')
I'm still open to other suggestions if there are any better ways to do it.
I am running a cucumber script by executing Cucumber::Cli::Main.new(args).execute!
But Ruby moves to the next line and starts reading from the file. But the file is empty as cucumber takes time to process the Cucumber::Cli::Main.new(args).execute!
How to make execution stop until Cucumber has finished executing the script and finished populating the file with HTML. Thank you
Here is the Link for Source Code: https://github.com/cucumber/cucumber-ruby/blob/master/lib/cucumber/cli/main.rb
require 'cucumber'
require 'tempfile'
require 'securerandom'
filename = "#{SecureRandom.urlsafe_base64}"
file = Tempfile.new(filename)
filepath = "#{file.path}"
features = "features/login.feature"
args = features.split.concat %w(--format html --out)
args << "#{filepath}.html"
begin
Cucumber::Cli::Main.new(args).execute!
#value = file.read
ensure
file.close
file.unlink
end
EDIT:
When Cucumber::Cli::Main.new(args).execute! finishes executing it throws a SystemExit Exception with a status 0.
Exit code is 0 when execution went fine
Cucumber always throws an SystemExit exception when it finishes.
Here is the Link for Source Code for Cucumber: https://github.com/cucumber/cucumber-ruby/blob/master/lib/cucumber/cli/main.rb
How to handle the SystemExit Exception in Rails, so that it doesn't skip the next lines of execution.
def run
filename = "#{SecureRandom.urlsafe_base64}"
file = Tempfile.new(filename)
filepath = "#{file.path}"
features = "features/login.feature"
args = features.split.concat %w(-f html -o)
args << "#{filepath}.html"
Cucumber::Cli::Main.new(args).execute! # throws SystemExit Exception Status 0
#output = file.read
file.close
file.unlink
# More Code Below
# # # # # # # # #
end
Two choices I see here, one is to catch the error and then read the file, such as:
begin
Cucumber::Cli::Main.new(args).execute!
rescue SystemExit => e
if e.status == 0
#value = file.read
else
raise e
end
ensure
file.close
file.unlink
end
The other option is to make a runner class that inherits from the CLI and override exit_ok.
class Runner < Cucumber::Cli::Main
def exit_ok
#NOOP
end
end
begin
Runner.new(args).execute!
#value = file.read
ensure
file.close
file.unlink
end
I use the capybara-webkit gem to scrape data from certain pages in my Rails application. I've noticed, what seems to be "random" / "sporadic", that the application will crash with the following error:
Capybara::Webkit::ConnectionError: /home/daveomcd/.rvm/gems/ruby-2.3.1/gems/capybara-webkit-1.11.1/bin/webkit_server failed to start.
from /home/daveomcd/.rvm/gems/ruby-2.3.1/gems/capybara-webkit-1.11.1/lib/capybara/webkit/server.rb:56:in `parse_port'
from /home/daveomcd/.rvm/gems/ruby-2.3.1/gems/capybara-webkit-1.11.1/lib/capybara/webkit/server.rb:42:in `discover_port'
from /home/daveomcd/.rvm/gems/ruby-2.3.1/gems/capybara-webkit-1.11.1/lib/capybara/webkit/server.rb:26:in `start'
from /home/daveomcd/.rvm/gems/ruby-2.3.1/gems/capybara-webkit-1.11.1/lib/capybara/webkit/connection.rb:67:in `start_server'
from /home/daveomcd/.rvm/gems/ruby-2.3.1/gems/capybara-webkit-1.11.1/lib/capybara/webkit/connection.rb:17:in `initialize'
from /home/daveomcd/.rvm/gems/ruby-2.3.1/gems/capybara-webkit-1.11.1/lib/capybara/webkit/driver.rb:16:in `new'
from /home/daveomcd/.rvm/gems/ruby-2.3.1/gems/capybara-webkit-1.11.1/lib/capybara/webkit/driver.rb:16:in `initialize'
from /home/daveomcd/.rvm/gems/ruby-2.3.1/gems/capybara-webkit-1.11.1/lib/capybara/webkit.rb:15:in `new'
from /home/daveomcd/.rvm/gems/ruby-2.3.1/gems/capybara-webkit-1.11.1/lib/capybara/webkit.rb:15:in `block in <top (required)>'
from /home/daveomcd/.rvm/gems/ruby-2.3.1/gems/capybara-2.7.1/lib/capybara/session.rb:85:in `driver'
from /home/daveomcd/.rvm/gems/ruby-2.3.1/gems/capybara-2.7.1/lib/capybara/session.rb:233:in `visit'
It happens even after it's already connected and accessed a website multiple times before. Here's a code snippet of what I'm using currently...
if site.url.present?
begin
# Visit the URL
session = Capybara::Session.new(:webkit)
session.visit(site.url) # here is where the error occurs...
document = Nokogiri::HTML.parse(session.body)
# Load configuration options for Development Group
roster_table_selector = site.development_group.table_selector
header_row_selector = site.development_group.table_header_selector
row_selector = site.development_group.table_row_selector
row_offset = site.development_group.table_row_selector_offset
header_format_type = site.config_header_format_type
# Get the Table and Header Row for processing
roster_table = document.css(roster_table_selector)
header_row = roster_table.css(header_row_selector)
header_hash = retrieve_headers(header_row, header_format_type)
my_object = process_rows(roster_table, header_hash, site, row_selector, row_offset)
rescue ::Capybara::Webkit::ConnectionError => e
raise e
rescue OpenURI::HTTPError => e
if e.message == '404 Not Found'
raise "404 Page not found..."
else
raise e
end
end
end
I've even thought perhaps I don't find out why it's happening necessarily - but just recover when it does. So I was going to do a "retry" in the rescue block for the error but it appears the server is just down - so I get the same result when retrying. Perhaps someone knows of a way I can check if the server is down and restart it then perform a retry? Thanks for the help!
So after further investigating it appears that I was generating a new Capybara::Session for each iteration of my loop. I moved it outside of the loop and also added Capybara.reset_sessions! at the end of my loop. Not sure if that helps with anything -- but the issue seems to have been resolved. I'll monitor it for the next hour or so. Below is an example of my ActiveJob code now...
class ScrapeJob < ActiveJob::Base
queue_as :default
include Capybara::DSL
def perform(*args)
session = Capybara::Session.new(:webkit)
Site.where(config_enabled: 1).order(:code).each do |site|
process_roster(site, session)
Capybara.reset_sessions!
end
end
def process_roster(site, session)
if site.roster_url.present?
begin
# Visit the Roster URL
session.visit(site.roster_url)
document = Nokogiri::HTML.parse(session.body)
# processing code...
# pass the session that was created as the final parameter..
my_object = process_rows( ..., session)
rescue ::Capybara::Webkit::ConnectionError => e
raise e
rescue OpenURI::HTTPError => e
if e.message == '404 Not Found'
raise "404 Page not found..."
else
raise e
end
end
end
end
end
I am trying to rescue an aws s3 exception.
class FileManager
def fetchFile
begin
s3.get_object(bucket:'myBucket', key: file_name)
rescue Aws::S3::Errors => e
debugger
end
end
end
Then when I call the method from console
FileManager.fetch_file('Non existing file')
I am not getting the debugger instead there is an error message in the console
Aws::S3::Errors::NoSuchKey: The specified key does not exist.
I believe this has what your looking for (assuming you are using this gem):
https://github.com/marcel/aws-s3#when-things-go-wrong
You can rescue all S3 errors using ServiceError
begin
# ...
rescue Aws::S3::Errors::ServiceError => e
# ...
end
Is there any way to have RSpec continue processing specifications after an exception is raised?
This is what my spec task looks like:
SPEC_PATTERN = "spec/**/*_spec.rb"
Spec::Rake::SpecTask.new() do |t|
t.spec_files = FileList[SPEC_PATTERN]
t.verbose = true
t.spec_opts = ["--format", "html:spec/spec_report.html"]
t.fail_on_error = false
t.rcov = true
t.rcov_dir = 'coverage'
t.rcov_opts = ['--exclude', 'spec']
end
what about using "should raise_exception"?
http://rspec.rubyforge.org/rspec/1.3.0/classes/Spec/Matchers.html#M000183
rspec does capture exceptions and report them as failures, in much the same way test/unit does. If you're seeing the task exiting it's because the exception is either outside of the code that rspec is handling, or it might be a syntax error.
HTH,
David
it "should not raise an exception" do
expect {
raise Exception unless true
}.should_not raise_exception
end