Reputation: 303
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
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
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
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