4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

active_decoratorはなぜアソシエーションまでデコレートできるのかを調べてみた

4
Last updated at Posted at 2025-12-02

日頃お世話になっているactive_decorator。とっても便利ですよね!
https://github.com/amatsuda/active_decorator

最近、以下のようにアソシエーションにもデコレーターが適用されることに気づきました。(神)

# コントローラー
@user = User.first

# ビュー
@user.posts.each do |post|
  post.decorated_method # アソシエーションも自動的にデコレートされる
end

なので今回はなぜアソシエーションにもデコレーターが適用できるのか仕組みを調べてみました。

どこでデコレーターが適用されているか

まず最初にrailsではControllerで定義されたインスタンス変数をView側に渡すためのhashを作成するview_assignsというメソッドがあります

  # actionpack/lib/abstract_controller/rendering.rb
  def view_assigns
    variables = instance_variables - _protected_ivars

    variables.each_with_object({}) do |name, hash|
      hash[name.slice(1, name.length)] = instance_variable_get(name)
    end
  end

(インスタンス変数名をキーにして値を詰めている。sliceしてるのはなんでだろうと思ったら”@”を消すためでした)

デコレーターの適用はこのview_assignsメソッドをオーバーライドして行われているようです。

# lib/active_decorator/monkey/abstract_controller/rendering.rb
def view_assigns
  hash = super
  hash.each_value do |v|
    ActiveDecorator::Decorator.instance.decorate v
  end
  hash
end

(decorateメソッドは今回の話からやや脱線するので省略しますが、配列やhashにも対応してくれており、再帰処理していて素敵なメソッドでした😃)
https://github.com/amatsuda/active_decorator/blob/master/lib/active_decorator/decorator.rb#L25

どこでアソシエーションにデコレーターを適用しているか

そして今回のきもとなる部分はAssociationのtargetのオーバーライドです。
このtargetがアソシエーションの実態らしいです🤔
ここでアソシエーションにデコレーターを適用していました。

# lib/active_decorator/monkey/active_record/associations.rb
module ActiveDecorator
  module Monkey
    module ActiveRecord
      module Associations
        module Association
          def target
            ActiveDecorator::Decorator.instance.decorate_association(owner, super)
          end
        end

decorate_associationでは親オブジェクトがデコレートされてる時だけデコレーターが適用されるようになっていました。これでViewでだけデコレーターが適用される仕組みみたいです。

# lib/active_decorator/decorator.rb
   def decorate_association(owner, target)
      (ActiveDecorator::Decorated === owner) ? decorate(target) : target
    end

というわけでアソシエーションにもデコレーターが適用されている仕組みがわかりました!
今回はCursorにざっくりと仕組みを聞いてから実装を辿るという方法で調べてみたのですが全体を把握してからコードを読めるのでわかりやすかったです。今後もGemのコードを読んだりするハードルが下がりそうと思いました!

4
0
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
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?