2012-05-24 137 views
3

我有一個相當安靜的API,但我正在努力研究如何幹淨地實現搜索。我希望能夠搜索兩個日期時間之間的所有記錄,日期時間允許相距最多6個小時。在我的控制方法的時刻,我有以下幾點:Rails驗證搜索參數

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是相當類似。

我知道這是違反在控制器中進行驗證的最佳做法,但我無法看到如何將其添加到模型中。

+0

我喜歡這個問題,但我不明白是什麼阻止你將所有的代碼('unprocessable_entity'除外)移動到模型中。還要注意''check_required_pa​​rams''可以使用數組交點來簡化很多,不需要循環。 – tokland

+0

@tokland好吧,我可以做到這一點。我想我希望我可以使用內置的Active :: Model驗證。 – Mike

回答

5

其實你正在做的事情是(幾乎)best practice,並將(幾乎)與strong parametsers合併到Rails 4中。 (我之所以這麼說,幾乎是因爲你的check_max_time看起來應該是你的模型中的一個驗證。)

你應該繼續前進,並在今天推出該功能,並使自己的升級更容易。強大的參數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 
+0

好像你的'registration_id'是一個字符串而不是散列。像這樣重寫它:'params [:user]。要求(:registration_id); params [:user] .permit(:device_name,:os_type)'。強參數的工作方式已經改變。 – mwoods79

0

那麼,在這種情況下我會做的是設置這兩個日期時間之間的默認值,這樣我就不必進行驗證並引發異常。

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嘗試分配默認值,如果它們不是從客戶端發送的。它所做的最後一件事是將params[:end_time]分配到最大值。

它非常整潔,因爲我們不需要進行驗證,客戶端也不需要處理不同的響應代碼,如422。你應該有一個API文檔,說明這個事實。

+0

驗證日期的情況最多隻能相隔6小時? – Mike

+0

我剛更新了我的答案。 – Chamnap

+0

感謝您的回答。我想我寧願返回422 ......否則它可能會爲使用該API的人返回意想不到的結果。 – Mike

1

從來沒有找到一個乾淨的答案。但是,如果您使API Grape具有內置的參數驗證和強制功能來處理它。