はじめに
Ransackは、複雑な検索機能でも簡単に作れるGemです。そして、ActionTextはRails6から導入されたリッチテキストを簡単に製作できる機能です。
RansackでActionTextの中を検索できないという記事がありましたが、どうやら検索できるようなので、記事を書こうと思いました。
注意
RansackやActionTextの導入は割愛させていただきます。
大事なところだけです。
また、恥ずかしながら私自身がRailsを勉強中なこともあり、完全に理解しれきていないと思いますので、他の記事でも調べて頂いた方がいいと思います。最大限頑張って説明させていただきます。
結論
Ransackで検索するためには、モデルにアソシエーションを追加する必要がありました。
結論としては、has_oneの行が必要ということです。
2つ同じ指定のように思えますが、片方が読み書き用で、片方が検索用と考えてもらうといいと思います。
class Message < ApplicationRecord
has_rich_text :content
has_one :content, class_name: 'ActionText::RichText', as: :record
end
<%= search_form_for @q, url: search_messages_path do |f| %>
<%= f.label :title_or_content_body_cont, 'テキスト検索' %>
<%= f.search_field :title_or_content_body_cont %>
説明
結論の例では、messageモデルに、「has_rich_text :content」でActionTextを紐付けています。
ここまではRailsガイドのとおりです。これがないとActionTextのデータが生成できません。
しかし、この「has_rich_text」に関しては、Ransack対応していないようです。
そのため、更にもう1行追加が必要です。
それが「has_one :content, class_name: 'ActionText::RichText', as: :record」です。
私は「class_name」と「as」は見慣れない記述だったので、Railsドキュメントを探したところ次のように記述がありました。
オプション | 説明 |
---|---|
class_name | 関連名と参照元のクラス名を異なるものにしたい場合に指定 |
as | ポリモーフィック関連を定義 |
class_nameで指定されたほうを見に行っているようです。
つまり、ActionText::RichTextクラスを参照しているようです。
asのポリモーフィック関連とは、テーブルのリレーションが直接接続されていないテーブルにアソシエーションを可能にすることができるようです。ただし、対象のレコードは「polymorphic: true」で生成されている必要があり、ActionText内のbelogns_toでも「polymorphic: true」の指定が必要になります。
確認してみると、ActionTextのマイグレーションファイルを見るとたしかにデフォルトで「polymorphic: true」が入っています。
class CreateActionTextTables < ActiveRecord::Migration[6.0]
def change
create_table :action_text_rich_texts do |t|
t.string :name, null: false
t.text :body, size: :long
t.references :record, null: false, polymorphic: true, index: false
t.timestamps
t.index [ :record_type, :record_id, :name ], name: "index_action_text_rich_texts_uniqueness", unique: true
end
end
end
また、RailsのGithubを確認すると、ActionText::RichTextクラスにて、recordのbelogns_toで「polymorphic: true」が指定されていることが確認できます。
(おそらくこのファイル)
module ActionText
class RichText < Record
self.table_name = "action_text_rich_texts"
serialize :body, ActionText::Content
delegate :to_s, :nil?, to: :body
belongs_to :record, polymorphic: true, touch: true
これらにより、(今回の例では)messageから、直接つながっていないaction_text_tablesにアクセスできるようになり、そのbodyを検索することが可能になりました。
参考
Go Rails / How do I search Action Text with Ransack?
GitHub rails/rails
Railsガイド
Railsドキュメント
Qiita / アソシエーションにおけるclass_nameの定義!
Qiita / Railsのポリモーフィック関連付けを理解する