Reputation: 1621
I have a Coupon class and I want my app to check and see how many counts are left on the coupon and if the date for the coupon has expired. I have the following method in my class to check both of these.
Coupon class
def self.get(code)
where(
:code => (normalize_code(code)),
:$and => [
{
:$or => [
{ :coupon_count.gte => 1 },
{ :coupon_count => nil }
]
}, {
:$or => [
{ :expires_at.gt => Time.now.utc },
{ :expires_at => nil }
]
}
]
).first
end
This works fine in development when I enter a coupon. But in production it does not work. I use my MongoDB shell to create a coupon as follows.
db.Coupon.insert({code:'#COUPONNAME',discount_percent: 10, expires_at: new ISODate("2016-05-18"), coupon_count: 10, "description": '1st cold visit sign-up'})
It seems that the problem is when the Coupon checks the expires_at date. In development it finds the coupon and works but in production it keeps not finding the coupon. Just for good measure here is my controller method for this.
EDIT I thought the issue was with the date but if I remove the date query it still does not work in production. I am confused why this wont work in production. It is using MongoDB 3.0.10 and mongoid 5.1.0 gem
charges_controller
@code = params[:couponCode]
if [email protected]?
@coupon = Coupon.get(@code)
if @coupon.nil?
flash[:error] = 'Coupon code is not valid or expired.'
redirect_to new_managers_charge_path(id: @reportapproval.id)
return
elsif @coupon.discount_percent == 100
@reportapproval.report_paid = true
@reportapproval.free_coupon_used = true
@reportapproval.save!
@coupon.coupon_count = @coupon.coupon_count - 1
@coupon.save!
redirect_to managers_dashboard_path, :notice => "You have successfully requested a pre-paid report from #{@reportapproval.tenant_last_name} with a 'No-Pay' intro coupon."
return
else
@final_amount = @coupon.apply_discount(@amount.to_i)
@discount_amount = (@amount.to_i - @final_amount.to_i)
end
Upvotes: 0
Views: 327
Reputation: 434615
If you have a Coupon
Mongoid model then the collection in the MongoDB shell would be db.coupons
. That would explain why:
db.Coupon.insert(...)
in the MongoDB shell isn't providing what you're expecting to find in your Rails code.
As far as Neil's comment about $exists
versus explicit nil
checks goes, I think you really do want nil
(AKA null
inside MongoDB) checks. Consider this in the MongoDB shell:
> db.models.insert({ n: 11 })
> db.models.insert({ n: 0 })
> db.models.insert({ n: null })
> db.models.insert({ })
> db.models.find()
{ "_id" : ObjectId("571546e1ce2934dadf379479"), "n" : 11 }
{ "_id" : ObjectId("571546e4ce2934dadf37947a"), "n" : 0 }
{ "_id" : ObjectId("571546e7ce2934dadf37947b"), "n" : null }
{ "_id" : ObjectId("571546ecce2934dadf37947c") }
So we have a collection with documents that have n
, don't have n
, have explicit null
values for n
, and non-null
values for n
.
Then we can see the difference between Mongoid queries like :n => nil
:
> db.models.find({ n: null })
{ "_id" : ObjectId("571546e7ce2934dadf37947b"), "n" : null }
{ "_id" : ObjectId("571546ecce2934dadf37947c") }
and :n.exists => true
(AKA :n => { :$exists => true }
):
> db.models.find({ n: { $exists: true } })
{ "_id" : ObjectId("571546e1ce2934dadf379479"), "n" : 11 }
{ "_id" : ObjectId("571546e4ce2934dadf37947a"), "n" : 0 }
{ "_id" : ObjectId("571546e7ce2934dadf37947b"), "n" : null }
and :n => { :$exists => false }
:
> db.models.find({ n: { $exists: false } })
{ "_id" : ObjectId("571546ecce2934dadf37947c") }
So the :expires_at => nil
queries will find documents which don't have an expires_at
as well as documents where expires_at
was explicitly set to nil
. Both those cases will happen with Mongoid unless you're careful to call remove_attribute
instead of assigning a nil
and both cases mean "no expiry date".
Upvotes: 2