4

私はこんにちはと書いていますが、そうはさせないので、より長い文章を書きます:) ところで、こんにちは。

私のスコープが機能していないようです。

私はその範囲を書きました:

scope :ordered, ->(field, order) { except(:order).order("#{field} #{order}") }

ただし、SQL をチェックすると次のように返されます。

irb >p.levels.ordered("name", "ASC").to_sql
=> "SELECT \"levels\".* FROM \"levels\" WHERE (\"levels\".pie_id = 6 AND (\"levels\".\"parent_id\" = 0)) ORDER BY position ASC, name ASC"

注:position ASCそこにあるべきではありません

しかし、スコープの前を除いて追加すると機能します...

irb > p.levels.except(:order).ordered("name", "ASC").to_sql
 => "SELECT \"levels\".* FROM \"levels\" WHERE (\"levels\".pie_id = 6 AND (\"levels\".\"parent_id\" = 0)) ORDER BY name ASC" `

スコープで except は利用できますか? または、私を助けてくれるものはありますか?

ルビー 1.9.2p290

レール 3.0.14

どうも

4

3 に答える 3

3

を使用することで目標を達成できることは、おそらくすでにお気づきでしょうreorder。では、なぜreorder機能し、except機能しないのかについての私の理論を次に示します。

、などorderのメソッドは のインスタンスによって処理されますが、例などのスコープはのインスタンスによってモデル クラスに委任されることが重要です。whereexceptActiveRecord::RelationorderedActiveRecord::Relation

some_relation.order(:x)some_relationメソッドは、 のリストに:x追加されたの新しいコピーを返すだけですorder_values。同様に、with emptysome_relation.except(:order)のコピーを返します。一連の呼び出しがそのようなリレーション メソッドで構成されている限り、期待どおりに機能します。some_relationorder_valuesexcept

スコープがリレーションを返すラムダとして実装されている場合、スコープ メソッドの呼び出しは、scopedラムダによって返されるリレーションとによって返されるモデルのリレーションのマージで終了します。

scopes[name] = lambda do |*args|
  options = scope_options.is_a?(Proc) ? scope_options.call(*args) : scope_options

  relation = if options.is_a?(Hash)
    scoped.apply_finder_options(options)
  elsif options
    scoped.merge(options) # <- here options is what returned by your :ordered lambda
  else
    scoped
  end

  extension ? relation.extending(extension) : relation
end

これは、マージされるリレーションの 1 つに対してのみ行われた場合mergeの効果を保持しません。exceptと をマージするabb順序が設定されていませんが、設定されているa場合でも、結果には順序があります。reorderこれはトリックで回避できます:をどのように運ぶreorder_flagかを制御する特別なフラグをリレーションに設定します。mergeorder_values

これが私のテストサンプルです。私はdefault_scope注文をに注入するために使用していProduct#scopedます。Level#scopedあなたの例では、注文はおそらくの関連付けによって注入されます。Pieこれは のようになりhas_many :levels, :order => 'position'ます。

class Product < ActiveRecord::Base
  default_scope order('id DESC')
  scope :random_order, lambda {
    r = order('random()')
    puts "from lambda: " + r.order_values.inspect
    r
  }
end

# in console:

>> Product.scoped.order_values
=> ["id DESC"]

>> Product.random_order.order_values
from lambda: ["id DESC", "random()"]
=> ["id DESC", "id DESC", "random()"]

# now if I change the first line of lambda to
# r = except(:order).order('random()')

>> Product.random_order.order_values
from lambda: ["random()"]
=> ["id DESC", "random()"]

ご覧のとおり、順序Product.scopedがあるid DESCため、スコープによって返されるリレーションからクリアされたにもかかわらず、結果に表示されます。

関連するソースへのリンクのリストは次のとおりです。

于 2012-09-04T21:10:57.057 に答える
1

モデルで定義したスコープを追加

scope :ordered, ->(field, order) { except(:order).order("#{field} #{order}") }

さまざまな組み合わせを試し、すべてが機能する

a.inspection_serial_numbers.ordered('part_serial_number', 'DESC').except(:order).ordered('id', 'DESC').to_sql

=> "SELECT `inspection_serial_numbers`.* FROM `inspection_serial_numbers` WHERE  `inspection_serial_numbers`.`inspection_master_id` = 1 ORDER BY id DESC" 

a.inspection_serial_numbers.ordered('part_serial_number', 'DESC').except(:order).ordered('id', 'DESC').except(:order).ordered('is_active', 'ASC').to_sql

=> "SELECT `inspection_serial_numbers`.* FROM `inspection_serial_numbers`  WHERE `inspection_serial_numbers`.`inspection_master_id` = 1 ORDER BY is_active ASC" 

uが'ordered'スコープと'except'を任意の組み合わせで何度も組み合わせた場合でも、最後の'ordered'スコープが順序付けに使用されます

a.inspection_serial_numbers.ordered('part_serial_number', 'DESC').ordered('id', 'ASC').except(:order).ordered('id', 'DESC').to_sql

=> "SELECT `inspection_serial_numbers`.* FROM `inspection_serial_numbers`  WHERE `inspection_serial_numbers`.`inspection_master_id` = 1 ORDER BY id DESC" 

すべてのスコープを削除したい場合は、「スコープなし」を使用してください

a.inspection_serial_numbers.ordered('id', 'ASC').unscoped.ordered('part_serial_number', 'DESC').to_sql

=> "SELECT \"inspection_serial_numbers\".* FROM \"inspection_serial_numbers\"  ORDER BY part_serial_number DESC" 

http://apidock.com/rails/ActiveRecord/SpawnMethods/except および http://apidock.com/rails/ActiveRecord/Base/unscoped/classを参照 してください

于 2012-08-30T07:48:11.103 に答える
0

メソッドの順序が間違っている可能性があります。

それは書くべきですorder("#{field} #{order}").except(:order)

レールガイドを参照

于 2012-08-19T13:51:59.977 に答える