Rails as_json 包含条件

Posted

技术标签:

【中文标题】Rails as_json 包含条件【英文标题】:Rails as_json includes with conditions 【发布时间】:2011-08-18 17:29:52 【问题描述】:

我无法通过动态属性限制 as_json 包含:

@pirates_ships = @current_account.pirates.as_json(:include => :ships => :only => [:id, :name], :only => [:id, :last_name])

这肯定给了我所有有船或没有船的海盗。

但我还需要限制船只,例如ship.ocean_id

我尝试通过包含条件来解决它:

pirates.includes(:ships).where("ships.ocean_id = ?", @ocean.id).as_json(...)

限制有效,但现在所有没有船的海盗都失踪了。

我自己的 JOIN 语法也没有运气。

有什么想法吗? 哎哟

更新

到目前为止,我的解决方案是手动预加载。这样我就可以拥有我的动态条件:

@pirates = @current_account.pirates
@ships = @current_account.ships.where(:pirate_id.in => @pirates, :ocean_id => @ocean.id)

render :json =>  :pirates => @pirates.as_json(...), :ships => @ships.as_json(...) 

我的 Ajax 回调现在可以遍历 :pirates 并为每个海盗添加他的船(如果有)。 (我使用 JS 模板引擎客户端从 JSON 响应生成视图)

不是很优雅,但对我来说性能很重要。

我仍然愿意接受更好的想法。 我试过动态 has_many :ships, :conditions => ... 但这有点繁琐。

【问题讨论】:

【参考方案1】:

我认为您最好的选择是在从 as_json 生成 @pirates_ships 哈希后更改它(我尝试了多种包含等变体,但无法正常工作)。

@pirates_ships = @current_account.pirates.as_json(:include => :ships)
@pirates_ships.each do |pirate|
  pirate[:ships].delete_if |ship| ship.ocean_id != @ocean.id 
end

# Now, @pirates_ships should contain ALL pirates, as well as ships for @ocean

【讨论】:

那行得通(投票赞成)。但是想象一下一个拥有数千艘船只并且仍在增长的海盗世界。我的大副每次必须报告单个海洋时都需要计算所有海洋上的所有船只……这将在我们的 sql 地图上造成性能损失;-) 从一开始我就更喜欢干净的地图。跨度> 啊!我仍然无法投票,作为新手,我缺少 15 名声望。对不起!! 绝对没有优化。我以前在我的一个项目中遇到过类似的问题,并且没有一次手动生成所有 JSON 一条记录,我无法想出一个好的方法来做到这一点。幸运的是,我的数据库相对较小,因此对数组的迭代对我来说效果很好。

以上是关于Rails as_json 包含条件的主要内容,如果未能解决你的问题,请参考以下文章

Rails - 验证:如果一个条件为真

Rails 模型中的条件回调?

Rails - 条件 html 属性

Ruby/Rails - 为啥自我关联条件取决于创建时间?

Rails ActiveRecord 条件

基于条件的Rails关联查询