次の関係を仮定します。
Blog
has_many Posts
has_many Comments
has_oneAuthor
Blogs
allですべてを取得したい場合は、次のPosts
ように記述できます。
Blog.all.as_json(:include => :posts)
ただし、これは N+1 クエリになります。
したがって、代わりに次のように書く必要があります。
Blog.includes(:posts).all.as_json(:include => :posts)
これは期待どおりに機能しますが、特にネストされたインクルードがある場合は、あまり DRY ではありません。
例えば:
Blog.includes(
:posts => {
:comments => :author
}
).all.as_json(
:include => {
:posts => {
:include => {
:comments => {
:include => :author
}
}
}
}
)
複数の場所で同じ JSON 形式を照会する必要がある場合、この問題はさらに悪化します。
as_json
次のように、リレーション形式をクラス メソッドに入れることを考えました。
class Blog < ActiveRecord::base
...
def self.include_all_json_format
:include => {
:posts => {
:include => {
:comments => {
:include => :author
}
}
}
}
end
...
end
これにより、複数の場所でこの JSON 形式をクエリする問題が解決されます。
Blog.includes(
:posts => {
:comments => :author
}
).all.as_json(
Blog.include_all_json_format
)
しかしもちろん、Blog.includes()
はリレーション ハッシュに別の形式をとるので、次のようになります。
Blog.includes(
Blog.include_all_json_format
).all.as_json(
Blog.include_all_json_format
)
うまくいきません。
Blog.includes()
リレーションシップ ハッシュを 2 番目のクラス メソッドに入れることもできますが、2 つのメソッドで同じ include 構造を宣言するのは DRY ではありません。
私が今考えることができる唯一のアイデアは、Blog.include_all_json_format
上記の方法を使用し、そのリレーションハッシュを(本質的にはキーBlog.includes()
を取り除くだけで)期待される形式に変換できるコンバーターメソッドを作成して、次のように呼び出すことです。:include
Blog.includes(
MyConverter(Blog.include_all_json_format)
).all.as_json(
Blog.include_all_json_format
)
:only
しかし、:except
自分のフォーマットで使用したい場合は複雑になりas_json
ます。
これらのインクルードを DRY するにはどうすればよいですか?
おそらく、名前付きスコープまたはいくつかの宝石を利用する方法はありますか?
どんな助けでも大歓迎です。