Sina
Sina

Reputation: 303

Validate url params not in model in Rails 4

What is the best way to validate url params that are not in the model.

Specifically I have a route like below:

get 'delivery_windows/:date',
        to: 'delivery_windows#index',
        :constraints => { :date => /\d{4}-\d{2}-\d{2}/ },
        as: :delivery_windows

I want to make sure that :date is a valid date and regex is not a solution. the date cant be in the past and not more than 3 months into the future.

Thank you in advance

Upvotes: 4

Views: 524

Answers (3)

Sina
Sina

Reputation: 303

Thanks to theunraveler and sadaf2605 for their responses.

I ended up doing to combination of their suggestions by using the before_action and raising a routing error in there.

in my controller I added:

class AngularApi::V1::DeliveryWindowsController < ApplicationController
  before_action :validate_date_param, only: :index

  def index
    ...
  end

  private

  def validate_date_param
    begin
      Date.parse(params[:date])
    rescue ArgumentError
      render json: [{
        param: :date,
        message: "Incorrect Date Format: Date format should be yyyy-mm-dd."
      }].to_json, status: :unprocessable_entity
      return
    end
  end
end

Upvotes: 3

sadaf2605
sadaf2605

Reputation: 7540

Well you can filter your date at controller, and raise 404 not found when you get date that does not fulfil your requirement.

def show
    date=params[:date].strftime("%Y-%m-%d').to_date
    if date > 0.day.ago or date > 3.month.from_now
        raise ActionController::RoutingError.new('Not Found')
    end
end

Upvotes: 0

theunraveler
theunraveler

Reputation: 3284

While I'm not sure that I would handle this in the routing layer myself, you should be able to use Advanced Routing Constraints for this.

The idea is that constraints can accept an object that responds to matches?. If matches? returns true, then the constraint passes, otherwise, the constraint fails. A simple implementation of this would be the following:

In your config/routes.rb, including something like this:

require 'routing/date_param_constraint'

get 'delivery_windows/:date',
    to: 'delivery_windows#index',
    constraints: DateParamConstraint,
    as: :delivery_windows

Then, somewhere in your application (perhaps in lib/routing/date_param_constraint.rb), define a class like the following:

module DateParamConstraint
  def matches?(request)
    # Check `request.parameters[:date]` to make sure
    # it is valid here, return true or false.
  end
end

Upvotes: 3

Related Questions