2015-04-25 35 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 

稍后如果您最终需要在几个地方使用这种逻辑,请将这些东西放在模块中,然后您可以将其包含在所需的控制器中。