ruby-on-rails - 从 Rails 中的外部 API 捕获错误

标签 ruby-on-rails ruby heroku twilio

我正在构建一个简单的 Web 应用程序,它使用 Twilio 向手机发送 SMS 消息。我想确保用户在允许尝试发送消息之前输入了完整的 10 位电话号码。

当我用小于或大于 10 位数字测试它时,在 heroku 日志 中,我看到 Twilio::REST::RequestError(“收件人”号码 1234567890不是有效的电话号码。)

我已尝试使用 begin/rescue 包装器并告诉它呈现文本:“请使用有效号码重试。” 并尝试了各种 if 语句来避免错误。

我是 Ruby、Rails 和 Twilio 的新手,但我保证我已经阅读了我找到的所有指南。任何帮助是极大的赞赏。下面是我的 UserController 的完整代码:

    require 'twilio-ruby'
    class UsersController < ApplicationController

    def new
      @user = User.new
    end

    def create
      @user = User.new(params[:user])

      account_sid = '...'
      auth_token = '...'

      if @user.save
         render text: "Wasn't that fun? Hit the back button in your browser to give it another go!"
    begin
       client = Twilio::REST::Client.new account_sid, auth_token
           client.account.sms.messages.create(
           from: '+16035093259',
           to: @user.phone,
           body: @user.message
           )
        rescue Twilio::REST::RequestError
           render text: "Try again with a valid number."        
        end
     else
       render :new
     end
  end

end

最佳答案

我会将 SMS 发送逻辑提取到单独的模型/ Controller 中,并使用后台作业来处理提交。 UserController 应该只处理用户创建/修改。

脚手架:

$ rails g model sms_job user:references message:text phone submitted_at:datetime
$ rake db:migrate

型号:

class SmsJob < AR::Base
  attr_accessible :user_id, :message, :phone

  belongs_to :user
  validates_presence_of :message, :phone, :user_id
  validates :phone,
      length: { min: 10 },
      format: { with: /\+?\d+/ }

  scope :unsubmitted, where(submitted_at: nil)

  TWILIO = {
    from_no:      '...',
    account_sid:  '...',
    auth_token:   '...'
  }

  # find a way to call this method separately from user request
  def self.process!
    unsubmitted.find_each do |job|
      begin
        client = Twilio::REST::Client.new TWILIO[:account_sid], TWILIO[:auth_token]
        client.account.sms.messages.create(
          from: TWILIO[:from_no],
          to:   job.phone,
          body: job.message
        )
        job.submitted_at = Time.zone.now
        job.save
      rescue Twilio::REST::RequestError
        # maybe set update a tries counter
        # or delete job record
        # or just ignore this error
      end
    end
  end
end

然后 Controller 应该只提供将要发送 SMS 的信息:

# don't forget the 'resources :sms_jobs' in your routes.rb
class SmsJobsController < ApplicationController
  # index, update, destroy only for only admin?

  def new
    @sms_job = SmsJobs.new
  end

  def create
    @sms_job = current_user.sms_jobs.build params[:sms_job]
    if @sms_job.save
      redirect_to root_url, notice: "Your message is being send!"
    else
      render :new
    end
  end
end

后台处理,看看这些优秀的Railscasts :-) 如果您必须处理许多消息和/或 Twilio 的响应时间很长(尚未使用该服务),您可能需要解决一些并发问题。

关于ruby-on-rails - 从 Rails 中的外部 API 捕获错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12859355/

相关文章:

ruby-on-rails - Capistrano 中的 "role"到底是什么?

ruby - 解析哈希以打印为格式良好的字符串

ruby-on-rails - 在Rails中获取没有HTML的图像URL

ruby-on-rails - 如果我想在按下按钮时触发外部 API 调用 - Controller 还是模型?

ruby - 在循环内附加到 ruby​​ 数组时拒绝 nil 值

heroku - 当我的 CNAME 记录重定向到我的 heroku 应用程序时,它说没有这样的应用程序。

mysql - 使用 AWS RDS 在 Heroku App 上获取 Mysql2::Error(SSL 连接错误:ASN:错误的其他签名确认)

javascript - heroku Nodejs 应用程序在部署后崩溃

jquery - 如何在facebox中模拟close()

ruby-on-rails - 如何从 View 调用 Rails Controller 中的自定义方法