On this platform I am working with there is a case of automatic requests that are not something we can do much about. But they send requests as
https://www.example.com/articles?page=2%27A=0
and this causes an error on the side of the platform. This gets logged, an email is send it is monitored as an error, but it is not an error for the platform and the platform should just show page=1
The page is not a number. Where do you check that the page is a number and convert it to 1?
In different cases and platforms I have:
Made the check in a concern that is then included in all controllers
Passed the @articles.paginate(page: params[:page]) to the model and the model is doing the check and then I extract this into a concern for all models.
I once had to make this check in rack even before the controller gets hit so that every “page” is automatically converted to a number if it is not a number.
My question is - where do you do it? Why you’ve decided to do it there?
What would happen if you just cast the param to an integer? @articles.paginate(page: params[:page].try(:to_i)). Also, which pagination system are you using? I have never seen this blow up for me when I use Kaminari, so maybe it’s doing something with that attribute before it tries to calculate the offset.
Yes, params[:page].try(:to_i) is one option. But I need a more complex logic like converting it to one and this will be the same call for all index and it makes sense to have it in a concern that does this.
And this is option 1 from the question - extract the logic to a controller concern
The code for converting the param into a number seems trivial - i’d just put params[:page].to_i into something reusable like a helper or controller concern.
What that number needs to default to is a different issue - I’d duplicate the logic in the controller action if different endpoints have different defaults.
The code itself is trivial. Question is where do you put it. As I understand it you would put it in a controller concern and add this concern to all the controllers.
Sorry for not answering your question, but wanted to remark, that now that will_paginate is officially in maintenance mode it is about time to switch to another solution. I’ve refactored an app from will_paginate to pagy, which is more modern, faster and more powerful. The pagy site has a migration guide, it was not much work.
With pagy you will face a similar issue. There I solved it by adding this method to my ApplicationController
def page
p = params[:page].to_i # converts strings to 0 (or the number they start with)
p.positive? ? p : 1 # when no valid page number is given, set page to 1
end
I ran into this issue just yesterday with Pagy. In my case, Pagy was raising an error if the page number was out of bounds. This was happening because a search engine crawler was hitting page numbers that no longer exist. It also raises for non-numeric page numbers.
Pagy seems to be of the opinion that methods should raise errors unless you give them exactly the arguments that are expected. This seems contrary to the Rails Way. Ruby itself, for example, returns nil rather than raise for a=[1,2,3]; a[5].
This is exacerbated by the fact that, unlike Kaminari, Pagy accesses params[:page] behind the scenes so there is no opportunity to restrict the input; the only option is to rescue.
What do you mean by modern and faster? How can pagy be faster than will_panigate - for example? Both pagy and will_paginate are sending a request with limit and offset - right?
Overflow only handles numbers larger than the amount of pages. To deal with invalid input, see my little snippet (in the post above) where I define my own page method in the ApplicationController to ensure I always have a positive number as page parameter.
pagy seems to do much less (instantiating less classes, consuming less memory) than the other gems. But when I say “faster” I relied on their own benchmarking:
As I reported the issue with will_paginate, the gem maintainer set the gem to maintenance mode.
So this turned out to be a greater question and I have scheduled it for next few weeks to migrate to kanimari (for example). I am not sure if I will find an answer there, I will have to check.
This is exacerbated by the fact that, unlike Kaminari, Pagy accesses params[:page] behind the scenes so there is no opportunity to restrict the input; the only option is to rescue.
Not really. That automatic handling of the prams[:page] is just for your convenience. You can always exlicitly pass page: params[:page].to_i or whatever to the pagy method and it will not try to find it in the params. FYI, you can also explicitly pass any other variable that you want to override.