Yelp API exception Handling Ruby on Rails - ruby-on-rails

I'm working on Yelp API through gem 'yelp' . Everything works fine but when we enter a location which is not provided by yelp it throws exception .
Yelp::Error::UnavailableForLocation
I have tried begin/end raise and rescue but not working . Can anyone tell , what's i'm doing wrong . here is what i tried
begin
client = Yelp::client
raise yelp_places_burst = client.search('lahore , pakistan')
end
rescue Exception => e
puts e.message
In addition , I want to send the error to js file (in response of ajax)

You are a little bit confused on how an exception is rescued. The way to rescue an exception in Ruby is
begin
# execution
rescue ErrorClass
# do something
end
Therefore your code should be
begin
client = Yelp::client
yelp_places_burst = client.search('lahore , pakistan')
rescue Yelp::Error::UnavailableForLocation => e
puts e.message
end
Also note I replaced Exception with the specific exception class. In fact, it's not recommended to rescue Exception as it will hide several other very exceptional events.

if you look at https://github.com/Yelp/yelp-ruby/blob/develop/lib/yelp/error.rb you can see that Yelp::Error::UnavailableForLocation is extended from Base which extends StandardError. So you need to catch StandardError, not Exception.
You get some additional explanations here: https://robots.thoughtbot.com/rescue-standarderror-not-exception, which suggests you can use rescue => e which will catch StandardError by default.

Related

Handle exception in ruby on rails

I called a method #txt.watch inside model from worker and Inside watch() there is an array of parameters(parameters = self.parameters). Each parameter have unique reference id.
I want to rescue each exception error for each parameter from inside worker.
class TextWorker
def perform(id)
#txt = WriteTxt.find(id)
begin
#txt.watch
total_complete_watch = if #txt.job_type == 'movie'
#txt.total_count
else
#txt.tracks.where(status:'complete').size
end
#txt.completed = total_completed_games
#txt.complete = (total_complete_games == #txt.total_count)
#txt.completed_at = Time.zone.now if #txt.complete
#txt.zipper if #txt.complete
#txt.save
FileUtils.rm_rf #txt.base_dir if #txt.complete
rescue StandardError => e
#How to find errors for each reference_id here
raise e
end
end
end
Is there any way to do. Thanks u very much.
I assume self.parameters are in your Model class instance. In that case, do as follows and you can reference them.
begin
#txt.watch
rescue StandardError
p #parameters # => self.parameters in the Model context
raise
end
Note:
As a rule of thumb, it is recommended to limit the scope of rescue as narrow as possible. Do not include statements which should not raise Exceptions in your main clause (such as, #txt.save and FileUtils.rm_rf in your case). Also, it is far better to limit the class of an exception; for example, rescue Encoding::CompatibilityError instead of EncodingError, or EncodingError instaed of StandardError, and so on. Or, an even better way is to define your own Exception class and raise it deliberately.

How to handle multiple exceptions in a Transaction with Ruby on Rails for importing a text file

My ruby environment is: Ruby 2.3.1 and Rails 5.0.0.1.
I'm trying to import a text file for import a lot of purchases items.
Example of purchase file:
data.txt
Customer\tDescription\tUnit Price\tQuantity\tAddress\tSupply company\n
Athos Matthew\tChocolate\t10\t5\tSome address.\tChocolate company\n
The columns are divided by a tab (\t) and it has an enter at the final (\n).
I have the purchase class where all attributes cannot be null. The attributes are:
custumer_name:string
product_id:integer # It has relationship with the Product Resource
product_quantity:integer
supply_company_id:integer # It has relationship with the SupplyCompany Resource
To import the file, I decided to create a PurchaseImporter class to do this job and keep the code cleaner.
My problem is that transaction part:
begin
ActiveRecord::Base.transaction do
purchase = Purchase.new
data = line.force_encoding('UTF-8').split(/\t/)
purchase.customer_name = data[0]
product = Product.find_or_create_by!(description: data[1], price: data[2])
purchase.product_quantity = data[3]
purchase.product = product
supply_company = SupplyCompany.find_or_create_by!(name: data[5], address: data[4])
purchase.supply_company = supply_company
purchase.save!
end
rescue Exception => e
#errors[:import][index] = e.message
end
My problem is that I want to catch all the raised errors from the Product, SupplyCompany and Purchase that could happen inside this transaction.
This is the order of the happenings without the unnecessary code to explain it.
product = Product.find_or_create_by!(description: data[1], price: data[2])
supply_company = SupplyCompany.find_or_create_by!(name: data[5], address: data[4])
purchase.save!
I need to print this errors information to this 3 classes in the screen, but with my code, I can only catch the first exception error, generated by the product. If some error happened in the SupplyCompany or in the Purchase, I lost these errors messages.
Are there other ways to import and log the errors message when importing files?
You can have more specific exception handling... do a rescue for each section you want to trap, at the end raise an error if any previous error was encountered (to get you out of the transaction block) and test in that final error that you're rescuing your own raise otherwise it's some other problem and you need to halt.
begin
ActiveRecord::Base.transaction do
error_encountered = false
purchase = Purchase.new
data = line.force_encoding('UTF-8').split(/\t/)
purchase.customer_name = data[0]
begin
product = Product.find_or_create_by!(description: data[1], price: data[2])
purchase.product_quantity = data[3]
purchase.product = product
rescue Exception => e
#errors[:import][index] = e.message
error_encountered = true
end
begin
supply_company = SupplyCompany.find_or_create_by!(name: data[5], address: data[4])
purchase.supply_company = supply_company
rescue Exception => e
#errors[:import][index] = e.message
error_encountered = true
end
begin
purchase.save!
rescue Exception => e
#errors[:import][index] = e.message
error_encountered = true
end
raise 'break out of transaction' if error_encountered
end
rescue Exception => e
raise unless e.message == 'break out of transaction'
end
Since you're rescuing Exception it's hard to know what error is actually emerging. When rescuing, you should try to use a more specific class when possible.
You also might not need to use rescue at all. The active methods you're using: find_or_create_by! and save! can be written without the exclamation point so that they don't raise errors.
In active record, if you try and save something with validation errors then the <record>.errors.full_messages array is populated. It won't necessarily raise an error if you don't use the exclamation point (although errors can be raised from all sorts of things regardless).
So, for example you can try and save a record and check for errors like this:
product = Product.find_or_initialize_by(description: data[1], price: data[2])
product.save
errors[:import][index] ||= []
errors[:import][index].concat product.errors_full_messages
Actually, in this case I think your approach makes some sense. You're saving a few records in sequence. If the first fails, then probably the others will fail - so is it worth even attempting to save those subsequent records? I'll let you decide.

rescue Twilio::REST::RequestError not working

I have been trying to implement the following in a Rails app but it seems not to do anything at all:
rescue Twilio::REST::RequestError => e
puts e.message
I notice it is only in the older docs for the twilio ruby gem, not in the newest ones. Is it no longer supported? Or do I need to change this code somehow?
I have tried to use the above when I get an invalid number or other error message from the Twilio API, but it doesn't work and just crashes the controller.
Here's an example of what I did:
rescue Twilio::REST::RequestError => e
flash[:error] = e.message
Well, it was my bad. I hadn't properly implemented the block. I did the following and it works now:
def create
begin
to_number = message_params
boot_twilio
sms = #client.messages.create(
from: ENV['TWILIO_NUMBER'],
to: to_number,
body: "..."
)
rescue Twilio::REST::RequestError => e
flash[:error] = "..."
else
flash[:notice] = "..."
end
redirect_to path
end
Twilio developer evangelist here.
If you are using the v5 release candidates then you will need to update the error class you are trying to catch.
The error raised in an HTTP request will be a Twilio::REST::RestException which inherits from the more generic Twilio::REST::TwilioException. See the error classes here: https://github.com/twilio/twilio-ruby/blob/next-gen/lib/twilio-ruby/framework/exception.rb
Note: I would not report the error message directly to the user. Those messages are intended for developers to better understand the issue.

