假设以下关系:
Blog
has_many Posts
has_many Comments
has_one Author
如果我希望全部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
时,它会变得复杂。
我如何干这些包括,最好只宣布一次关系格式?
也许有一些方法可以利用命名范围或某些宝石?
非常感谢任何帮助。
答案 0 :(得分:0)
您可以覆盖模型中的as_json
方法
例如
class Blog < ActiveRecord::Base
def as_json
super(:include => :posts)
end
end
然后你的控制器看起来像
render json: @blogs
<强>建议强>
您可以使用JBuilder,Rabl,AMS或其他模板库,这些模板库允许您将响应构建从控制器/模型逻辑中分离出来。这样做肯定会干掉你的代码。