LoginSignup
1
3

More than 1 year has passed since last update.

[Rails] Formオブジェクトに使えるmodule

Last updated at Posted at 2022-05-25

概要

Formオブジェクトなどを実装する場合、ActiveModel::ModelをincludeしたPOROクラスを実装することがあると思います。
この記事ではその際に、追加のmoduleを使ってできることをまとめてみました。

環境

Rails: 7.0.3

ActiveModel::API

まずはこのActiveModel::APIをincludeすることから始まります。
これにより、以下のような機能が利用できます。

  • form_withrenderなどのAction Viewのヘルパーメソッド
  • 値のvalidation

tips

  • 値を上書きしたい場合、対象のattributeはattr_readerにしておき、#{attr_name}=のsetterを定義します。
email_contact.rb
class EmailContact
  include ActiveModel::Model

  # 値を変更したい場合、ここはattr_readerだけにして、setterメソッドを定義する
  attr_accessor :email
  attr_reader :message

  validates :email, :message, presence: true

  # setter
  def message=(value)
    @message = value + 'ありがとうございます。'
  end

  def deliver
    if valid?
      # deliver email
    end
  end
end
new.html
<%= form_with model: @email_contact, local: true do |f| %>
  <%= f.label :email %>
  <%= f.text_field :email %>
  <%= f.label :message %>
  <%= f.text_area :message %>
  <%= f.submit %>
<% end %>
email_contacts_controller.rb
class EmailContactsController < ApplicationController
  def create
    @email_contact = EmailContact.new(email_contact_params)
    # <@email="sample@example.com", @message="こんにちはありがとうございます。">
    @email_contact.deliver
  end

  def new
    @email_contact = EmailContact.new
  end

  def email_contact_params
    params.require(:email_contact).permit(:email, :message)
  end
end

ActiveModel::Attributes

ActiveModel::Attributesを使うことで、以下のような機能が利用できます。

  • 値のキャスト
  • 値のデフォルト値設定

tips

email_contact.rb
class EmailContact
  include ActiveModel::Model
  include ActiveModel::Attributes

  # formに何も入れなかった場合、sample@example.comが入る
  attribute :email, :string, default: 'sample@example.com'
  # formからは文字列のparamsが渡ってくるが、これによりdate型に変換される
  attribute :send_date, :date
  ...
end
new.html
<%= form_with model: @email_contact, local: true do |f| %>
  <%= f.label :email %>
  <%= f.text_field :email %>
  ...
  <%= f.label :send_date %>
  <%= f.date_field :send_date %>
  <%= f.submit %>
<% end %>

以下のように、デフォルト値の設定と、キャストが行われます。
また、attributesなどのメソッドも利用できるようになります。

email_contacts_controller.rb
class EmailContactsController < ApplicationController
  def create
    @email_contact = EmailContact.new(email_contact_params)
    # @email.contact.attributes => {"email"=>"sample@example.com", "send_date"=>Sat, 01 Jan 2022}
    @email_contact.deliver
  end
  ...
end

Enumerize

列挙型を扱う際に使いますが、こちらも組み込むことが可能です。
これにより、以下の機能などが利用可能です。

  • 値のValidation
  • Form側でのoptionsの使用
  • i18nの設定

tips

class EmailContact
  include ActiveModel::Model
  include ActiveModel::Attributes
  extend Enumerize

  enumerize :type, in: %w(purchase notice register)
  attribute :email, :string
  validates :name, :email, :message, presence: true
  ...
end

以下のようにEmailContact.type.optionsでオプション一覧を表示可能。
keyはtype.textになるので、i18nを使用すれば、その値で表示される。

new.html
<%= form_with model: @email_contact, local: true do |f| %>
  <%= f.label :email %>
  <%= f.text_field :email %>
  ...
  <%= f.label :type %>
  <%= f.select :type, EmailContact.type.options %> 
  <%= f.submit %>
<% end %>
email_contacts_controller.rb
class EmailContactsController < ApplicationController
  def create
    @email_contact = EmailContact.new(email_contact_params)
    # @email.contact.attributes => {"type"=>"purchase", "email"=>"sample@example.com"}
    @email_contact.deliver
  end
  ...
end
1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3