Railsvalidation搜索参数

我有一个非常安静的API,但我正在努力研究如何干净地实现搜索。 我希望能够在两个日期之间搜索所有记录,日期时间最多允许间隔6小时。 在我的控制器方法中,我有以下内容:

required_params = [:start_time, :end_time] if check_required_params(required_params, params) and check_max_time_bound(params, 6.hours) ... rest of controller code here ... end 

check_required_pa​​rams是一个如下所示的应用程序方法:

 def check_required_params(required_params, params_sent) required_params.each do |param| unless has_param(param, params_sent) unprocessable_entity return false end end true end 

check_max_time非常相似。

我知道在控制器中进行validation是违反最佳做法的,但我看不出如何干净地将它添加到模型中。

实际上你正在做的是(差不多) best practice并且(几乎)将在Rails 4中加入strong parametsers 。 (我说几乎是因为你的check_max_time看起来应该是你模型中的validation。)

您应该继续使用今天的function,让自己更容易升级。 强参数https://github.com/rails/strong_parameters

文档是存在的,但这里是你如何合并它。

 class SearchController < ApplicationController include ActiveModel::ForbiddenAttributesProtection def create # Doesn't have to be an ActiveRecord model @results = Search.create(search_params) respond_with @results end private def search_params # This will ensure that you have :start_time and :end_time, but will allow :foo and :bar params.require(:start_time, :end_time).permit(:foo, :bar #, whatever else) end end class Search < ActiveRecord::Base validates :time_less_than_six_hours private def time_less_than_six_hours errors.add(:end_time, "should be less than 6 hours from start") if (end_time - start_time) > 6.hours end end 

从来没有找到一个干净的答案。 但是,如果您正在制作API, Grape已经内置了参数validation和强制来处理它。

那么,在这种情况下我要做的是设置这两个日期时间之间的默认值,这样我就不必进行validation并引发exception。

 class SearchController < ApplicationController before_filter :assign_default_params def index end private def assign_default_params params[:start_time] ||= Time.now params[:end_time] ||= params[:start_time] + 6.hours params[:end_time] = params[:start_time] + 6.hours if ((params[:end_time] - params[:start_time]) / 3600).round) > 6 end end 

使用上面的代码,它始终具有搜索所需的参数。 如果不是从客户端发送, assign_default_params方法assign_default_params尝试分配默认值。 它做的最后一件事是它将params[:end_time]分配给最大值。

它更整洁,因为我们不需要进行validation,客户端不需要处理不同的响应代码,如422 。 你应该有一个API文档,说明这个事实。