Rails 3 アプリケーションには、高度に正規化されたデータベース スキーマがあり、これはさまざまな理由で必要です。さらに、仮想リソースが複数のモデルからの「結合された」(非正規化された) データから派生した読み取り専用の RESTful ルートをいくつか提供する必要があり、結果を JSON ドキュメントとして提示する必要があります。
たとえば、State、City、Neighborhood などのモデルがあり、それぞれに独自のデータと関連付けがあります。「RESTful リソース」はネイバーフッドですが、関連する州と都市の名前を常に含めたいと考えています。したがって、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の推奨アプローチは何ですか?
私が想像できる最も直接的なアプローチは、データベースから必要なデータを選択し、結果のレコードを JSON として返すカスタム SQL クエリを生成することです。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 で大きく、新しく、クールなものを見逃しているのでしょうか?それとも、これは単純なソリューションが適切な方法であるという状況にすぎないのでしょうか?