2012-01-26 34 views
2

在Rails 3.1,鑑於這種模式:在其他方法中重複使用鋼軌範圍條件的DRY解決方案?

class Subscripion < ActiveRecord::Base 
    scope :active, lambda { 
     where("start_date is not ? AND end_date >= ?", nil, Date.today) 
    } 

    def active? 
     self.class.active.exists?(self) 
    end 
end 

到目前爲止,這是幹EST解決方案,我能想到的,因爲它不重複的條件在active?方法。

有兩個缺點,但:

  • 鑑於訂閱實例,就不需要數據庫查詢,以確定它是否處於活動狀態。我們可以根據它的屬性檢查:!start_date.nil? && end_date >= Date.today。撥打exists?會導致額外的數據庫查詢。
  • 如果在active範圍內調用exists?之前初始訂閱實例已更改,結果不是我們想要的,因爲exists?忽略實例並直接查詢數據庫。

關於更好的解決方案的任何想法,仍然定義在一個地方的條件?

回答

1

我相信積極?方法實現不好,因爲它會加載所有活動的訂閱,然後查看自己的列表。更好的方法是這樣的:

def active? 
    self.class.active.where(id: self.id).present? 
end 

此實現只使用COUNT查詢檢查數據庫。

在任何情況下,我相信這會對活動更有意義?方法與您已寫入的條件(!start_date.nil?& & end_date> = Date.today),因爲它是反映當前實例的真實狀態的唯一方法。

+0

如您所建議的那樣使用'where(id:self.id).present?'會稍微有效一些,但唯一的區別是它返回一個count而不是結果行的所有屬性。 但'存在?(self)'不*首先加載所有活動的訂閱。它運行幾乎相同的查詢,不同之處在於它不是'SELECT COUNT(*)'而是'SELECT 1 FROM ... LIMIT 1'查詢。 我同意使用'!start_date.nil? && end_date> = Date.today'對於'active?'方法是最正確的,但它確實定義了兩次相同的條件,這更容易出錯(將來)。 –

相關問題