Next dump

This commit is contained in:
Bill Niblock 2025-01-24 14:11:47 -05:00
parent ef378a1f59
commit f0e1a2890e
12 changed files with 91 additions and 1 deletions

View file

@ -0,0 +1,15 @@
class UnsubscribesController < ApplicationController
allow_unauthenticated_access
before_action :set_subscriber
def show
@subscriber.destroy
redirect_to root_path, notice: "Unsubscribed successfully."
end
private
def set_subscriber
@subscriber = Subscriber.find_by_token_for(:unsubscribe, params[:token])
end
end

View file

@ -0,0 +1,11 @@
class ProductMailer < ApplicationMailer
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.product_mailer.in_stock.subject
#
def in_stock
@product = params[:product]
mail to: params[:subscriber].email
end
end

View file

@ -1,5 +1,5 @@
class Product < ApplicationRecord
has_many :subscribers, dependent: :destroy
include Notifications
has_one_attached :featured_image
has_rich_text :description

View file

@ -0,0 +1,18 @@
module Product::Notifications
extend ActiveSupport::Concern
included do
has_many :subscribers, dependent: :destroy
after_update_commit :notify_subscribers, if: :back_in_stock?
def back_in_stock?
inventory_count_previously_was.zero? && inventory_count > 0
end
def notify_subscribers
subscribers.each do |sub|
ProductMailer.with(product: self, subscriber: sub).in_stock.deliver_later
end
end
end
end

View file

@ -1,3 +1,4 @@
class Subscriber < ApplicationRecord
belongs_to :product
generates_token_for :unsubscribe
end

View file

@ -0,0 +1,7 @@
<h1>Good News!</h1>
<p>
<%= link_to @product.name, product_url(@product) %> is back in stock!
</p>
<%= link_to "Unsubscribe", unsubscribe_url(token: params[:subscriber].generate_token_for(:unsubscribe) %>

View file

@ -0,0 +1,6 @@
Good News!
<%= @product.name %> is back in stock!
<%= product_url(@product) %>
Unsubscribe: <%= unsubscribe_url(token: params[:subscriber].generate_token_for(:unsubscribe) %>

View file

@ -0,0 +1,11 @@
<% if product.inventory_count? %>
<p><%= product.inventory_count %> in stock</p>
<% else %>
<p>Out of Stock</p>
<p>Notify me when more is stocked:</p>
<%= form_with model: [product, Subscriber.new] do |form| %>
<%= form.email_field :email, placeholder: "you@example.com", required: true %>
<%= form.submit %>
<% end %>
<% end %>

View file

@ -5,6 +5,8 @@
<%= @product.description %>
<% end %>
<%= render "inventory", product: @product %>
<% if authenticated? %>
<%= link_to "Edit", edit_product_path(@product) %>
<%= button_to "Delete", @product, method: :delete,

View file

@ -1,6 +1,7 @@
Rails.application.routes.draw do
resource :session
resources :passwords, param: :token
resources :unsubscribe, only: [ :show ]
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
resources :products do
resources :subscribers, only: [ :create ]

View file

@ -0,0 +1,7 @@
# Preview all emails at http://localhost:3000/rails/mailers/product_mailer
class ProductMailerPreview < ActionMailer::Preview
# Preview this email at http://localhost:3000/rails/mailers/product_mailer/in_stock
def in_stock
ProductMailer.in_stock
end
end

View file

@ -0,0 +1,11 @@
require "test_helper"
class ProductMailerTest < ActionMailer::TestCase
test "in_stock" do
mail = ProductMailer.in_stock
assert_equal "In stock", mail.subject
assert_equal [ "to@example.org" ], mail.to
assert_equal [ "from@example.com" ], mail.from
assert_match "Hi", mail.body.encoded
end
end