【Ruby on Rails】お問合せフォームの作成

# 目標
このような問い合わせフォームを作成します。
今回は開発環境でgmail宛に送信する方法です。
![問い合わせ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700999/a1e4ccb5-2865-0d5a-7d6a-f96f5ea30d96.png)


# 開発環境
ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina


# 前提
※　▶◯◯　を選択すると、説明等が出てきますので、
　　よくわからない場合の参考にしていただければと思います。

bootstrap4導入済み

[【Ruby on Rails】enumを日本語表記にする方法](https://qiita.com/japwork/items/2009de397519ca36a0b7)
お問い合わせ件名の選択に使用します。_i18nが使用されている箇所です。




# 流れ
1 mailerを作成、編集
2 テーブルの作成
3 config/enviroments/development.rbの編集
4 環境変数の設定
5 controllerの作成
6 routing編集
7 viewの編集
8 googleアカウントで安全性の低いアプリのアクセスを許可する



# mailerを作成、編集
```:ターミナル
$ rails g mailer ContactMailer
```
送信先と件名を指定します。
ENV['TOMAIL']は後ほど設定します。

```rb:app/mailers/contact_mailer.rb
class ContactMailer < ApplicationMailer
  def send_mail(contact)
    @contact = contact
    mail to:   ENV['TOMAIL'], subject: '【お問い合わせ】' + @contact.subject_i18n
  end
end

```


# テーブルの作成

```:ターミナル
$ rails g model Contact
```
カラムは必要なものを追加してください。
enumの設定については次回記事で解説します。

```rb:db/migrate/xxxxxxxxxxxxx_create_contacts.rb
class CreateContacts < ActiveRecord::Migration[5.2]
  def change
    create_table :contacts do |t|
      t.string :name, null: false
      t.string :email, null: false
      t.string :phone_number, null: false
      t.integer :subject, default: 0, null: false
      t.text :message, null: false

      t.timestamps
    end
  end
end
```


# config/enviroments/development.rbの編集
```rb:config/enviroments/development.rb

...

config.action_mailer.raise_delivery_errors = false　
 ↓　true　に変更
config.action_mailer.raise_delivery_errors = true

...

config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
      port: 587,
      address: 'smtp.gmail.com',
      domain: 'smtp.gmail.com',
      user_name: ENV['SMTP_USERNAME'],
      password: ENV['SMTP_PASSWORD'],
      enable_starttls_auto: true
  }
end
```


# 環境変数の設定
今回はGitHub上にアドレスとパスワードをアップしないよう
gem "dotenv-rails"を使用します。

```:Gemfile
gem "dotenv-rails"
```
```:ターミナル
$ bundle install
```
次にGemfileと同じ階層に .envファイルを作成

```:.env
TOMAIL=送信先のアドレス

SMTP_USERNAME=送信元のgmailアドレス
SMTP_PASSWORD=送信元のgmailアドレスのパスワード
```

<details><summary>失敗談【SMTP_USERNAME】</summary>
はじめにSMTP_USERNAMEをMAILと設定しようとしたところ、
何度やってもエラーになりました。
なので、設定する際にはこのように表記をした方がいいかもしれません。
命名規則を勉強した上でまた更新したいと思います。</details>

.gitignoreファイルの一番下に下記を追加。

```:.gitignore
/.env
```
# controllerの作成
```:ターミナル
$ rails g controller contacts
```
```rb:app/controllers/contacts_controller.rb
class Public::ContactsController < ApplicationController
  def new
    @contact = Contact.new
  end
  
  # 確認画面を作成する場合はこのような記述になるかと思います。
  # newアクションから入力内容を受け取り、
  # 送信ボタンを押されたらcreateアクションを実行します。
  def confirm
    @contact = Contact.new(contact_params)
    if @contact.invalid?
      render :new
    end
  end
　
  # 入力内容に誤りがあった場合、
  # 入力内容を保持したまま前のページに戻るのが当たり前になっているかと思いますが、
  # backアクションを定義することで可能となります。
  def back
    @contact = Contact.new(contact_params)
    render :new
  end

  # 実際に送信するアクションになります。
  # ここで初めて入力内容を保存します。
  # セキュリティーのためにも一定時間で入力内容の削除を行ってもいいかもしれません。
  def create
    @contact = Contact.new(contact_params)
    if @contact.save
      ContactMailer.send_mail(@contact).deliver_now
      redirect_to done_path
    else
      render :new
    end
  end

  # 送信完了画面を使用する場合お使いください。
  def done
  end

  private

  def contact_params
    params.require(:contact)
          .permit(:email,
                  :name,
                  :phone_number,
                  :subject,
                  :message
                 )
  end
end

```

# routing編集
```rb:config/routes
resources :contacts, only: [:new, :create]
post 'contacts/confirm', to: 'contacts#confirm', as: 'confirm'
post 'contacts/back', to: 'contacts#back', as: 'back'
get 'done', to: 'contacts#done', as: 'done'
```



# viewの編集
app/views/contact_mailer配下に
send_mail.html.erb
send_text.html.erb　を作成してください。
※なぜ２つ作成するかはわからないので、未来の自分に託したいと思います。。。
内容は同じ内容を記入してください

```erb:app/views/contact_mailer/send_mail.html.erb,send_text.html.erb
<%= @contact.name %> 様 から問い合わせがありました。<br>
【Tel】：<%= @contact.phone_number %><br>
【Mail】：<%= @contact.email %><br>
【用件】：<%= @contact.subject_i18n %><br>
【お問い合わせ内容】<br>
<span style="white-space: pre-wrap;"><%= @contact.message %></span>
```

実際の入力フォームを作成していきます。
※名前とmessageのみ記述します。

```erb:app/views/contacts/new.html.erb

<%= form_for(@contact, url: confirm_path) do |f| %>
  <div class="form-group">
    <%= f.label :name, 'お名前*' %>
    <%= f.text_field :name, autofocus: true, class: 'form-control' %>
  </div>
    
  <div class="form-group">
    <%= f.label :message, 'メッセージ*' %>
    <%= f.text_area :message, size: '10x10', class: 'form-control' %>
  </div>

  <div>
    <%= f.submit '入力内容確認' %>
  </div>
<% end %>
```
確認画面から入力画面に戻るコードを記述します。
※名前とmessageのみ記述します。

```erb:app/views/contacts/confirm.html.erb

<table>
  <tbody>
    <tr>
      <td class="text-center" style="width: 30%;">お名前</td>
      <td><%= @contact.name %></td>
    </tr>
    <tr>
      <td class="text-center">メッセージ</td>
      <td style="white-space: pre-wrap;"><%= @contact.message %></td>
    </tr>
  </tbody>
</table>

<%= form_for(@contact) do |f| %>
  <%= f.hidden_field :name %>
  <%= f.hidden_field :email %>
  <%= f.hidden_field :phone_number %>
  <%= f.hidden_field :subject %>
  <%= f.hidden_field :message %>
  <div><%= f.submit '送信' %></div>
<% end %>
<%= form_for @contact, url: back_path do |f| %>
  <%= f.hidden_field :name %>
  <%= f.hidden_field :email %>
  <%= f.hidden_field :phone_number %>
  <%= f.hidden_field :subject %>
  <%= f.hidden_field :message %>
  <div><%= f.submit '入力画面に戻る' %></div>
<% end %>
```
<details><summary>補足【<%= @contact.name %>】</summary>
new画面のフォームでconfirmアクションに飛ばしているため、
paramsでは@contactに値が入っている状態が作れています。
したがって保存せずとも表示が可能です。</details>

<details><summary>補足【送信】</summary>
@contactで表示はされているものの、保存は出来ていない状態です。
このままcreateアクションに飛ばしてしまうと保存されない状態でparamsを投げてしまいます。
そこでf.hidden_fieldを使い、それぞれparamsを再代入し、createに飛ばしています。</details>

<details><summary>補足【入力画面に戻る】</summary>
こちらは送信と同じ理由になりますので、上記をご確認ください
@contactで表示はされているものの、保存は出来ていない状態です。</details>



# googleアカウントで安全性の低いアプリのアクセスを許可する
[Google 安全性の低いアプリのアクセスを有効にする方法](https://qiita.com/miriwo/items/7c5a451a35cecdd72085)
こちらの記事がわかりやすかったので参考にしてください。


#参考

- [Railsとメール送信あれやこれや](https://okzk.org/blog/how-to-use-email-for-rails/)
- [Ruby OnRailsで環境変数を使用する方法](https://qiita.com/alokrawat050/items/0d7791b3915579f95791)　※英語です
- [シンプルにお問い合わせ機能を実装する](https://qiita.com/s_rkamot/items/d6d0e9abb43383342fd6)
- [rails でお問合せフォームを作り、自分のメールアドレスに送信させる方法](https://qiita.com/george022497/items/30a360baca14b33b4602)


# まとめ
個人のアドレスや電話番号を扱うことになるため、
プライバシーポリシーや定期的な情報の削除は必須だと思います。
しかし、メールを相手に自動的に送信できるのは様々なこｔにおいて優先順位は高めだと思いますので、
しっかり理解したほうがいいかもしれません。


またtwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら　https://twitter.com/japwork