api-pagination icon indicating copy to clipboard operation
api-pagination copied to clipboard

undefined method `to_i' for #<ActionController::Parameters:0x00007fec23852f70

Open belgoros opened this issue 5 years ago • 5 comments

I'm using 4.8.2 version of api-paginationwith Rails API 5.2.2 and will_pagiante gem. Here is the links generated in the JSON response:

..
"links": {
    "self": "http://localhost:3000/api/countries/be/addresses?page%5Bnumber%5D=1&page%5Bsize%5D=30",
    "first": "http://localhost:3000/api/countries/be/addresses?page%5Bnumber%5D=1&page%5Bsize%5D=30",
    "prev": null,
    "next": "http://localhost:3000/api/countries/be/addresses?page%5Bnumber%5D=2&page%5Bsize%5D=30",
    "last": "http://localhost:3000/api/countries/be/addresses?page%5Bnumber%5D=2&page%5Bsize%5D=30"
  }

When I tried to hit manually the next link URL as follows:

http://localhost:3000/api/countries/be/addresses?page[number]=2&page[size]=30

it fails to respond and returns the following error:

Started GET "/api/countries/be/addresses?page[number]=2&page[size]=30" for 127.0.0.1 at 2019-03-01 15:28:42 +0100
Processing by V1::Api::AddressesController#all_by_country as */*
  Parameters: {"page"=>{"number"=>"2", "size"=>"30"}, "country_code"=>"be"}
  Country Load (0.5ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."code" = $1 LIMIT $2  [["code", "BE"], ["LIMIT", 1]]
+++++ <ActionController::Parameters {"page"=>{"number"=>"2", "size"=>"30"}, "controller"=>"v1/api/addresses", "action"=>"all_by_country", "country_code"=>"be"} permitted: false>
   (1.3ms)  SELECT COUNT(*) FROM "addresses" INNER JOIN "shops" ON "shops"."id" = "addresses"."shop_id" INNER JOIN "countries" ON "countries"."id" = "shops"."country_id" WHERE "countries"."code" = $1  [["code", "BE"]]
Completed 500 Internal Server Error in 4ms (ActiveRecord: 1.8ms)


  
NoMethodError (undefined method `to_i' for #<ActionController::Parameters:0x00007fec231c37e0>
Did you mean?  to_s
               to_h):
  

As you see I'm getting a Hash in params:

 Parameters: {"page"=>{"number"=>"2", "size"=>"30"}, "country_code"=>"be"}

Here is the corresponding controller action:

def all_by_country
    @addresses = Address.all_by_country(@country.code)
    paginate(
       json: @addresses,
       include: ['shop', 'shop.country'],
       status: paginated_response_status(@addresses)
    )
end

What am I missing ? Thank you.

belgoros avatar Mar 01 '19 14:03 belgoros

The solution I came to and that worked for me was to create a api_pagination.rb file in config/initializers folder with the following settings:

ApiPagination.configure do |config|
  config.page_param do |params|
    params[:page][:number] if params[:page].is_a?(ActionController::Parameters)
  end
    
  config.per_page_param do |params|
    params[:page][:size] if params[:page].is_a?(ActionController::Parameters)
  end
end

Is it correct ? If so, it is alittle bit confusing, because Configuration section in README says it to be optional.

belgoros avatar Mar 01 '19 14:03 belgoros

Hmm that seems wrong to me. By default, the params would be page and per_page, not page[number] and page[size]. Are you sure you didn't have this configured already?

davidcelis avatar Mar 01 '19 20:03 davidcelis

What does paginated_response_status do?

davidcelis avatar Mar 01 '19 20:03 davidcelis

paginated_response_status is just a helper defined in controllers/concerns/response.rbas follows:

module Response
  extend ActiveSupport::Concern
...
  def paginated_response_status(collection)
    collection.size > WillPaginate.per_page ? :partial_content : :ok
  end
end

It does not matter. I created a separate repo to reproduce the issue. Take a look at README for setup details, it is pretty basic but raises the same problem.

Regards

belgoros avatar Mar 03 '19 16:03 belgoros

Thanks, I'll take a look as soon as I'm able to.

davidcelis avatar Mar 04 '19 18:03 davidcelis