# FormでもらったデータをDBに保存しないActiveModel::Model

# ActiveModel::Model

みなさん、ActiveModelって知ってますか?

例えば、Formで受け取ったデータをDBに保存せずに、何かの実装したいときにメチェメチャ便利です!

今回は、Formで{ query: { :name, :email } }を受け取り、DBには保存せずにActionMailerを使ってMailを流す場合を考える。

# ActiveModel::Modelを使わない場合

app/controllers/queries_controller.rb

class QueriesController < ApplicationController
  def new
  end
  def create
    if params[:name].present? && params[:email].present? # if文の条件分岐のvalidationは好ましくない
      ContactMailer.post_email(params[:name], params[:email]).deliver
    else
       # このelse文の中身のvalidationは綺麗じゃない
      @error_messages = []
      @error_messages << 'タイトルを入力してください' if params[:name].blank?
      @error_messages << '本文を入力してください' if params[:email].blank?
      render :new
    end
  end
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

app/views/queries/new.html.erb

<%= form_with url: queries_path, local: true do %>
  <% @error_messages && @error_messages.each do |message| %>
    <%= message %>
  <% end %>
  <%= label_tag :name %>
  <%= text_field_tag :title, params[:name] %>
  <%= label_tag :email %>
  <%= text_area_tag :body, params[:email] %>
  <%= submit_tag %>
<% end %>
1
2
3
4
5
6
7
8
9
10

Queryのテーブルがない場合、当然自分でModelを作ろうなんて普通は思わないですよね? また、以上のような場合はControllerの役割を超えすぎてるし、validationが美しくない!

そんなときに便利なのが、ActiveModel::Model!

# ActiModel::Modelを使う場合

Viewは以上と同じなので、割愛。

app/controllers/queries_controller.rb

class QueriesController < ApplicationController
  def new
  end
  def create
    @query = Query.new(query_params)
    if @query.save
        redirect_to home_path, notice: 'フィードバックを送信しました'
    else
        @query.errors.full_messages
    end
  end
   private
   def query_params
        params.require(:query).permit(
            :name,
            :email
        )
   end
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

app/models/query.rb

require "active_model" # これを忘れずに
class Query # DBに保存しないため、ActiveRecoredは継承しない!
    include ActiveModel::Model
    attr_accessor :name, :email
    validates :name, :email, presence: true
    def save
        return false unless valid?
        ContactMailer.post_email(params[:name], params[:email]).deliver
        true
   end
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

これで、ControllerはController自身の役割を超えずに、またvalidationもきれいに書くことができる