假设以下关系:
Blog
has_many Posts
has_many Comments
has_oneAuthor
如果我想Blogs
全力以赴Posts
,我可以写:
Blog.all.as_json(:include => :posts)
但是,这将导致 N+1 查询。
所以我需要写:
Blog.includes(:posts).all.as_json(:include => :posts)
它按预期工作,但不是很干燥,特别是当您嵌套包含时。
例如:
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()
关系哈希放在第二个类方法中,但是有两个方法声明相同的包含结构并不是 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
格式使用时,它会变得复杂。
我怎样才能干燥这些包括,最好只声明一次关系格式?
也许有一些方法可以利用命名范围或一些宝石?
任何帮助是极大的赞赏。