SlideShare a Scribd company logo
1 of 44
Crafting Rails 4 Applications
第2章
Active Modelを使って
モデルを作る
目標
Mail Formプラグインを作ってActive Modelを勉強する
• ActiveModel::AttributeMethods
• API準拠
• ActiveModel::Conversion
• ActiveModel::Naming
• ActiveModel::Translation
• ActiveModel::Validations
• ActiveModel::Callbacks
• そして最後に…
以下のプラグインを作ってみよう
Post リクエストから送信されたハッシュを受け取り、バリデーシ
ョンを行ってから、特定のメールアドレスに送信する
まずは一発
attributes()
最初にattributes()メソッドを作ってみる
(動作: Mail Formオブジェクトに含める属性を指定する)
ActiveModel::AttributeMethods
Mail Formオブジェクトに含める属性を指定する
テスト:
attributes()
この時点ではMailForm::Baseがないので
bundle exec rake testすると当然失敗する
テストが通るようにするためにMailForm::Baseを実装
属性の作成はattr_accessor()に委譲(delegate)している
attributes()
attributes()
autoload()とは
• MailForm::Baseという定数が最初に参照されるまでは
mail_form/base.rbが読み込まない
• 起動を早めるためによく使われるテクニック
autoload()を追加することでテストがパスする
ActiveModel::AttributeMethods
ActiveModel::AttributeMethodsは、定義済みの属性を追いかけて共
通の動作を追加する
ここではclear_というprefixにマッチするメソッドを定義してみる
(ActiveRecordでおなじみの、定義した属性に自動的にメソッドが
追加される、あの動作を再現する)
まずはテストを作成
ActiveModel::AttributeMethods
clear_で始まる属性を定義し、それを使用してメソッドを定義する
ActiveModel::AttributeMethods
これでテストに通る
ActiveModel::AttributeMethods
attribute_method_prefix()をattribute_method_suffixに変えればsuffix
でも同じことができる
name?()とemail?()にマッチさせる場合
attribute_method_affix()を使用すれば両方を同時に指定することも
できる
秘密はmethod_missing()にあり
ActiveModel::AttributeMethodsは、動的なメソッドをキャッチする
ために内部でmethod_missing()を使用する
clear_name()やclear_email()のようなメソッドが明示的には定義さ
れていないのに、属性を定義するだけで利用できるのはこのおかげ
そしてActiveModelは、clear_*をキャッチしたらclear_attributeを呼
び出してくれる
method_missing()
method_missing()は、メッセージの継承パスの最後のところでメッ
セージをキャッチする
(排水口に取り付けたストッキングみたいなもの?)
method_missing()はしばしば黒魔法にたとえられる
非常に強力だが、乱用すると流れを追いにくくなり、えらいことに
なるらしい
このあたりのことは「Metaprogramming Ruby」に詳しく載っている
method_missing
ActiveRecordではこのような動的なattribute methodが広く使われ
ている
でも、Rails 4 で find_by_* 形式の動的な検索メソッドが非推奨にな
ったのは、もしかしてやりすぎてしまったからなのかも。
Railscastより:
ぼそっと
rubyのクラス定義でクラス名をファジーマッチできたらもっとシン
プルにならないだろうか?
冗談です
Active Model APIに準拠する
自作モデルをActive Model APIに沿ったものにする:
(そうしないとcontrollerやviewで使えない)
実は ActiveModel::Lint::Testsですべて行える
Active Model APIに準拠する
APIに合致するまでエラーを出しまくる
Active Model APIに準拠する
以下のエラーを解決しよう
以下を定義すればよい
でもこれをもろに実装する必要はない
ActiveModel::Conversion
ActiveModel::Conversionを使用すれば、to_model()だけでなく
to_key()やto_param()、to_partial_path()などの必須メソッドを実
装できる
• to_key() : モデルを指定するキーの配列を返す。viewのdom_id()で
使用され、dom_id()はRailsで広く使われている
• to_param() : ルーティングで使用され、モデルのユニークURL生
成のために広く使われている
• to_partial_path() : ビューのrender()で使用される
ActiveModel::Conversion
これらのメソッドをカスタマイズすることもできる
to_param() : URLのidにタイトルを加えたい:
to_partial_path() : postでフォーマットを指定したい
ビューでこう書くより
オーバーライドしてから呼び出す方がスマートかつ高速
(render呼び出しが1回で済むので)
ActiveModel::Conversion
ActiveModel::Conversionをインクルードするだけでよい
これでエラーが3つに減った
ActiveModel::Naming
model_nameのエラーを減らすには、ActiveModel::Namingをエク
ステンド
これを追加すると、human()やsingular()などのモデル名活用が行わ
れる
ActiveModel::Translation
i18n対応するにはActiveModel::Translationをエクステンド
* i18nバックエンドが確実にリロードされるように
begin…ensure…endで囲んでいる
ActiveModel::Validation
以下のエラーを解消するためにActiveModel::Validationをインク
ルード
persisted?()
今回、以下のエラーについては自前で実装が必要
persisted?()
このmail_formで永続性は不要なのでfalseを返すようにする
(※protectedの下に書かないこと)
これでテストはすべてパスする
Formを配信する
次はdeliver()メソッドを実装してみる
• モデルのemail属性に保存されているメアドに送信する
でテスト
Formを配信する
実装
(MailForm::Notifierを作成)
ActionMailer::Baseを継承して実装
contact()はMailFormクラスではなく子クラスのメールデータ
(:to, :from, :subject)を返す(配信先をカスタマイズするのにNotifierクラ
スをいじる必要がない
Formを配信する
append_view_path()はプラグインフォルダ内にlib/viewsフォルダを
追加しテンプレート検索の対象とする
以下を追加
Formを配信する
準備が整ったのでサンプルクラスにメソッドを追加してみる
メイラーにビューテンプレートがないのでこの時点では失敗する
ビューテンプレートを追加してみる
Formを配信する
attrubete_names()というclass_attributeを定義して属性のリストを
取得できる
• attributes()を呼ぶたびに更新される
• 継承時に自動的に動作する
これでテストに通る
capybaraで結合テスト
(略)
validation
validates_presence_of() の動作:
以下の呼び出しは基本的にどれも同じ
Railsは:presenceキーを PresenceValidateに変換し、現在のクラス
にPresenceValidatorという名前の定数があるかどうかを調べる:
validation
Rubyでは定数の探索はすべての先祖クラスに対して行われるの
で、これは動作する
validation
スパム判定用のabsence validatorを作ってみる
(ボットにしか見えないnicknameフィールドをわざとフォームに
作っておき、そこに書き込みがあればスパムとみなす)
まずはテスト
AbsenceValidatorクラスを定義 (EachValidatorを継承)
validation
MailForm::Baseでインクルードする
MailForm::ValidatorsはMailForm::Baseの先祖チェインに追加され
る
それにより、:absenceをvalidates()のキーとして与えると、
AbsenceValidator定数の値が探索され、MailForm::Validatorsの中を
検索、初期化が行われる
(PresenceValidatorのときと同様)
あとはautoloadすればよい
ActiveModel::Callbacks
最後に、deliver()メソッドにbeforeとafterを追加してみよう
まずはfixture
evaluated_callbacks()メソッドを定義
ActiveModel::Callbacks
callbackが評価されていることを確認するテスト
実装 (ActiveModel::Callbacksをextendしてコールバックを定義)
ActiveModel::Callbacks
これでテストは通る
ActiveModel::Model
ここまでは勉強のために個別に実装を行ってきたが、実はActive
Modelに準拠するのは非常に簡単:
ActiveModel::Modelをインクルードするだけでいい
これだけで、Lintテストはすべてパスする
ActiveModel::Model
その実装
(これまでやってきたことを
集約しただけ)
おまけ
この章と同じコンセプトで作られたmail_form gemがある
https://github.com/plataformatec/mail_form
おつかれさまでした

More Related Content

Similar to Building Modelsvwith Active Model

scala+liftで遊ぼう
scala+liftで遊ぼうscala+liftで遊ぼう
scala+liftで遊ぼうyouku
 
jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック
jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハックjQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック
jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハックJun-ichi Sakamoto
 
Spring bootでweb 基本編
Spring bootでweb 基本編Spring bootでweb 基本編
Spring bootでweb 基本編なべ
 
やってみよう!ASP.NET MVC #2
やってみよう!ASP.NET MVC #2やってみよう!ASP.NET MVC #2
やってみよう!ASP.NET MVC #2Tadahiro Higuchi
 
実装(3) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第32回】
実装(3) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第32回】実装(3) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第32回】
実装(3) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第32回】Tomoharu ASAMI
 
appengine ja night #24 Google Cloud Endpoints and BigQuery
appengine ja night #24 Google Cloud Endpoints and BigQueryappengine ja night #24 Google Cloud Endpoints and BigQuery
appengine ja night #24 Google Cloud Endpoints and BigQueryRyo Yamasaki
 

Similar to Building Modelsvwith Active Model (7)

scala+liftで遊ぼう
scala+liftで遊ぼうscala+liftで遊ぼう
scala+liftで遊ぼう
 
UnicastWS vol.2
UnicastWS vol.2UnicastWS vol.2
UnicastWS vol.2
 
jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック
jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハックjQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック
jQuery Validation x ASP.NET MVC で遭遇した不具合 & 対抗ハック
 
Spring bootでweb 基本編
Spring bootでweb 基本編Spring bootでweb 基本編
Spring bootでweb 基本編
 
やってみよう!ASP.NET MVC #2
やってみよう!ASP.NET MVC #2やってみよう!ASP.NET MVC #2
やってみよう!ASP.NET MVC #2
 
実装(3) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第32回】
実装(3) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第32回】実装(3) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第32回】
実装(3) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第32回】
 
appengine ja night #24 Google Cloud Endpoints and BigQuery
appengine ja night #24 Google Cloud Endpoints and BigQueryappengine ja night #24 Google Cloud Endpoints and BigQuery
appengine ja night #24 Google Cloud Endpoints and BigQuery
 

Recently uploaded

PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directoryosamut
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdffurutsuka
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 

Recently uploaded (9)

PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdf
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 

Building Modelsvwith Active Model