How can I call a method from the model, inside of the Rufus Scheduler(in the controller), so that the time is scheduled based on user input? Rails 4

StackOverflow https://stackoverflow.com/questions/21820356

Question

So here is the scenario. I am using Rails 4 and the Rufus Scheduler to make an app that sends SMS at a specific time in the future. So far, I got the SMS to work if I want to send an SMS by the click of a button. And I am also able to send them on a timer I set in my own code, such as the one below, which allows my message to be sent in the future. Basically, I set the timer, and when it goes off, it calls my method to send an SMS message.

This is all great but the last thing I need to do is make a method that takes user input, and puts it in the spot where the date/time/timezone are at. In my new.html.erb I am already taking in all this information, but I don't know how to take it from there and put it in the scheduler action.

This works:

scheduler = Rufus::Scheduler.new
      scheduler.at '2014-02-16 5:47 PM Pacific Time' do
      @sms_message.send_text_message
      end

This is what I have tried already, with no luck.

Here is the model.

class SmsMessage

include Mongoid::Document
include Mongoid::Timestamps

field :from, type: String
field :to, type: String
field :body, type: String

field :year, type: String
field :month, type: String
field :day, type: String
field :timehour, type: String
field :timeminute, type: String
field :timezone, type: String
field :ampm, type: String

belongs_to :user

def set_time

puts year + month + day + " " + timehour + timeminute + " " + ampm + " " + timezone 

end


def send_text_message

ts = self.user.twilio_sid
tt = self.user.twilio_token

sent_to_number = to
sent_from_number = self.user.twilio_number
  message_to_send = body

@twilio_client ||= Twilio::REST::Client.new ts, tt

@twilio_client.account.sms.messages.create(

  :from => "#{sent_from_number}",
  :to => "#{sent_to_number}",
  :body => "#{message_to_send}"
)

end

end

And here is the controller.

def create   
if current_user

  @sms_message = current_user.sms_messages.build(params[:sms_message].permit(:to, :from, :body))

    if @sms_message.save

      scheduler = Rufus::Scheduler.new
      scheduler.at @sms_message.set_time do
      @sms_message.send_text_message
      end

      flash[:notice] = "Your text has been scheduled!"
      redirect_to sms_messages_path

    else
      render 'new'
    end

else new_user
  redirect_to new_user_path
end

end

And the view:

<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6">
    <%= form_for(@sms_message) do |f| %>

        To: <%= f.text_field :to, class: "form-control" %>
        Body: <%= f.text_area :body, class: "form-control" %><br />
        <%= f.select :month, ['01-', '02-', '03-','04-',
            '05-', '06-', '07-', '08-', '09-', '10-', '11-', '12-'] %>
        <%= f.select :day, ['1', '2', '3', '4', '5', '6', '7', '8', '9',
        '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23',
        '24', '25', '26', '27', '28', '29', '30', '31'] %>
        <%= f.select :year, ['2014-', '2015-', '2016-', '2017-'] %>
        at <%= f.select :timehour, ['1:', '2:', '3:', '4:', '5:', '6:', '7:', '8:', '9:',
            '10:', '11:', '12:']%>
        <%= f.select :timeminute, ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10',
            '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24',
            '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38',
            '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52',
            '53', '54', '55', '56', '57', '58', '59', '60'] %>
        <%= f.select :ampm, ['AM', 'PM'] %>
        <%= f.select :timezone, ['Pacific Time', 'Eastern Time', 'Central Time',
            'Mountain Time', 'Alaska Time', 'Hawaii-Aleutian Time', 'Samoa Time'] %><br /><br /><br />
        <%= f.submit "Send Text Message", class: "btn btn-success"  %>
    <% end %>
</div>
<div class="col-md-3"></div>

I have been trying to crack this for 3+ hours with no luck. I am a beginner at Rails so sorry in advance if this question isn't formatted perfectly. Still learning. I kept getting errors with my method when I used "-", "+", and " ". So I put those things inside of the view. That is why it looks weird. What do you guys think?

Was it helpful?

Solution

In app/model/sms_message.rb

Change your set_time function to:

def set_time
  year + month + day + " " + timehour + timeminute + " " + ampm + " " + timezone 
end

This will return the string instead of printing it.

In your app/controllers/sms_message_controller.rb add:

def create   
  if current_user

    @sms_message = current_user.sms_messages.build(sms_message_params)
    if @sms_message.save

    scheduler = Rufus::Scheduler.new
    scheduler.at @sms_message.set_time do
      @sms_message.send_text_message
    end

    flash[:notice] = "Your text has been scheduled!"
    redirect_to sms_messages_path

  else
    render 'new'
  end

else new_user
  redirect_to new_user_path
end

private

def sms_message_params
  params.require(:sms_message).permit(:from, :to, :body, :month, :day, :year, :timehour, :timeminute, :ampm, :timezone)
end

OTHER TIPS

You should not create a new rufus-scheduler instance for every user request. You'll end up with myriads of rufus-scheduler threads that were useful only once and use up memory and cpu for nothing.

A better way would be to:

a) start the scheduler once and for all in an initializer (config/initializers/scheduler.rb for example)

b) schedule from the controller in the scheduler instance as necessary.

so

config/initializers/scheduler.rb:

require 'rufus-scheduler'

$scheduler = Rufus::Scheduler.new

in your controller:

def create

  if current_user

    @sms_message = current_user.sms_messages.build(params[:sms_message].permit(:to, :from, :body))

    if @sms_message.save

      $scheduler.at @sms_message.set_time do
        @sms_message.send_text_message
      end

      flash[:notice] = "Your text has been scheduled!"
      redirect_to sms_messages_path

    else
      render 'new'
    end

  else new_user

    redirect_to new_user_path
  end
end

WARNING

In the end it all depends on what "server" you run Rails on. Thin and Webrick should be OK. If you go with Passenger or another server you'll have to read the doc carefully. Some of those servers fork the Ruby process, the original process (the one hosting the rufus-scheduler thread you initialized) might not survive, losing all the schedules. Read the nice manuals that come with your tools.

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