Tom Brunoli
Tom Brunoli

Reputation: 3466

Rails auto convert query string params to integers

I'm trying to implement a form of pagination using limit and offset query parameters. Is there a way to make sure the values are integers otherwise throw a 400 error, perhaps by using strong_parameters? It seems like the sort of thing that would be built in to rails, but I can't find anything.

I could just manually convert the query parameters, but I'd rather use something a bit more bullet proof if possible.

Upvotes: 18

Views: 27292

Answers (3)

Owen Peredo Diaz
Owen Peredo Diaz

Reputation: 154

Try this: Repair numeric param values converted into string

repair_nested_params({id: '11', age: '25'}) # Sample

def repair_nested_params(obj)
  obj.each do |key, value|
    obj[key] = parse_string(value)
  end
end

def parse_string(value)
  return repair_nested_params(value) if value.is_a?(Hash)
  return value.map(&method(:repair_nested_params)) if value.is_a?(Array)
  return value unless value.is_a?(String)

  is_numeric = value.match?(/\A[-+]?\d*\.?\d+\z/)
  return value unless is_numeric

  (value.to_f % 1).positive? ? value.to_f : value.to_i
end

Upvotes: 3

Satya Kalluri
Satya Kalluri

Reputation: 5214

You basically need to convert your parameters manually. Ideally, abstract this into a controller-method to keep your actual method clean.

Class SomeController < ActionController
  before_filter: cleanup_pagination_params

  def cleanup_pagination_params
    params[:offset] = params[:offset].to_i
    params[:limit]  = params[:limit].to_i
  end

  # Your regular controller methods here
end

Upvotes: 4

GladstoneKeep
GladstoneKeep

Reputation: 3972

Like the commenter @Litmus above, I would recommend using a Ruby gem such as kaminari to manage pagination.

But if you're set on rolling your own, and you're concerned about input sanitization, the simplest method to ensure the "offset" and "limit" parameters are integers might be a filter in your controller:

class YourController < ApplicationController

  before_filter :sanitize_page_params

  # ... other controller methods ...

  private

  def sanitize_page_params
    params[:offset] = params[:offset].to_i
    params[:limit] = params[:limit].to_i
  end

  # ... etc. ...

end

Note that strings such as "foo" will be converted to 0.

Upvotes: 25

Related Questions