2017-02-08 1 views
0

私は顧客に属する仕事を持っています。仕事は毎年再生成されます(ただし時には受け入れられません)。私は、次のことを決定するために仕事上のスコープを必要とする:Rails:同じ顧客レコードの過去の年が存在するレコードを検索するスコープ

class Customer < ApplicationRecord 
    has_many :jobs 
end 

class Job < ApplicationRecord 
    belongs_to :customer 

    self.new_job # => Customer has no jobs from previous years 
    where(customer.jobs.count == 1) # => Best guess/pseudocode 
    end 

    self.current # => Customer has a job from the previous year 
    where(
     customer.jobs.where("year >= ? and year <= ?", 1.year.ago, 2.years.ago).exists? 
    ) # => Best guess/pseudocode 
    end 

    self.lapsed # => Customer has jobs from previous years, but not last year 
    where(
     customer.jobs.not(:current).where(year >= 2.years.ago).exists? 
    ) # => Best guess/pseudocode 
    end 
end 

私は上記のこれらの例は、私が達成するために探しているかを説明することを願って/しようとしています。

私はしばらくこのことについて調査してきましたが、これをどうやって達成するかはまだできません。基本的には、同じ顧客からの過去の年のジョブが存在するかどうかに基づいてジョブを照会できるようにするスコープです。

私はジョブモデルで前年/後年のhas_many/belongs_to関係を追加する必要がありますか?代わりに顧客の仕事を照会できるので、別のデータベース列を追加する必要はないと思っていますか?

その後、私は存在を達成するために、このような何かを行うことができます(?):

includes(:previous_jobs).where(# more constraints).where.not(previous_jobs): { id: nil }) 

私は顧客IDのオフに基づいてbelongs_toの/にhas_many(?自己参照)以前の仕事をする、または希望でした私は外部キーを追加し、既存/次のジョブIDを既存のレコードに割り当てるためのスクリプトを書く必要がありますか?

+1

'.new'メソッドをスコープで上書きすることは本当に悪い考えです。 Rubyの '.new'は、常に新しいインスタンスを返すファクトリメソッドです。それ以外のことは、少なくとも驚きの原則に対する本当に悪い違反です。 – max

+0

うーん!良い点@max – gregblass

答えて

1

残念ながら、あなたのアプローチは間違っています - スコープCustomerは、Jobクラスではいけません。

class Customer 
    has_many :jobs 
    has_many :current_jobs, class_name: 'Job', 
    -> { where(created_at: 1.year.ago..Time.now) } 
    has_many :lapsed_jobs, class_name: 'Job', 
    -> { where('created_at >= ?', 1.year.ago) } 
end 

class Job 
    belongs_to :customer 
end 

これらはすべてがそうスキーマへの変更は必要ありません同じjobs.customer_id列を参照:あなたの代わりに何ができるか

は、スコープの関連付けを作成することです。お客様が作成していないジョブを取得するには

Customer.joins(:jobs) # only customers with jobs 
Customer.joins(:current_jobs) # has a job which is not older than a year 
Customer.joins(:lapsed_jobs) # has a job older than one year 

:あなたが結合テーブルに少なくとも一つの試合を持っている行のみが返されているのでカウントせずに、検索Customerレコードを制限することができLEFT INNER JOINを使用することにより

昨年はサブクエリでそれをやっていました:

Job.where.not(customer: Customer.joins(:current_jobs)) 
+0

私はこれを考えていましたが、ユースケースは: "前の年に同じ顧客からの仕事をしていないすべての仕事を与えてください" – gregblass

+0

そのユースケースはあなたのモデルでも意味をなさない仕事には仕事がありません - 顧客はそうします。 – max

+0

正確です。それは私の質問です。同じcustomer_idを持つことに基づいてジョブに他のジョブがある場合、どのようにして自己参照結合を設定できますか。 – gregblass

関連する問題