3

私は基本的に Rails の経験がなく、プログラミングの方法を学んでいる友人を助けようとしていますが、SQL の経験は豊富で、Rails に単純な正しいことをさせるのに苦労しています。結合を使用してクエリを実行します。

私は2つのテーブルを持っていdrawingsますdrawing_types. には、列を持つ をdrawings指す外部キーがあります。これは明らかに、想像できる最も基本的な関係です。SQL では、すべての図面を正しいものにするには、次のようにします。drawing_typestype_descriptiontype_descriptions

SELECT d.*, dt.type_description FROM drawings as d
INNER JOIN drawing_types as dt ON dt.id = d.drawing_type_id;

これは、まさに私が欲しいものを返す単一の効率的な SQL クエリです。つまり、テキスト タイプの説明もある図面のリストです。

私の人生では、レールにこのような単一のクエリを生成して使用させることはできません。私ができる最善のことは、データベースに実行させるのではなく、コードで「結合」を実行していることを明確に示す2つのクエリを実行させることです。N+1 クエリを実行するのが好きな場合もあります!?!

モデルのコードは次のとおりです。

class Drawing < ActiveRecord::Base
  attr_accessible :image, :drawing_type_id
  belongs_to :drawing_type
end

class DrawingType < ActiveRecord::Base
  attr_accessible :type_description
  has_many :drawings
end

関連するコントローラーコードは次のとおりです。

@drawings = Drawing.includes(:drawing_type)

そして、ここにビューがあります:

<% @drawings.each do |drawing| %>
  <tr>
    <td><b><%= drawing.drawing_type.type_description %></b></td>

これにより、2 つの SQL クエリが生成されます。1 つは ondrawings.*で、もう 1 つはすべての説明を取得するためのものです。これらは明らかにコードで検索されます。をa に変更するincludesと、joins1+M+N 個の SQL クエリが実行されます (M = 図面タイプの数、N = 図面の数)!?!?!?!

これを使用して、正しい SQL 結合をログに出力することができます (ここから):

@drawings = Drawing.select("drawings.*, drawing_types.type_description").
     joins("INNER JOIN drawing_types ON drawing_types.id = drawings.drawing_type_id")

しかし、レールは結果の列を無視して、type_description結果を図面の配列としてのみ使用しているように見えるため、追加の M + N クエリを実行します!

これらのバリエーションはすべて、ページがそれらすべてに対して正しくレンダリングされるという意味で「機能」しますが、実行する必要がある単一の正しい SQL 結合と比較して、この単純なことを行うにはすべて間違った方法です。

これは、まったく退屈な Web サイト スキーマで見つかる可能性のある最も基本的な関係であるため、これを正しく行う簡単な方法が必要です。これを行う方法を理解できませんでした。

ありがとう、クリス

4

2 に答える 2

1

多くの場合、2 つのクエリを使用すると 1 つよりも速く実行されるため、この動作は意図的なものです。理由の適切な説明については、この回答を参照してください: Rails で :include を使用して複数のクエリを回避するにはどうすればよいですか?

つまり、リレーションにwhere条件を指定して単一のクエリを強制することはできますが、お勧めしません。

于 2013-06-15T10:19:39.500 に答える