2012-12-05 40 views
1

此代碼感覺不對。我試圖讓我的控制器很瘦,我覺得控制器操作中有太多的邏輯。如何重構構建活動記錄搜索哈希的控制器操作

組織這段代碼會更好嗎?

def search 
    where_obj = {:status => 1} 

    if params[:city].present? 
     where_obj.merge! :city => params[:city] 
    end 

    if params[:county].present? 
     where_obj.merge! :county => params[:county] 
    end 

    ## THERE WILL BE MANY MORE IF STATEMENTS HERE DUE TO GROWING SEARCH FORM 

    @person = Person.where(where_obj) 
end 

隨着搜索表單增長這個控制器的動作也將增長。我怎樣才能保持我的控制器瘦?

回答

2

如何:

def search 
    query = { :status => 1 }.merge(params.select { |k,_| [:city, :country].include?(k) }) 
    @person = Person.where(query) 
end 

或者使用ActiveSupport提供(用Rails)的slice方法有點簡單的版本:

def search 
    query = { :status => 1 }.merge(params.slice(:city, :country)) 
    @person = Person.where(query) 
end 

如果你將有很多不同的PARAMS以選擇性包括,那麼你可以像這樣對它們進行分組:

def search 
    search_params = [:city, :country, :continent, ...] 
    query = { :status => 1 }.merge(params.slice(*search_params)) 
    @person = Person.where(query) 
end 

(感謝@ajcodez傳遞給slice時指出對search_params一個圖示的需要。)

+1

這將包括值不管它們是否存在與否,這也不是什麼OP的代碼在做什麼。 – sawa

+0

的確,我想我們以不同的方式解釋了這個問題。 –

+0

你的第一個建議是好的。正如Sawa所說,slice將會有與OP if語句不同的行爲。 – oldergod

1
def search 
    @person = Person.where({status: 1}.merge(params).select{|_, v| v.present?}) 
end 
+1

這將包括'params'哈希中的任何內容,這不是OP的代碼所做的。 –

+0

我解釋說,「由於成長搜索形式,這裏會有更多的陳述」,這意味着。 – sawa

1
# controller 
def search 
    @person = PersonSearch.new(params).result 
end 


# lib/person_search.rb 
class PersonSearch 

    attr_accessor :params 

    SUPPORTED_FIELDS = [:city, :country] 

    def initialize(params) 
    @params = params 
    end 

    def result 
    Person.where conditions 
    end 

    private 

    def conditions 
    conditions = default_conditions 

    SUPPORTED_FIELDS.each do |field| 
     conditions.merge!(field => params[field]) if params[field] 
    end 

    conditions 
    end 

    def default_conditions 
    { :status => 1 } 
    end 

end 

增長的搜索表單?將更多屬性添加到SUPPORTED_FIELDS

優點:

+可擴展的(甚至是其他機型支持)

+可測試(即使不打你的DB居多)

+可重複使用的

缺點:

-稍微代碼