シングルテーブル継承のコレクションをrenderする
Railsには「設定より規約」の発想で、いろいろ便利な機能がありますが、複数組み合わせるとちょっと予想していなかった挙動をしました。
シングルテーブル継承とは
Rubyに限らず、オブジェクト指向プログラミングの上で継承は欠かせない仕組みですが、RDBMSと組み合わせるとなると少し複雑となってしまいます。
ただ、RailsのActiveRecordには標準で「シングルテーブル継承(STI)」という仕組みが用意してあって、
- テーブルは親クラスで定義して、すべての子クラスが同じ列を持つ
- (デフォルトでは)テーブルの
type
列を、子クラスの識別に使う1 - ActiveRecordからコレクションとして取ってきた時にも、きちんと子クラスとして取れる
という感じになります。
コード例
# マイグレーション
create_table :smart_phones do |t|
t.string :type
t.integer :storage
t.integer :frequency
t.string :maker
t.string :version
t.timestamps, null: false
end
# app/models/smart_phone.rb
class SmartPhone < ActiveRecord::Base
end
# app/models/i_phone.rb
class IPhone < SmartPhone
# 特有の処理も書ける
default_value_for(:maker) { 'Apple' }
end
# app/models/android_phone.rb
class AndroidPhone < SmartPhone
end
コレクションのrender
ビューで使うrender
にはいろんな機能がありますが、コレクションをまとめて表示することもできます。
たとえばDigitalBook
モデルに対して、コレクションの変数名をモデルのキャメルケース複数形(@digital_books
)としておけば、render @digital_books
と書くだけで、「@digital_books
の各要素を'digital_book'
というパーシャルで表示する。各要素はパーシャル内からdigital_book
として参照できる」という動作を実現してくれます。
STIコレクションをまとめてrender
STIのコレクションをまとめて表示するような場合、子クラス同士がSTIの性質上同じような構造となるので、「全部まとめて同じパーシャルでいい」というような場面もあるかもしれません(実際、そういう「よく似たもの同士」を入れるのに向いた構造ですし)。
実際に、上のSmartPhone
のようなデータ構造を作って、_smart_phone
パーシャルを用意した上でrender @smart_phones
としてみたところ、「_android_phone
のパーシャルが見つかりません」とエラーになってしまいました。どうやら、STIのコレクションをrender
すると、各クラスごとのパーシャルを呼んでくれるようでした。
ということで、全部同じでいいような場合は、render collection: @smart_phones, partial: 'smart_phone'
のように明示的に指定するのが必要だったようです。なお、「本来のモデルに合わせてリンク先を変えたい」ということなら、polymorphic_path
を使えば、モデルとアクションに合わせてアドレスを設定してくれます。
Author And Source
この問題について(シングルテーブル継承のコレクションをrenderする), 我々は、より多くの情報をここで見つけました https://qiita.com/jkr_2255/items/c20f5e64ed3bbc9cd19a著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .