Reputation: 2082
If I do this:
@open_shops = Shop.includes(:opening_times).where("opening_times.day =?", today)
.order("opening_times.opens+opening_times.open_for")
@open_shops.size returns 10
If I do this:
@open_shops = Shop.includes(:opening_times).where("opening_times.day =?", today)
.order("opening_times.opens+opening_times.open_for")
.limit(2)
@open_shops.size returns 2, as expected. .limit(1) also works as expected.
But if I do this:
@open_shops = Shop.includes(:opening_times).where("opening_times.day =?", today)
.order("opening_times.opens+opening_times.open_for")
.limit(3)
@open_shops.size returns 2! As you can see above, 10 records are returned when there is no limit, but only 2 are returned with a limit of 3. With any limit from 3-10, it returns one less than it should. My mind is boggling.
Removing the where statement or the order statement makes limit work as expected.
EDIT: Perhaps worth noting that it isn't the same record missing each time. It's always the last one on the list that is missing. So limit(3) returns exactly the results that limit(2) should return for example.
These are my models:
class Shop
has_many :opening_times
end
class OpeningTime
belongs_to :shop
end
Upvotes: 2
Views: 638
Reputation: 31
I had a similar issue here.
Turned out the problem was in my development database data. I was also using includes
in my query and one of the entries had duplicated data on the included table, and it shouldn't have.
So, in your example, it would be like if you had two entries in opening_times
for one specific Shop
. When this specific Shop
is not included in the results, the query returns the right quantity of results. If you set limit to a higher number, it starts including this Shop
in the results and, as it is duplicated, it is counted but shown only once.
So the tip is: check if you have any duplicate entries in the table which is being included using includes
.
After I found and deleted this specific duplicate entry in my database table, everything worked as it should.
Upvotes: 0
Reputation: 5258
Don't know whether this might help or not at this point, or whether this was your actual problem but one case where limit(n)
returns less than n
records even if the expression being limited has n
or more records is when you have a counter cache incorrectly set.
For example,
class ParentThing
has_many :children_things
end
class ChildrenThing
belongs_to :parent_thing
end
In this case, with parent_things table having a children_thing_count
column,
ParentThing.find(1).children_things.size
will return whatever (correct or incorrect) it is in the children_thing_count
column whereas
ParentThing.find(1).children_things.limit(n).size
will always return the correct count expression over the table with the counter.
So, be very careful with counter cache's!!
Upvotes: 1
Reputation: 2082
Well. I had one shop that is closed all day on Saturday (the day I was querying for). I began to wonder if this record was acting as a "ghost" getting included in the query (even though it shouldn't) without actually returning. This would explain why the last record of each query was missing, because the ghost record was knocking it off the list.
So I tried making a dummy opening time for this shop. I had it open at 00:01 and stay open for one minute. Suddenly, everything worked! If that isn't already weird enough, I then deleted this dummy record, and it still worked.
I'm not accepting my own answer out of hope that someone can explain what on earth happened. At this point, demon possession and witchcraft appear like reasonable explanations.
Upvotes: 0