user1804592
user1804592

Reputation: 137

Rails Deliver on Certain Date?

I am making a little app based on futureme.org for practice. The user goes to a page, sees a form, fills it out with email, subject, message, and a delivery date. Then the app delivers their message (email) on that date.

The problem I am having, is I am not sure how to set up the delivery date option in the model & in the view (ie. does rails have a date option?). Here is my code;

Letter.rb

class Letter < ActiveRecord::Base

      VALID_EMAIL_REGEX = /\A[\w+\-,]+@[a-z\d\-.]+\.[a-z]+\z/i
    validates_presence_of :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                          uniqueness: { case_sensitive: false }

    validates_length_of :subject, presence: true, :maximum => 30

    validates_presence_of :message

    validates_presence_of :deliver_on #not sure if this is right
end

Letters_Controller.rb

class LettersController < ApplicationController

    def create
        @letter = Letter.new(letter_params)

        if @letter.save
            LetterMailer.letter_confirm(@letter).deliver
            redirect_to letters_path, :notice => "Your letter was sent!"
        else
            render "welcome/home"
        end
    end

    private

    def letter_params
        params.require(:letter).permit(:email, :subject, :message)
    end

end

lettermailer.rb

class Lettermailer < ActionMailer::Base
  default from: "[email protected]"

  def letter_confirm(letter)
    mail(to: @letter.email, subject: "Thanks from Future Self")
  end

  def letter_email(letter)
    @letter = letter
    @url = 'http://futureself.herokuapp.com'
    mail(to: @letter.email, subject: @letter.subject)
  end
end

Home Page Form;

<%= form_for @letter, :html => {:class => 'form-horizontal'} do |f| %>
     <% if @letter.errors.any? %>
       <div class="error_messages">
       <h3><%= pluralize(@letter.errors.count, "error")%> stopped this message from being saved</h3>

       <ul>
       <% @letter.errors.full_messages.each do |msg| %>
         <li><%= msg %></li>  
        <% end %>
      </ul>

    <% end %>  

  <div class="field">
      <%= f.label :email %><br />
      <%= f.text_field :email %>
    </div>
    <div class="field">
      <%= f.label :subject %><br />
      <%= f.text_field :subject %><br />
    </div>
    <div class="field">
      <%= f.label :message, "Message" %><br />
      <%= f.text_area :message, size: "100x10" %>
    </div>
<!-- Deliver on Option -->
    <div class="field"><%= f.submit "Submit", class: "btn btn-small btn-primary" %></div>

  <% end %> 

</body> 
</html>

Any help at all would be great.

Upvotes: 0

Views: 205

Answers (2)

Matt Smith
Matt Smith

Reputation: 3529

You need a job queue, I would suggest using DelayedJob as it's about as simple as it gets (if you are using ActiveRecord) https://github.com/collectiveidea/delayed_job

Then in your LessonsController

LetterMailer.delay(run_at: @letter.deliver_on).letter_confirm(@letter)

This assumes deliver_on is a DateTime object.


Couple things you might want to consider:

Upvotes: 2

JosephL
JosephL

Reputation: 5973

Validations

I like to use the validates_timeliness gem. So you can do things like

validates_date :deliver_on, :before => lambda { Time.zone.now + 1.year },
                            :before_message => "must be earlier one year from today",
                            :on_or_after => lambda { Time.zone.now.end_of_day },
                            :on_or_after_message => "must be after today"

Form

You can use jquery-ui-rails

    f.input :deliver_on, as: :string, label: "Date of delivery (dd/mm/yyyy)", input_html: {class: "jquery-ui-date", value: f.deliver_on ? l(f.deliver_on) : nil }

Don't get me started on RegEx for email. Try googling it ;)

And yeah like @mattsmith said check out delayed job.

Upvotes: 1

Related Questions