0

ドキュメントでは見つけられないように見えるレールでのこの動作に遭遇しました。

ActiveRecord クエリを複雑にして、基になる SQL を「複雑な」クエリ (以下を参照) にまとめると、関連付けで指定された順序が守られないように見えます。

これが私のモデル例です:

class Article < ActiveRecord::Base
  belongs_to :user
  has_many :categories, :order => :name
  attr_accessible :title, :user_id, :user
end

「単純な」クエリを実行すると、関連するカテゴリを名前順に並べて取得できます。

> Article.includes(:categories).first.categories.map &:name
  Article Load (0.1ms)  SELECT "articles".* FROM "articles" LIMIT 1
  Category Load (0.2ms)  SELECT "categories".* FROM "categories" WHERE "categories"."article_id" IN (11) ORDER BY name
 => ["category 3059", "category 3212", "category 3240", "category 3651", "category 4371", "category 5243", "category 6176", "category 6235", "category 6468", "category 654", "category 6804", "category 6892", "category 7026", "category 8929", "category 9653"]

カテゴリの名前が予想どおりの順序になっていることがわかります (注: データベースが文字列を順序付ける方法により、3 桁の番号付きカテゴリはアルファベット順になると予想されます)。

次の例は、順序付けに別の関連付け属性を使用した、より複雑なクエリです。

> Article.includes(:user, :categories).order('users.name').first.categories.map &:name
  Article Load (0.3ms)  SELECT DISTINCT "articles".id FROM "articles" LEFT OUTER JOIN "users" ON "users"."id" = "articles"."user_id" LEFT OUTER JOIN "categories" ON "categories"."article_id" = "articles"."id" ORDER BY users.name LIMIT 1
  SQL (0.2ms)  SELECT "articles"."id" AS t0_r0, "articles"."title" AS t0_r1, "articles"."user_id" AS t0_r2, "articles"."created_at" AS t0_r3, "articles"."updated_at" AS t0_r4, "users"."id" AS t1_r0, "users"."name" AS t1_r1, "users"."created_at" AS t1_r2, "users"."updated_at" AS t1_r3, "categories"."id" AS t2_r0, "categories"."name" AS t2_r1, "categories"."article_id" AS t2_r2, "categories"."created_at" AS t2_r3, "categories"."updated_at" AS t2_r4 FROM "articles" LEFT OUTER JOIN "users" ON "users"."id" = "articles"."user_id" LEFT OUTER JOIN "categories" ON "categories"."article_id" = "articles"."id" WHERE "articles"."id" IN (16) ORDER BY users.name
 => ["category 5023", "category 728", "category 3306", "category 8170", "category 5957", "category 7190", "category 4427", "category 3435", "category 1274", "category 7251", "category 7368", "category 682", "category 2918"]

ご覧のとおり、AR がクエリを「複雑な」SQL クエリの 1 つにまとめると、categories関連付けによって順序が失われます。

この動作は予期されたものですか? 私が見つけられなかったどこかに文書化されていますか?

ありがとう!

4

1 に答える 1

3

ここで重要なのは、結合を実行し、「users.name」で並べ替えているということです。

結合を行うときは、2つのテーブルをまとめます。順序は、結合されたテーブル全体に影響します。

とにかく2つのクエリを実行しているので、次のように記述します。

Article.includes(:user, :categories).order('users.name').first.categories.order(:name).map &:name

またはさらに良いことに、pluckメソッドを使用します。1つの列値のみを返します。

Article.includes(:user, :categories).order('users.name').first.categories.order(:name).pluck(:name)

そうすれば、名前を一覧表示するためにすべてのカテゴリ属性をロードする必要はありません。=)

PS:

二重注文を行う場合は、2つのパラメーターを渡して注文できます。

Article.includes(:user, :categories).order('users.name', 'categories.name')

何を回復しようとしているのか正確に理解できなかったため、クエリ全体を記述しませんでした。もっと説明していただければ、試してみることができます。これまで、名前で並べ替えられた最初のユーザーに属する記事のすべてのカテゴリを名前で並べ替えようとしていることを理解しました。しかし、私にとって、そのクエリはコンテキストなしではあまり意味がありません。

于 2012-08-22T15:55:12.197 に答える