No description provided.
per(0) should still returns scope / array with no elements
Well, I actually don't have any strong opinion whether per(0) should "not limit" or "limit 0", but why do you think it "should" return an empty list?
personally I think that this should not break chain of scopes and I think that this should reflect sql behavior.
So when you do a query with LIMIT 0 - empty result set is returned.
I don't think per should limit because it makes it impossible to calculate how many pages there are.
Let's say you have 100 records and call per(0), which is equivalent to limit(0). In this case, we will possibly encounter a "Division by zero" error.
I'm closing to avoid the division by zero error.
Hi, I agree with @gs that .per(0) should return 0 results. Zero means zero seems completely logical. My reason for wanting this is I have an API where the user can specify how many results they want (with an upper limit of course), but as that endpoint also returns metadata there are times when you want only the metadata and no actual content. Rather than making a separate API endpoint it makes sense to allow per(0). Furthermore, in the current implementation if a user supplies params[:per] = 0 then they could DOS your site as suddenly everything is returned. If you want all results then leave off the per or perhaps add another option of per(false) or per(:all). To patch my API quickly I've added this in a Rails initializer:
params[:per] = 0
if num.to_i <= 0
if limit_value == 0
If you would change your stance on this and consider my reasoning then I'd be happy to write a pull request, including prevention of divide by zero. Otherwise I'll just keep using my patch.
@sfcgeorge allowing per(0) (meaning limit(0)) would break almost all the helper methods as it would become impossible to calculate total_pages. total_pages shouldn't be 0 when it's actually incomputable (or mathematically infinity).
It makes sense per(0) returns an empty array but pagination is not only about models. If your API needs to return only metadata,
makes more sense to me.
@yuki24 Thank you for the fast and thoughtful comment. It's given me a lot to think about.
You are right about total_pages, making it 0 isn't right, and making it :infinity or something seems weird. I suppose you could also conceptualise it as if someone is hitting an endpoint designed to return something then they probably shouldn't ask for nothing. Moving all meta information into headers and issuing a HEAD for when that's all you want seems most 'correct'. So I think you're right and Kaminari shouldn't allow 0.
For my case I am very tempted to go down the HEAD route. However, due to caching and ETags even a HEAD request in Rails still hits the database. So, if the whole point of asking for just the headers is performance then HEAD doesn't actually help, unfortunately. Also forcing consumers to parse both headers and content to get what they need adds a fair bit of complexity. There are tradeoffs either way, but I think I'm going to go for simplicity over correctness and continue monkeypatching. I will keep re-evaluating though.
I still think 0 returning everything is a denial of service risk though and a really unexpected behaviour for the developer. Perhaps Kaminari should raise an exception instead.
So what if we make the following changes?
Maybe Kaminari::ZeroDivisionError isn't a good name though...
Ah actually that is quite a good way of improving it. By doing that, if someone wants to create an API that allows per(0) then instead of returning total_pages it can return total_items leaving the client to work out the paging.
How about Kaminari::ZeroPerDivisionError? It's a little more descriptive, though maybe it could be clearer. Kaminari::ZeroPerWithPagesError describes the reason more than the error operation. I'm not sure. Overall it sounds like a good way forward.