在 Rails 3 应用程序中,我们有一个高度规范化的数据库模式,出于多种原因,这是必要的。此外,我们需要提供一些只读 RESTful 路由,其虚拟资源来自多个模型的“组合”(非规范化)数据,我们必须将结果呈现为 JSON 文档。
例如,我们会有像州、城市和邻里这样的模型,每个模型都有自己的数据和关联。“RESTful 资源”是 Neighborhood,但我们总是希望包含关联的州和城市的名称。因此,对 URI“” 的“GET”请求/neighborhood/nm/albuquerque
将返回一个包含新墨西哥州阿尔伯克基所有社区的 JSON 数组,例如:
[{"state":"NM","city":"Albuquerque","neighborhood":"North Valley"},
{"state":"NM","city":"Albuquerque","neighborhood":"Northeast Heights"}, //... ]
但是,在 URI (" ") 中省略城市名称GET /neighborhood/nm
将返回新墨西哥州所有城市中所有社区的列表。
在这种情况下生成数据库查询的 Rails 3 首选方法是什么?
我能想象的最直接的方法是生成一个自定义 SQL 查询,该查询从数据库中选择必要的数据并将结果记录作为 JSON 返回,而不执行任何 ActiveRecord 对象反序列化(因为我们只需要未经处理的原始数据),例如:
def neighborhood # our Action in the target Controller...
state, city, hood = params[:state], params[:city], params[:hood]
query = <<-__HERE__
SELECT s.name AS state, c.name AS city, n.name AS neighborhood
FROM states AS s, cities AS c, neighborhoods AS n
WHERE n.city_id=c.id AND c.state_id=s.id
__HERE__
query += ' AND s.slug=' + ActiveRecord::Base.sanitize(state) if state
query += ' AND c.slug=' + ActiveRecord::Base.sanitize(city) if city
query += ' AND n.slug=' + ActiveRecord::Base.sanitize(hood) if hood
query += ' ORDER BY state, city, neighborhood ASC'
render :json => ActiveRecord::Base.connection.select_all(query)
end
这个解决方案在概念上很简单,并且依赖于数据库来完成繁重的工作,但感觉明显不像 Rails。我尝试使用 Arel/AR 查询和“as_json”覆盖的组合来实现相同的效果,但经过一段时间和挫折后,我似乎无法正确(和高效)。
我是否在 Rails 3 中遗漏了一些重要的、新的和很酷的东西,或者这只是一种快速而肮脏的解决方案是正确的方法的情况?