Richlewis
Richlewis

Reputation: 15374

ActionMailer delivery when following parameters met

Forgive me for asking what i believe is quite an in depth challenge (well for me at the moment anyway)

I have a small app that allows users to check in, check out and hopefully receive emails when a book has been checked back in by registering their interest via a remind me button

So far I have setup actionmailer (basic setup)

class ReminderMailer < ActionMailer::Base
default from: "email address"

def remind_email(book)
@book = book
@url = "http://localhost:3000"
mail(:to => @book.user.email, :subject => "Book Reminder")


end

I have all the config in place to send the emails as I am already doing that through devise.

I have also created the mailer templates. It is the logic I am stuck with.

So when a User checks a book out i pass this back to the model

<%= form_for @book do |f| %>
<%= f.label :checked_out, "Check Book Out?" %>
<%= f.check_box :checked_out, {}, true %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<%= f.hidden_field :checked_out, :value => true %>
<%= f.submit 'Checkout' %>
<% end %>

Check In

<%= form_for @book do |f| %>
<%= f.label :checked_out, "Check Book Back In" %>
<%= f.check_box :checked_out, {checked: false}, false  %>
<%= f.hidden_field :user_id, :value => nil %>
<%= f.hidden_field :checked_out, :value => false %>
<%= f.submit 'Check In' %>
<% end %>

Register Interest

<%= form_for @book do |f| %>
<%= f.label :remind_me, "let Me know when book back in" %>
<%= f.check_box :remind_me, {checked: false}, false  %>
<%= f.hidden_field :remind_me, :value => current_user.id %>
<%= f.submit 'Remind Me' %>
<% end %>

So my thinking is that when you register your interest your user id gets placed into the remind_me column, and what i want to achieve is that when the checked_out field is false and book.user_id is back to nil I would like the email to send the the user whos user_id is in the remind_me column

Am i thinking about this in the correct way?

if anyone can help it would be appreciated so that i can learn from this and then keep practicing it until I understand what is going on

Upvotes: 0

Views: 101

Answers (1)

CupraR_On_Rails
CupraR_On_Rails

Reputation: 2489

There are 2 ways to answer:

The first one, don't use a form to check in a book and just call a method. For example: You replace your form with a link which call a new method in your controller:

<%= link_to "check in", check_in_book_path(@book.id) %>

In your books_controller you call a model method which check in the book:

def check_in
  @book = Book.find params[:id]
  @book.check_in!
  redirect_to book_path(@book)
end

In your book model:

def check_in!
  self.user = nil
  self.checked_out = false
  if self.save
    RemindMailer.remind_mail(self).deliver
  end
end

Don't forget to add the route for your new controller method.

The second way, if you keep your form, is shorter but more complicated. You need to add a callback to your model which will verify if the data changed. For example, in you book model:

after_save :send_mail_if_check_in

def send_mail_if_check_in
  if !self.checked_out && self.changes[:user_id] && self.user.nil?
    RemindMailer.remind_mail(self).deliver
  end
end

I prefer the first solution because it seems to be a state machine which is more maintenable.

I hope this help

Upvotes: 3

Related Questions