ActiveDecoratorを(ごく一部)読んだ

 

先ほどActiveDecoratorを使って定義したメソッド(を呼んでるモデルに定義したメソッド)をコントローラーで呼んだところ、エラーとなりました。

ActiveDecoratorをView以外で使う時は、ActiveDecorator のデコレーターメソッドをかましてあげる必要があるとのことでした。

 以下のように、ActiveDecorator::Decorator.instance.decorate( ) とメソッドを呼ぶインスタンスに処理を加えてあげると無事動いてくれました。

class AmountChecksController < ApplicationController

   略

private
def total_amount_sum(invoices)
invoices.map{|invoice| ActiveDecorator::Decorator.instance.decorate(invoice).total_amount_for_read}.sum
end
end

 

 

この処理が何をしているのか気になったため、定義元をみてみました。

 

github.com

 

 

active_decorator/lib/active_decorator/decorator.rb の中にdecorate( ) メソッドがあり、定義は以下のようになっておりました。


def
decorate(obj)
return if defined?(Jbuilder) && (Jbuilder === obj)
return if obj.nil?

if obj.is_a?(Array)
obj.each do |r|
decorate r
end
elsif obj.is_a?(Hash)
obj.each_value do |v|
decorate v
end
elsif defined?(ActiveRecord) && obj.is_a?(ActiveRecord::Relation)
# don't call each nor to_a immediately
if obj.respond_to?(:records)
# Rails 5.0
obj.extend ActiveDecorator::RelationDecorator unless obj.is_a? ActiveDecorator::RelationDecorator
else
# Rails 3.x and 4.x
obj.extend ActiveDecorator::RelationDecoratorLegacy unless obj.is_a? ActiveDecorator::RelationDecoratorLegacy
end
else
if defined?(ActiveRecord) && obj.is_a?(ActiveRecord::Base) && !obj.is_a?(ActiveDecorator::Decorated)
obj.extend ActiveDecorator::Decorated
end

d = decorator_for obj.class
return obj unless d
obj.extend d unless obj.is_a? d
end

obj
end

 

引数のオブジェクトがArrayならeachで取り出して再度1つずつdecorateメソッドを呼び、

Hashならeach_valueでバリューを取り出して1つずつdecorateメソッドを呼んでおります。

 

そして必ずオブジェクトを返すように、様々な条件分岐させてモジュールを生やしておりました。

 

 

Viewだとdecorate( ) メソッドを呼ばなくてもActiveDecoratorを使えるようになってるのはどうやっているのだろうと思い、そのほかのファイルものぞいてみたのですが、難しかったのでまた後日チャレンジしてみようと思います。。。!!