複数のモデルが入り混じったメンバに対してrenderメソッドを使うと、各モデルに適切なパーシャルを読んでくれる

  • 4
    Like
  • 0
    Comment
More than 1 year has passed since last update.

Railsガイドを眺めていたら、renderメソッドにcollectionを渡す場合に置いて以下のような興味深い記述があった。

使用するパーシャル名は、コレクション内のモデル名に基いて決定されます。実は、メンバが一様でない (さまざまな種類のメンバが入り混じった) コレクションにも上の方法を使用できます。この場合、コレクションのメンバに応じて適切なパーシャルが自動的に選択されます。

つまり、複数のモデルが混在したメンバに対して、以下の様にrenderメソッドを呼び出すことで、
それぞれのモデルに対応したパーシャルが自動的に選択されてレンダリングされるという事。

render @contents

たとえばQiitaのフィードの様な物を想定したとする。

サイト内の様々なユーザーが取るアクティビティを、Feedモデルに対応したfeedsテーブルに格納し、
それぞれのアクションに対応するモデルをFeedモデル継承させた(単一テーブル継承)させたモデルとして作成し、


class Feed < ActiveRecord::Base
  # 何らかの実装
end

class FeedPost < Feed
  # 何らかの実装
end

class FeedStock < Feed
  # 何らかの実装
end

それぞれ、app/views/feed_posts/_feed_post.html.erb, app/views/feed_stocks/_feed_stock.html.erbという、モデルに対応したパーシャルを作成しておき、controllerでおもむろにFeedモデルからデータを取得して、

class FeedsController < ApplicationController
  def index
    @feeds = Feed.all
  end
end

アクションに対応するViewテンプレートで、以下の様にrenderメソッドを呼び出すと、
感動的な事に、事前に用意したFeedPost, FeedStockのモデルに対応したパーシャルが呼ばれる。

# app/views/feeds/index.html.erb
<%= render @feeds %>

強い。

Railsの単一テーブル継承つかった場合、親モデルからActiveRecordのメソッド(where等)をつかってオブジェクトを取得すると、
以下のようにFeedモデルを継承したサブクラス(FeedPost, FeedStock)としてオブジェクトを取得することが出来るので、renderメソッドとの相性が非常に良い事がわかった。

> Feed.all
  => #<ActiveRecord::Relation [#<FeedPost id: 1, user_id: 1, content_id: 1, created_at: "2016-11-17 03:20:56", updated_at: "2016-11-17 03:20:56">, 
#<FeedStock id: 2, user_id: 1, content_id: 1, created_at: "2016-11-17 04:25:21", updated_at: "2016-11-17 04:25:21">]>