2015-04-25 64 views
0

我有兩個模型的Rails 4應用程序。如何驗證子記錄的數量?

class User 
    has_many :bids 
end 

class Bid 
    belongs_to :user 
end 

用戶只能每週創建一個投標,所以我增加了以下至投標表

add_column :bids, :expiry, :datetime, default: DateTime.current.end_of_week 

及以下範圍至投標模型

scope :default, -> { order('bids.created_at DESC') } 
scope :active, -> { default.where('expiry > ?', Date.today) } 

我可以現在阻止用戶在控制器級別創建多個出價,如下所示:

class BidsController 
    def new 
    if current_user.bids.active.any? 
     flash[:notice] = "You already have an active Bid. You can edit it here." 
     redirect_to edit_bid_path(current_user.bids.active.last) 
    else 
     @bid = Bid.new 
     respond_with(@bid) 
    end 
    end 
end 

但是在模型層面驗證這一點的最佳方法是什麼?

我一直在嘗試設置自定義驗證,但我一直在努力查看最佳方法來設置此值,以使current_user可用於該方法。另外,我是否將錯誤添加到正確的對象?

class Bid 
    validate :validates_number_of_active_bids 
    def validates_number_of_active_bids 
    if Bid.active.where(user_id: current_user).any? 
     errors.add(:bid, "too much") 
    end 
    end 
end 

回答

0

爲了保持關注點分離,請關注current_user知識的莫del層。您的出價模型已具有user_id屬性。另外,我會添加一個這樣的錯誤,因爲驗證不會檢查出價上的「出價」屬性,而是整個出價可能無效。

class Bid 
    validate :validates_number_of_active_bids 
    def validates_number_of_active_bids 
    if Bid.where(user_id: user_id).active.any? 
     errors[:base] << "A new bid cannot be created until the current one expires" 
    end 
    end 
end 
0

這看起來應該是在協作者服務對象中。創建一個適當命名的新類(類似於ActiveBid,可能會考慮一些名稱)該類將使用current_user進行初始化,並返回活動出價或false。

這限制了邏輯這種限制成一個單一的位置(可能在未來一些計劃可具有2等

然後在控制器執行強制執行這個邏輯before_action。

before_action :enforce_bid_limits, only: [:new, create] 

private 

def enforce_bid_limits 
    active_bid = ActiveBid.new(current_user).call 
    if active_bid #returns false or the record of the current_bid 
    flash[:notice] = "You already have an active Bid. You can edit it here." 
    redirect_to edit_bid_path(bid) 
    end 
end 

稍後如果您最終需要在幾個地方使用這種邏輯,請將這些東西放在模塊中,然後您可以將其包含在所需的控制器中。