6. 各モデルの詳細画面のURLを返すメソッド(つらみ例)
class ChangeOrder < ApplicationRecord
def resource_path
routes = Rails.application.routes.url_helpers
case self
when AmpereChangeOrder
routes.ampere_change_order_path(self)
when CapacityChangeOrder
routes.capacity_change_order_path(self)
when ConsumerChangeOrder
routes.consumer_change_order_path(self)
when LeaveOrder
routes.leave_order_path(self)
when PlanChangeOrder
routes.plan_change_order_path(self)
end
end
end
STI
AmpereChangeOrder
STI
ConsumerChangeOrder
ChangeOrder
せっかく継承を用いているのだから、うまく活用しよう。
7. 各モデルの詳細画面のURLを返すメソッド(改善例)
class AmpereChangeOrder < ChangeOrder
def resource_path
Rails.application.routes.url_helpers.ampere_change_order_path(self)
end
end
class ChangeOrder < ApplicationRecord
end
親クラスからはresource_pathメソッドを削除ない
し、ダミーで実装
子クラスに記述
class ConsumerChangeOrder < ChangeOrder
def resource_path
Rails.application.routes.url_helpers.consumer_change_order_path(self)
end
end
8. 同様の例
class ChangeOrder < ApplicationRecord
def ampere_change_order?
type == 'AmpereChangeOrder'
end
def consumer_change_order?
type == 'ConsumerChangeOrder'
end
end
class AmpereChangeOrder < ChangeOrder
def ampere_change_order?
true
end
end
class ChangeOrder < ApplicationRecord
def ampere_change_order?
false
end
def consumer_change_order?
false
end
end
class ConsumerChangeOrder < ChangeOrder
def consumer_change_order?
true
end
end
親クラスはfalseで定義して、各子クラスに
て必要なものだけをオーバーライドするよ
う。
9. DecoratorでActiveRecordの属性を上書きしている
class ElecContractDecorator < Draper::Decorator
delegate_all
def status
{
'before_check' => '申込内容確認前 ',
'completed' => '完了',
}[object.status]
end
end
viewやCSV出力、API連携で利用しているが、 decorateして
いるのか、素のActiveRecordなのかわからない
class ElecContractsController < ApplicationController
def show
@elec_contract =
ElecContract.find(params[:id]).decorate
end
end
Draperの使用例:
DecoratorでActiveRecordの上書きはしないよ
うにしよう。
viewで使う用のメソッドを定義する場合は、
suffixを用いるなど、チーム内で方針を決めよ
う。
たとえば、enumerizeというgemを使っているの
であれば、表示用のメソッドには _textが生える
のでそれに合わせて enum以外も_textにする
など。
decorateしてあっても、元の値を使いたい時もある
例)元の値を使おうとする
→ decorateしてあるので、decorateされた値が出力
→ objectを付けてdecorateを解除する
=> 二度手間!
人間は、いつどのタイミングで decorateしたかがわからない
10. モデルとDecoratorで同じメソッド名で異なる挙動
class OrderItem < ApplicationRecord
def full_name(with_space: false)
return "#{family_name}#{given_name}" unless with_space
"#{family_name} #{given_name}"
end
end
class OrderItemDecorateor < Draper::Decorator
delegate_all
def full_name(sep: '', prefix: '', kana: false)
if corporate_name.present?
send("corporate_name#{kana ? '_kana' : ''}")
else
full_name_person(sep: sep, prefix: prefix, kana: kana)
end
end
def full_name_person(sep: '', prefix: '', kana: false)
value = send("#{prefix}family_name#{kana ? '_kana' : ''}") || ''
value += sep.presence || ' '
value + (send("#{prefix}given_name#{kana ? '_kana' : ''}") || '')
end
end
モデルに定義された full_nameは引
数なしではスペースなしだが、
Decoratorで定義されたfull_nameは
スペースありとなっている。
モデルとDecoratorで同じメソッド名を
定義しないようにしよう。
当初decoratorに実装していても、モ
デル側でも使用したくなった場合は、
モデル側に移動しよう。