Begin and Rescue block exception handling

I have little experience in rails exception handling. I have this snippet
def update
#game = Game.find(params[:id])
begin
params[:game][:tier] = eval(params[:game][:tier])
rescue
#game.errors.add(:tier, "Please make sure the correct format for tier, example [100, 1000, 10000]")
end
#.... more code
end
In case params[:game][:tier] = "[100,200]" everything is perfect.
In case of error case of ruby syntax like params[:game][:tier] = "[100,200] abc" it catch the error however the application just crush.
How can I handle exception with 'eval()' such that it won't crush the app? Why begin and rescue does not work in this case? Appreciate any help for ruby enlightenment thanks :)
What if params[:game][:tier] was "[100,200]; system('rm -rf /')"?
Since the incoming data is expected to be an array, I would not use eval but JSON.parse instead:
> JSON.parse("[100,200]")
=> [100, 200]
> JSON.parse("[100,200] abc")
JSON::ParserError: 746: unexpected token at 'abc'...
Then rescue from only a JSON::ParserError exception
rescue JSON::ParserError => e
This will also solve the rescue not catching the exception problem you're having.
duplicate of this
however you should rescue in this way
def update
#game = Game.find(params[:id])
begin
params[:game][:tier] = eval(params[:game][:tier])
rescue Exception => e
#game.errors.add(:tier, "Please make sure the correct format for tier, example [100, 1000, 10000]")
end
#.... more code
end
in order to make it work

rescuing from Mysql2::Error

I have a simple question. I have a join table which has an index that ensure that (col 1, col 2) is unique.
I am adding to that table using mysql2 gem and am trying to catch the Mysql2::Error if the attempt results in a duplicate key error. While I am getting the duplicate key error, my rescue body is not being executed.
begin
self.foo << bar
rescue Mysql2::Error
logger.debug("#{$!}")
end
I am receiving the following error upon executing self.foo << bar
Mysql2::Error: Duplicate entry '35455-6628' for key 'index_foos_bars_on_foo_id_and_bar_id': INSERT INTO foos_bars (foo_id, bar_id) VALUES (35455, 6628)
BUT my rescue statement is not being hit! The exception is not be successfully rescued from. What am I doing wrong? If I remove Mysql2::Error and rescue for everything, then it works. But that is bad practice - I just want to rescue from Mysql2::Error which in the event of a duplicate entry.
Thanks,
Mysql2::Error is wrapped in another exception class now. Change your code to:
begin
self.foo << bar
rescue Exception => e # only for debug purposes, don't rescue Exception in real code
logger.debug "#{e.class}"
end
...and you'll see the real exception class that you need to rescue.
Edit: It seems in this case it turned out to be ActiveRecord::RecordNotUnique

Resources