使用Twilio + rails安排SMS以供日后使用

时间:2013-12-08 21:34:26

标签: ruby-on-rails twilio

我想使用Twilio + Rails现在或在特定时间发送短信,但我不确定最佳做法方法。我认为cron不适合这个。

我有一个简单的观点 -

<div>
  <%= form_for @text_message, url: {action: "send_message"}, 
  html: {role: "form", class: "form-horizontal" } do |f|%>
    <%= f.text_field :from  %>
    <%= f.text_field :to %>
    <%= f.text_area :body, class: 'text-input' %>
    <div class="schedule-outer">
      <a id="schedule-link">
        <span>Schedule text for later?</span>
       </a>
    </div>   
    <div >
      <%= f.datetime_select :scheduled_date, ampm: true, minute_step: 15, value: nil %> <br>
    </div>
    <%= f.submit "Send Text Message"%>
  <% end %>
</div>

和相应的控制器 -

class TextMessagesController < ApplicationController

  def new
    @text_message = TextMessage.new
  end

  def send_message
    number_to_send_to = params[:text_message][:to]
    number_sent_from = params[:text_message][:from]
    the_payload = params[:text_message][:body]

    @twilio_client = Twilio::REST::Client.new(ENV['TWILIO_SID'], ENV['TWILIO_AUTH'])


    @twilio_client.account.sms.messages.create(
     from: "#{number_sent_from}",
     to: "#{number_to_send_to}",
     body: "#{the_payload}"
    )

    flash[:notice] = "Your text has been sent!"
    redirect_to action: 'new'
  end
end

的routes.rb

get 'text_messages/new', to: "text_messages#new"
post '/send_message' => "text_messages#send_message" 

textmessage.rb

class TextMessage < ActiveRecord::Base
  attr_accessible :body, :from, :to, :scheduled_date

end

现在,如果您填写表单,它会将短信发送到您输入的任何参数。我在设计方面遇到了下一步的麻烦。

以下是我的想法

  • 控制器中的before_filter,用于检查:scheduled_date是否为零。
  • 如果不是,则立即发送,如果不将其发送给调度程序(?)

问题

  • 这实际上似乎没有创建文本消息对象,它只是发送短信
  • 我不确定下一步可能是多么优雅。

目标

  • 允许某人立即发送短信或在指定时间以
  • 的形式发送短信

问题

  • 实现这一目标的下一步是什么?

** **更新

这是我根据调度程序建议更新的控制器/表单代码,我希望这是我的解决方案。

class TextMessagesController < ApplicationController  
  def new
    @text_message = TextMessage.new
  end

  def send_message
    number_to_send_to = params[:text_message][:to]
    number_sent_from = params[:text_message][:from]
    the_payload = params[:text_message][:body]
    @text_message = TextMessage.create(params[:text_message])
    @twilio_client = Twilio::REST::Client.new(ENV['TWILIO_SID'], ENV['TWILIO_AUTH'])

    if @text_message.scheduled_date == nil
      @twilio_client.account.sms.messages.create(
       from: "#{number_sent_from}",
       to: "#{number_to_send_to}",
       body: "#{the_payload}"
      )
    else
      # add it to a scheduler
    end
    flash[:notice] = "Your text has been sent!"
    redirect_to action: 'new'
  end
end

表格

  <%= f.datetime_select :scheduled_date, ampm: true, minute_step: 15, include_blank: true %> 

2 个答案:

答案 0 :(得分:1)

我会尽量避免为现在或将来发送的消息设置不同的逻辑。如果你不需要响应的任何部分(目前你没有对它做任何事情),那么最简单的方法是在任何情况下将它移动到后台。最大的好处是服务的响应时间和可用性对您网站的响应时间没有影响。

在后台排队作业的一个好工具是resque(https://github.com/resque/resque),它可以使用resque-scheduler(https://github.com/resque/resque-scheduler)进行扩展,以允许在将来的某个时间点完成作业(而不是只需Resque.enqueue,然后使用Resque.enqueue_in和/或Resque.enqueue_at将任务移动到队列中。

答案 1 :(得分:0)

这是我目前正在实施的实现,我相信它可以改进。

我添加了sidekiqredis用于后台作业处理。这是我的twilio工作者

class TwilioWorker
  include Sidekiq::Worker
  sidekiq_options retry: false

  def perform(text_message_id)
    text_message = TextMessage.find(text_message_id)
    number_to_send_to = text_message.to
    number_sent_from =  text_message.from
    the_payload = text_message.body
    @twilio_client = Twilio::REST::Client.new(ENV['TWILIO_SID'], ENV['TWILIO_AUTH'])

    @twilio_client.account.sms.messages.create(
     from: "#{number_sent_from}",
     to: "#{number_to_send_to}",
     body: "#{the_payload}"
    )
  end
end

这是我更新的text_messages_controller.rb

class TextMessagesController < ApplicationController  
  def new
    @text_message = TextMessage.new
  end

  def send_message
    @text_message = TextMessage.new(params[:text_message])

    if @text_message.save
      if @text_message.scheduled_date == nil
        TwilioWorker.perform_async(@text_message.id)
      elsif @text_message.scheduled_date != nil 
        time = ((@text_message.scheduled_date - @text_message.created_at) / 3600).round
        TwilioWorker.perform_at(time.hours, @text_message.id)

      else
        flash[:notice] = "something went wrong"
      end

    else
      redirect_to action: 'new'
    end
  end
end

rbates sidekiq railscast非常适合设置它。