【Rails】DBと連携しないモデル(Active Model)の日本語化対応
Railsでスケジュール通知アプリを個人開発しています。
このアプリで実装したお問い合わせフォームを例に、「DBに紐づかないモデル」の扱い方をまとめます。
環境
アプリは以下の環境で作成しています。
- macOS 11.6.2
- Ruby 3.1.2
- Rails 7.0.3
- PostgreSQL 14.4
DBと連携しないモデルでActive Recordの機能を使う
Railsのモデルは通常ActiveRecord::Base
というクラスを継承しており、DBと連携して使います。このActiveRecord::Base
を継承したモデルであれば、バリデーションやアソシエーションなどの便利な機能を使うことができます。
一方、DBと連携しないモデルを設計したい場合は、ActiveRecord::Base
を継承しないクラスにする必要があります。
では、「DBとは連携しないけれども、Active Recordにあるような便利な機能は使いたい」……そんなときはどうすればいいのでしょうか?
実はそのようなケースもRailsは想定していて、ActiveModel::Model
をinclude
すると、ActiveRecord::Base
を継承していないクラスでも、Active Recordの機能の一部が使えるようになるのです。
下記が、DBと連携しないモデルの例(Inquiry
)です。入力されたお問い合わせ内容はすぐにメールで送信するのでDBには保存しませんが、バリデーション機能は使いたいので、include ActiveModel::Model
としました。
class Inquiry
include ActiveModel::Model
attr_accessor :email, :body
validates :email, presence: true
validates :body, presence: true, length: { maximum: 65535 }
end
関連するコントローラ、ルーティング、ビューは次の通りです。InquiriesController
では、create
アクションの@incuiry.valid?
の箇所で、フォームに入力された内容のバリデーションを行っています。
class InquiriesController < ApplicationController
def new
@inquiry = Inquiry.new
end
def create
@inquiry = Inquiry.new(inquiry_params)
if @inquiry.valid?
# ここにメール送信の処理を記述(省略)
redirect_to root_path, success: 'お問い合わせを受け付けました'
else
flash.now[:error] = 'お問い合わせの受付に失敗しました'
render :new
end
end
private
def inquiry_params
params.require(:inquiry).permit(:email, :body)
end
end
/ CSSは省略
- if @inquiry.errors.any?
- @inquiry.errors.full_messages.each do |error_message|
ul
li
= '- ' + error_message
h1
| お問い合わせ
p
| 下記のフォームに必要事項をご記入ください。
br
| 近日中にメールにて返信いたします。
= form_with model: @inquiry do |f|
label
span
= Inquiry.human_attribute_name('email') + '(必須)'
= f.text_field :email
label
span
= Inquiry.human_attribute_name('body') + '(必須)'
= f.text_area :body
= f.submit '送信'
Rails.application.routes.draw do
resources :inquiries, only: %i(new create)
end
Active Modelをincludeしたモデルの日本語化
Active Modelをincludeしたモデルの日本語化のやり方は、Railsガイドの「Rails 国際化(i18n)API」のページの、「Active Recordモデルで翻訳を行なう」の項に書いてあります。
通常のActive Recordのモデルを日本語化するときは、訳文ファイルでja:
のあとにactiverecord:
という階層を作って日本語訳を記述しますが、Active modelをincludeしたモデルを日本語化するときは、activerecord:
の部分をそのままactivemodel:
に置き換えて日本語訳を記述すればOKです。
ja:
activemodel:
models:
inquiry: 'お問い合わせ'
attributes:
inquiry:
email: '返信用メールアドレス'
body: 'お問い合わせ内容'
これで、Inquiry.human_attribute_name('email')
が「返信用メールアドレス」を、Inquiry.human_attribute_name('body')
が「お問い合わせ内容」を返すようになります。
実際に、アプリのお問い合わせフォームを表示させてみます。
フォームのラベルに日本語訳が表示されていますし、空の状態で「送信」ボタンを押すと、日本語化されたエラーメッセージが表示されました!
感想
Active Modelに関する記事はいくつかありましたが、その日本語化に関する情報はあまりなかったので書いてみました。
調べるついでに、Rails7では「Active ModelからActiveModel::APIが切り出された」という情報も発見しました。下記にリンクを貼っておきます。
Discussion