2

私の User モデル クラスでは、以下に示すように 2 つのスコープを定義しました。

  scope :condition, lambda { where('updated_at >= ?', 3.day.ago) }

  scope :tardy, lambda {
    joins(:timesheets).group("users.id") & Timesheet.condition
  }

次に、リロードを実行してみました! 、その後u =User.find 14を実行すると、以下の結果が得られました。

  User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 14 LIMIT 1
 => #<User id: 14, login: "janu", password: "janu", password_confirmation: nil, email: "janu@gmail.com", created_at: "2013-01-03 09:47:36", updated_at: "2013-01-03 09:47:36"> 

次に、u.tardy.to_sqlを実行しますが、次のエラーが返されます。

NoMethodError: undefined method `tardy' for #<User:0x00000003cb5ea0>
    from /home/local/rajesh.co/.rvm/gems/ruby-1.9.3-p327/gems/activemodel-3.2.9/lib/active_model/attribute_methods.rb:407:in `method_missing'
    from /home/local/rajesh.co/.rvm/gems/ruby-1.9.3-p327/gems/activerecord-3.2.9/lib/active_record/attribute_methods.rb:149:in `method_missing'
    from (irb):64
    from /home/local/rajesh.co/.rvm/gems/ruby-1.9.3-p327/gems/railties-3.2.9/lib/rails/commands/console.rb:47:in `start'
    from /home/local/rajesh.co/.rvm/gems/ruby-1.9.3-p327/gems/railties-3.2.9/lib/rails/commands/console.rb:8:in `start'
    from /home/local/rajesh.co/.rvm/gems/ruby-1.9.3-p327/gems/railties-3.2.9/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

以下に示すように両方のスコープを結合すると、同じエラーが発生します。

  scope :tardy, lambda {
    joins(:timesheets).
    where("timesheets.updated_at >= ?", 3.days.ago).
    group("users.id")
  }

同じ問題を解決するのを手伝ってください。ありがとうございました。

4

2 に答える 2

4

特定のレコードでスコープを呼び出すことはできません。を呼び出す.findと、追加のスコープを連鎖できる関係/関連付けではなく、1 つの特定のレコードが返されます。

ID 14 の遅刻ユーザーを見つけたい場合は、メソッド呼び出しの順序を逆にする必要があります。

User.tardy.find(14)

レコードが 1 つになるため、まだを実行することはできません。.to_sql特定の ID による検索に対して SQL を本当に戻したい場合は、次を使用できます。

User.tardy.where(:id => 14).to_sql
于 2013-01-07T04:48:39.470 に答える
1

エラーはモデルのスコープ定義にあり、meagar の回答もエラーの 1 つに当てはまります。

  scope :tardy, lambda {
    joins(:timesheets).group("users.id") && Timesheet.condition
  }

上記では、タイムシートの更新時間に関してユーザーをグループ化する必要があるため、 User モデルではなくTimesheet モデル条件スコープを宣言する必要があるTimesheet.conditionを指定しました。したがって、以下のスコープは、以下のようにタイムシート モデルに存在する必要があります。

scope :condition, lambda { where('updated_at >= ?', 3.day.ago) }

User.tardyを実行すると、すべてのタイムシートが更新され、指定された条件を満たすユーザーが取得されます。

これを達成する2番目の簡単な方法は、ユーザーモデル自体で単一のスコープを定義することです:

scope :tardy, lambda {
    joins(:timesheets).
    where("timesheets.updated_at >= ?", 3.days.ago).
    group("users.id")
  }

ただし、このクロスモデル スコープは、適切なオブジェクト指向の設計原則に違反しています。これには、タイムシートが更新されるかどうかを判断するロジックが含まれています。これは、タイムシート クラスに適切に属するコードです。したがって、最初の方法が望ましいです。

皆さん、ありがとうございました。

于 2013-01-07T06:14:44.357 に答える