Question

I'm connecting our Rails (3.2) application to an external web service (campaign monitor) which requires a few calls to their system to set a client up.

I've put each action into separate rescue blocks and wrapped in a transaction but things aren't looking so great. I need it to escape after each error and display the correct message. Currently it just escapes.

I have a list of possible errors per action - how is it possible to read these and format as a flash message?

For example, the following error:

 CreateSend::BadRequest: The CreateSend API responded with the following error - 172: You can create a maximum of five (5) clients per thirty (30) minutes

I currently have this in my controller:

  def create_send_setup
     ...
      begin

       client = CreateSend::Client.create(@user.company_name, @user.username, @user.email, "(GMT) Dublin, Edinburgh, Lisbon, London", @user.country)

       rescue
        flash[:notice] = "Uh oh, there's been a problem. Please try again. Client"
       end

       begin
         @client = CreateSend::Client.new(@user.createsend_client_api)
         @client.set_access(@user.username, @password, @user.createsend_access_level)
         @client.set_monthly_billing(@user.createsend_currency, true, @user.createsend_markup)

       rescue
          flash[:notice] = "Uh oh, there's been a problem. Please try again. Access"
       end

          flash[:notice] = "Great, now you just need to choose a plan"
          redirect_to edit_user_registration_path    

 end

In a previous integration, I've used something like

case bla.code.to_s
     when /2../
     when '403'
       raise "Could not update subscriber: new-customer-id is already in use."
     ...
 end

What's the best way to extract the error code from the response and display as a flash message?

Was it helpful?

Solution

As Dave said, if the exception is all you've got, you can only capture the exception and do something with that exception as a string.

For example:

begin
  ...
rescue Exception => ex
  # here "ex.message" contains your string, you can do anything you want with it
  # or parse as is:
  flash[:notice] = ex.message
end

redirect_to edit_user_registration_path

UPDATE

If you combine my proposed solution with those put forward by Dave, you'd get something like this, with which you can use your own error strings:

begin
  ...
rescue Exception => ex
  code = ex.message.match(/.*?- (\d+): (.*)/)[1]

  case code
  when '172'
    flash[:notice] = 'Please wait 30 minutes to create more clients'
  end
end

redirect_to edit_user_registration_path

OTHER TIPS

All you can do is work with the exception given-if there's no data payload you can try to parse the message strings, use it as-is, map all or part of it to your own messages, etc.

For example, if the example message you show is normalized, a regex could be used to grab the numeric and message portions:

[1] pry(main)> s = "CreateSend::BadRequest: The CreateSend API responded with the following error - 172: You can create a maximum of five (5) clients per thirty (30) minutes"
=> "CreateSend::BadRequest: The CreateSend API responded with the following error - 172: You can create a maximum of five (5) clients per thirty (30) minutes"
[2] pry(main)> md = s.match /.*?- (\d+): (.*)/
=> #<MatchData
 "CreateSend::BadRequest: The CreateSend API responded with the following error - 172: You can create a maximum of five (5) clients per thirty (30) minutes"
 1:"172"
 2:"You can create a maximum of five (5) clients per thirty (30) minutes">
[3] pry(main)> md[1]
=> "172"
[4] pry(main)> md[2]
=> "You can create a maximum of five (5) clients per thirty (30) minutes"

The best way of handling errors in this specific situation is by specifically handing the errors which the library defines itself. createsend-ruby defines CreateSendError, BadRequest, and Unauthorized. You do not need to parse any strings.

Here is an example take from the README, of handling errors:

require 'createsend'

CreateSend.api_key 'your_api_key'

begin
  cl = CreateSend::Client.new "4a397ccaaa55eb4e6aa1221e1e2d7122"
  id = CreateSend::Campaign.create cl.client_id, "", "", "", "", "", "", "", [], []
  puts "New campaign ID: #{id}"
  rescue CreateSend::BadRequest => br
    puts "Bad request error: #{br}"
    puts "Error Code:    #{br.data.Code}"
    puts "Error Message: #{br.data.Message}"
  rescue Exception => e
    puts "Error: #{e}"
end

The data field always contains a Code and Message, which correspond to the status codes API documentation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top