学生向けプログラミング入門

学生向けにプログラミングを解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails

Ruby on Rails 6.0によるWebアプリケーション開発32 メールの送信

<<前  [TOP]  次>>


電子メールの設定はRailsアプリケーションの環境に含まれています。
今回は開発環境のみにメールの環境を構築していきます。
「C:\Rails6\work\shop\config\environments」フォルダの「development.rb」ファイルに設定を追加します。
「 Rails.application.configure do」からの記述が追加した部分です。


【C:\Rails6\work\shop\config\environments\application.rb】

Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.

  # In the development environment your application's code is reloaded on
  # every request. This slows down response time but is perfect for development
  # since you don't have to restart the web server when you make code changes.
  config.cache_classes = false

  # Do not eager load code on boot.
  config.eager_load = false

  # Show full error reports.
  config.consider_all_requests_local = true

  # Enable/disable caching. By default caching is disabled.
  # Run rails dev:cache to toggle caching.
  if Rails.root.join('tmp', 'caching-dev.txt').exist?
    config.action_controller.perform_caching = true
    config.action_controller.enable_fragment_cache_logging = true

    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => "public, max-age=#{2.days.to_i}"
    }
  else
    config.action_controller.perform_caching = false

    config.cache_store = :null_store
  end

  # Store uploaded files on the local file system (see config/storage.yml for options).
  config.active_storage.service = :local

  # Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = false

  config.action_mailer.perform_caching = false

  # Print deprecation notices to the Rails logger.
  config.active_support.deprecation = :log

  # Raise an error on page load if there are pending migrations.
  config.active_record.migration_error = :page_load

  # Highlight code that triggered database queries in logs.
  config.active_record.verbose_query_logs = true

  # Debug mode disables concatenation and preprocessing of assets.
  # This option may cause significant delays in view rendering with a large
  # number of complex assets.
  config.assets.debug = true

  # Suppress logger output for asset requests.
  config.assets.quiet = true

  # Raises error for missing translations.
  # config.action_view.raise_on_missing_translations = true

  # Use an evented file watcher to asynchronously detect changes in source code,
  # routes, locales, etc. This feature depends on the listen gem.
  # config.file_watcher = ActiveSupport::EventedFileUpdateChecker

  config.action_cable.disable_request_forgery_protection = true

  Rails.application.configure do
      config.action_mailer.delivery_method = :smtp
       config.action_mailer.smtp_settings = {
    	   address:        "smtp.gmail.com",
    	   port:           587, 
	   domain:         "gmail.com",
     	   authentication: "plain",
    	   user_name:      "gmailのメールアドレス",
     	   password:       "gmailのパスワード",
     	   enable_starttls_auto: true
       }
  end 
end



「gmailのアドレス」と「gmailのパスワード」の部分には自分のものを記述してください。
gmailを利用する際、セキュリティの問題が発生します。
Gmailの設定でセキュリティの「2段階認証プロセス」をオンにし、アプリパスワードを取得してください。
取得したアプリパスワードを「gmailのパスワード」部分に記述します。


ではオンラインストアで使用するメーラを作ってみます。
このメーラを使って送信する電子メールは2種類です。
注文を受けたことを知らせるメールと発送したことを知らせるメールです。
「rails generate mailer」コマンドにはメーラクラスの名前と電子メールアクションメソッドの名前を渡します。


コマンドプロンプトで「bin」フォルダに移動して「rails generate mailer Order received shipped」と入力します。

メーラの作成
メーラの作成


生成されたOrderMailerクラスは以下のようになっています。
「C:\Rails6\work\shop\app\mailers」フォルダにある「order_mailer.rb」ファイルに「default from: 'Rails '」の記述を追加しておきます。


【C:\Rails6\work\shop\app\mailers\order_mailer.rb】

class OrderMailer < ApplicationMailer

  default from: 'Rails <shop@example.com>'

  # Subject can be set in your I18n file at config/locales/en.yml
  # with the following lookup:
  #
  #   en.order_mailer.received.subject
  #
  def received
    @greeting = "Hi"

    mail to: "to@example.org"
  end

  # Subject can be set in your I18n file at config/locales/en.yml
  # with the following lookup:
  #
  #   en.order_mailer.shipped.subject
  #
  def shipped
    @greeting = "Hi"

    mail to: "to@example.org"
  end
end



電子メールのテンプレートを作成します。
「C:\Rails6\work\shop\app\views\order_mailer」フォルダにある「received.html.erb」ファイルを以下のように編集します。


