在 rails 上与 ruby 具有多态关联的模型上验证时间重叠
Validate time overlap on a model with polymorphic associations with ruby on rails
我正在尝试在模型中创建一个验证(我认为实际上在数据库级别对其进行验证会更好)这样用户就无法购买和已经购买了 2 天间隔的商品( 2 天后 he/she 再次购买就可以了。
我有一个 "purchase" 操作的模型,每个购买操作都有一个关联的项目,名为 "purchasable"。此外,每个购买操作都有一个 user_id 关联。
我正在购买模型中这样尝试(但我的问题是我不知道如何正确编写此验证,甚至不知道如何检索 "purchasable.id" 或 "user.id"在编写验证方法时)
class Purchase < ApplicationRecord
belongs_to :purchasable, polymorphic: true
belongs_to :user
validates :price, presence: true
validate :no_purchase_overlap
def no_purchase_overlap
allPur = Purchase.includes(:purchasable).all
if allPur.where("created_at >= ? AND user_id = ? AND purchase_id = ?", (Time.now-2.days), user_id, purchasable.id)
errors.add(:date_end, 'it overlaps another purchase')
end
end
end
购买及其可购买看起来像:
irb(main):006:0> Purchase.first
Purchase Load (0.1ms) SELECT "purchases".* FROM "purchases" ORDER BY "purchases"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<Purchase id: 1, price: 0.299e1, quality: "SD", purchasable_type: "Season", purchasable_id: 9, user_id: 1, created_at: "2020-02-25 09:34:59", updated_at: "2020-02-25 09:34:59">
irb(main):007:0> Purchase.first.purchasable
Purchase Load (0.1ms) SELECT "purchases".* FROM "purchases" ORDER BY "purchases"."id" ASC LIMIT ? [["LIMIT", 1]]
Season Load (0.2ms) SELECT "seasons".* FROM "seasons" WHERE "seasons"."id" = ? LIMIT ? [["id", 9], ["LIMIT", 1]]
=> #<Season id: 9, title: "Brandy of the Damned", plot: "Here's looking at you, kid.", number: 1, created_at: "2020-02-25 09:34:17", updated_at: "2020-02-25 09:34:17">
现在它没有通过我的测试,似乎不允许保存任何购买:
it 'a movie can not be purchased by the same user more than once' do
purchase = Purchase.new(price: 2.99, quality: 'HD', purchasable: movie, user: user)
purchase_rep = Purchase.new(created_at: Time.now + 1.day ,price: 1.99, quality: 'SD', purchasable: movie, user: user)
expect { purchase.save }.to change { user.purchases.count }.by(1)
expect { purchase_rep.save }.to raise_error
end
失败信息:
失败:
1) Purchase When creating a purchase a movie can not be purchased by the same user more than once
Failure/Error: expect { purchase.save }.to change { user.purchases.count }.by(1)
expected `user.purchases.count` to have changed by 1, but was changed by 0
# ./spec/models/purchase_spec.rb:14:in `block (3 levels) in <main>'
解决了
def no_purchase_overlap
if Purchase.where("created_at >= ? AND user_id = ?", (Time.now-2.days), self.user.id).any?{|purchase| purchase.purchasable == self.purchasable}
errors.add(:date_end, 'it overlaps another purchase')
end
end
我正在尝试在模型中创建一个验证(我认为实际上在数据库级别对其进行验证会更好)这样用户就无法购买和已经购买了 2 天间隔的商品( 2 天后 he/she 再次购买就可以了。
我有一个 "purchase" 操作的模型,每个购买操作都有一个关联的项目,名为 "purchasable"。此外,每个购买操作都有一个 user_id 关联。
我正在购买模型中这样尝试(但我的问题是我不知道如何正确编写此验证,甚至不知道如何检索 "purchasable.id" 或 "user.id"在编写验证方法时)
class Purchase < ApplicationRecord
belongs_to :purchasable, polymorphic: true
belongs_to :user
validates :price, presence: true
validate :no_purchase_overlap
def no_purchase_overlap
allPur = Purchase.includes(:purchasable).all
if allPur.where("created_at >= ? AND user_id = ? AND purchase_id = ?", (Time.now-2.days), user_id, purchasable.id)
errors.add(:date_end, 'it overlaps another purchase')
end
end
end
购买及其可购买看起来像:
irb(main):006:0> Purchase.first
Purchase Load (0.1ms) SELECT "purchases".* FROM "purchases" ORDER BY "purchases"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<Purchase id: 1, price: 0.299e1, quality: "SD", purchasable_type: "Season", purchasable_id: 9, user_id: 1, created_at: "2020-02-25 09:34:59", updated_at: "2020-02-25 09:34:59">
irb(main):007:0> Purchase.first.purchasable
Purchase Load (0.1ms) SELECT "purchases".* FROM "purchases" ORDER BY "purchases"."id" ASC LIMIT ? [["LIMIT", 1]]
Season Load (0.2ms) SELECT "seasons".* FROM "seasons" WHERE "seasons"."id" = ? LIMIT ? [["id", 9], ["LIMIT", 1]]
=> #<Season id: 9, title: "Brandy of the Damned", plot: "Here's looking at you, kid.", number: 1, created_at: "2020-02-25 09:34:17", updated_at: "2020-02-25 09:34:17">
现在它没有通过我的测试,似乎不允许保存任何购买:
it 'a movie can not be purchased by the same user more than once' do
purchase = Purchase.new(price: 2.99, quality: 'HD', purchasable: movie, user: user)
purchase_rep = Purchase.new(created_at: Time.now + 1.day ,price: 1.99, quality: 'SD', purchasable: movie, user: user)
expect { purchase.save }.to change { user.purchases.count }.by(1)
expect { purchase_rep.save }.to raise_error
end
失败信息:
失败:
1) Purchase When creating a purchase a movie can not be purchased by the same user more than once
Failure/Error: expect { purchase.save }.to change { user.purchases.count }.by(1)
expected `user.purchases.count` to have changed by 1, but was changed by 0
# ./spec/models/purchase_spec.rb:14:in `block (3 levels) in <main>'
解决了
def no_purchase_overlap
if Purchase.where("created_at >= ? AND user_id = ?", (Time.now-2.days), self.user.id).any?{|purchase| purchase.purchasable == self.purchasable}
errors.add(:date_end, 'it overlaps another purchase')
end
end