Railsでモデルなしの簡易的なメッセージ送信機能をつけます。
メッセージ送信機能といっても幅広いため、今回はモデルなしでパラメーターのみで情報を取得し、その情報をメールで管理者へ送信する機能とします。
※本記事では、リクエストボックスとします。

実装時のイメージ
前提
・メール送信の設定済み

メイラーを作成

ターミナル

rails g mailer RequestFormMailer

上記にて/app/mailers/request_form_mailer.rb というファイルができます。

class RequestFormMailer < ApplicationMailer
  
  def request_form_to_admin(contents)
    @contents = contents
    mail(
      from: '"BOOK TECH株式会社" <support@book-tech.com>',
      to:   'contact-ml@book-tech.com',
      subject: '【BOOK TECH】リクエストを受け付けました。'
    )
  end
  
end

/app/views/request_form_mailer のディレクトリへ request_form_to_admin.text.erb を作成してadminへメール送付する際のテンプレートを作成します。

<管理者向け>
下記のリクエストを受け付けました。

内容
<%= @contents %>

以上でメールを送信する準備が整いました。

コントローラを作成

ターミナル

rails g controller request_forms
class RequestFormsController < ApplicationController
  
  def create
    RequestFormMailer.request_form_to_admin(params[:request_contents]).deliver_later
  end
  
end

ルートを作成

Rails.application.routes.draw do

  # 省略
  post 'request_forms' => 'request_forms#create'
 # 省略

end

念の為ルートが作成されているかrails routesで確認してみます。

ターミナル

rails routes
       Prefix Verb   URI Pattern                    Controller#Action
request_forms POST   /request_forms(.:format)       request_forms#create

問題なく作成されていました。

Viewを編集

リクエストボックスを実装するViewファイルへ下記を追加します。

<!--今回は非同期通信で実装-->
<div id="request-contents-box">
<%= form_with(url: request_forms_path, method: :post ) do |f| %>
  <%= f.text_area :request_contents, type: 'text', class: '' %>
  <%= f.submit "送信", class: '' %>
<% end %> 
</div>

<!--非同期通信をしない場合は、local: trueを追加すればOKです。-->
<%= form_with(url: request_forms_path, method: :post, local: true) do |f| %>

送信ボタンを押した後に、<div id=”request-contents-box”>~</div> で囲った箇所を非同期で書き換えたいため、request_formsコントローラーのcreateアクションのViewとして、/app/views/request_forms ディレクトリへ create.js.erb を作成します。

$("#request-contents-box").html('送信完了しました');

これで送信ボタンを押すと、「送信完了しました」と表示されるようになります。

書き換える内容をテキストではなく、部分テンプレートを使用する場合は下記の記述にすればOKです。

$("#request-contents-box").html('<%= escape_javascript(render("****/***")) %>');

<!--下記の記述でも同様の結果になります-->
$("#request-contents-box").html('<%= j(render("****/***")) %>');

空送信を許可しない設定にする

これまでの実装の場合だと、空送信(paramsがnilの状態)でもadminへメールを送ってしまう&送信完了しました、と表示されます。
空送信時は無効にするために、まず <div id=”request-contents-box”>~</div> の中身を部分テンプレートにします。

<div id="request-contents-box">
  <%= render 'layouts/request_form' %>
</div>

/app/views/layouts ディレクトリ配下に _request_form.html.erb を作成します。

<%= form_with(url: request_forms_path, method: :post ) do |f| %>
  <%= f.text_area :request_contents, type: 'text', class: '' %>
  <%= f.submit "送信", class: 'btn' %>
<% end %> 

そしてcreateアクションにおいては、params[:request_contents]があるときだけMailerを起動するように変更します。

class RequestFormsController < ApplicationController  

  def create
    if params[:request_contents].present?
    RequestFormMailer.request_form_to_admin(params[:request_contents]).deliver_later
    end
  end

end

createアクションのviewは、params[:request_contents]がある場合は送信完了した旨を表示させ、ない場合は layouts/request_form を表示させます。


<% if params[:request_contents].present? %>
  $("#request-contents-box").html('送信完了しました');
<% else %>
  $("#request-contents-box").html('<%= escape_javascript(render("layouts/request_form")) %>');
<% end %>

以上で空送信をしても、見た目はなにも変わらず、文字を打ち込んだ状態であれば送信できるようになります。

サービスに組み込んだ際の動き

今までの流れをベースに、サービスに組み込む際はニックネーム欄を追加したり、CSSやjQueryでカスタマイズして実装しました。

参考になれば幸いです。