【C:\Rails6\work\shop\app\views\order_mailer\received.html.erb】

<%= @order.name %>様
<br>
Railsはじめてマートでのご注文、誠にありがとうございます。
<br>
あなたがご注文されたのは以下の商品です。
<br>
<%= render @order.line_items -%>
<br>
商品発送の際には別途電子メールでご連絡いたします。



「<%= render @order.line_items -%>」の記述で読み込まれるのは「C:\Rails6\work\shop\app\views\line_items\_line_item.html.erb」ファイルです。
ここではテンプレートの内部なので「truncate()」などの正規のヘルパーメソッドを使用できます。
以下のように記述すると項目の数量とタイトルを1行の形式に整えます。


【C:\Rails6\work\shop\app\views\line_items\_line_item.html.erb】

<%= sprintf("%2d x %s",
            line_item.quantity,
            truncate(line_item.good.title, length: 50)) %>



OrderMailerクラスに戻って「received()」メソッドの内容を埋めます。


【C:\Rails6\work\shop\app\mailers\order_mailer.rb】

class OrderMailer < ApplicationMailer

  default from: 'Rails <shop@example.com>'

  # Subject can be set in your I18n file at config/locales/en.yml
  # with the following lookup:
  #
  #   en.order_mailer.received.subject
  #
  def received(order)
    @order = order

    mail to: order.email, subject: 'Railsはじめてマート 注文確認'
  end

  # Subject can be set in your I18n file at config/locales/en.yml
  # with the following lookup:
  #
  #   en.order_mailer.shipped.subject
  #
  def shipped
    @greeting = "Hi"

    mail to: "to@example.org"
  end
end



メールの生成をするための記述を「orders_controller.rb」に行います。
「create()」メソッドに「OrderMailer.received(@order).deliver_later」の記述を追加します。


【C:\Rails6\work\shop\app\controllers\orders_controller.rb】

class OrdersController < ApplicationController

  include CurrentCart
  before_action :set_cart, only: [:new, :create]
  before_action :ensure_cart_isnt_empty, only: :new
  before_action :set_order, only: [:show, :edit, :update, :destroy]

  # GET /orders
  # GET /orders.json
  def index
	@orders = Order.all
  end

  # GET /orders/1
  # GET /orders/1.json
  def show
  end

  # GET /orders/new
  def new
    @order = Order.new
  end

  # GET /orders/1/edit
  def edit
  end

  # POST /orders
  # POST /orders.json
  def create
    @order = Order.new(order_params)
    @order.add_line_items_from_cart(@cart)


    respond_to do |format|
      if @order.save
	Cart.destroy(session[:cart_id])
	session[:cart_id] = nil
        OrderMailer.received(@order).deliver_later
        format.html { redirect_to market_index_url, notice: 'ご注文ありがとうございました。' }
        format.json { render :show, status: :created, location: @order }
      else
        format.html { render :new }
        format.json { render json: @order.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /orders/1
  # PATCH/PUT /orders/1.json
  def update
    respond_to do |format|
      if @order.update(order_params)
        format.html { redirect_to @order, notice: 'Order was successfully updated.' }
        format.json { render :show, status: :ok, location: @order }
      else
        format.html { render :edit }
        format.json { render json: @order.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /orders/1
  # DELETE /orders/1.json
  def destroy
    @order.destroy
    respond_to do |format|
      format.html { redirect_to orders_url, notice: 'Order was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_order
      @order = Order.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def order_params
      params.require(:order).permit(:name, :address, :email, :pay_type)
    end

    def ensure_cart_isnt_empty
	if @cart.line_items.empty?
		redirect_to market_index_url, notice: 'カートは空です。'
	end
    end

    def pay_type_params
      if order_params[:pay_type] == "クレジットカード"
        params.require(:order).permit(:credit_card_number, :expiration_date)
      elsif order_params[:pay_type] == "現金"
        params.require(:order).permit(:routing_number, :account_number)
      elsif order_params[:pay_type] == "着払い"
        params.require(:order).permit(:po_number)
      else
        {}
      end
    end
end



これで注文されたときに入力されたメールアドレス宛に自動でメールを送ることができます。
発送完了時のメールが必要であれば「C:\Rails6\work\shop\app\mailers\order_mailer.rb」ファイルの「shipped()」メソッドを同じ用に実装すればよいです。


<<前  [TOP]  次>>