2014-01-25 95 views
0

我在用戶模型中具有以下關係。Rails - 與WHERE&ORDER的has_one關係?

has_many :subscriptions, dependent: :destroy 
has_one :subscription, -> { where 'end_date >= ?', Date.today } 

:訂閱實質上是他們最新的每月訂閱。 :訂閱是他們以前每月訂閱的一個數組(包括最新的)。他們列出了start_date,end_date,user_id,plan_id,payment_method。

訂閱計劃升級或降級時,我將當前訂閱的end_date更改爲Date.today(表示訂閱今天結束),然後創建一個新的訂閱,該訂閱從今天開始並在一個月內結束。

使End_date成爲Date.today的問題在於WHERE子句將選取已取消的訂閱和新的訂閱。但會贊成已取消的訂閱,因爲SQL查詢在ORDER BY類上生成了針對主要ID升序的粘性。

ORDER BY "subscriptions"."id" ASC LIMIT 1 

對於我的生活,我無法弄清楚如何扭轉ORDER BY從ASC到ID的DESC。但我更喜歡它根據created_at時間戳進行排序。以下是適用於排序的代碼,但除了ORDER BY子句之外,我還需要WHERE子句。

has_one :subscription, -> { order 'created_at desc' } 

有沒有人想過如何將兩者結合?

+1

你是否嘗試在ruby中對它進行排序而不是SQL? – hd1

+0

不,但如果Rails不允許在同一個has_one關係中組合where子句和order子句,這可能是所需的路由,這實際上令人驚訝。 –

回答

2

鐵軌4,Rails的自動ID,當你調用first方法添加的順序。 (您可以撥打take來避免這一點。)所以我猜has_one呼籲first內部。

由於has_one只是自動創建一個名爲subscription方法,爲什麼不自己建?:

def subscription 
    subscriptions.where('end_date >= ?', Date.today).order("created_at DESC").take 
end 

如果你不喜歡這樣,它不是從你的問題清楚你是否已經嘗試這個:

has_one :subscription, -> { where('end_date >= ?', Date.today).order("created_at DESC") } 

沒有理由不能連鎖這樣的兩個項目。但我記得Rails 4 first將覆蓋您的order指令並將其替換爲order(:id),所以這可能不起作用。您可以通過說@user.subscription.to_sql找到答案。

+0

將聲明鏈接到where聲明的工作,不知道你可以做到這一點。謝謝! –

0

的問題似乎是在到期訂閱和他們約會的「今天」,並指出只有一個預訂,則有一個結束日期> =今天之間設計不匹配。他們互相矛盾,所以你需要解決這個問題。

它的核心似乎是訂閱的開始日期是包含性的,結束日期是排他性的 - 除非您將結束日期定義爲「訂閱活動的最後日期」而不是「最後一天訂閱處於活動狀態的日期「,則您有兩個訂閱在同一天處於活動狀態。

+0

我誤以爲我希望它在end_date上排序,我的意思是created_at時間戳。我提供了一個使用模型範圍來實現我所需要的答案。在這種情況下可行,但不適用於其他人,具體取決於模型的需求。 –

0

除了建立一個自定義的方法來處理這個問題,而不是使用HAS_ONE關係,唯一的解決辦法,我可以在訂購查詢發現是通過設置範圍在訂閱模式通過created_at DESC訂購。

class Subscription < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :plan 

    default_scope order: 'created_at DESC' 


    #Subscription Load (0.2ms) SELECT "subscriptions".* FROM "subscriptions" WHERE "subscriptions"."user_id" = ? AND (end_date >= '2014-01-25') ORDER BY end_date DESC LIMIT 1 [["user_id", 2]]