如何重构此控制器操作,该操作构建活动记录搜索哈希

时间:2012-12-05 23:39:59

标签: ruby ruby-on-rails-3 refactoring

这段代码感觉不对。我正试图让我的控制器变得粗糙,我觉得控制器动作中有太多逻辑。

组织此代码的更好方法是什么?

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

随着搜索表单的增长,此控制器操作也将增长。如何保持我的控制器骨瘦如柴?

4 个答案:

答案 0 :(得分:2)

怎么样:

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

或者使用ActiveSupport提供的slice方法(在Rails中)更简单的版本:

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

如果您要选择性地包含一系列不同的参数,那么您可以将它们分组:

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

(感谢@ajcodez指出传递给search_params时需要在slice上展示广告。)

答案 1 :(得分:1)

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

答案 2 :(得分:1)

这是我将如何做到的。您也可以将字段定义为常量。

FIELDS = [:city, :country]

def search
  query_params = params.slice(*FIELDS).reject { |_,val| val.blank? }
  query_params[:status] = 1
  @person = Person.where query_params
end

请注意字段上的图示。哈希#slice:http://api.rubyonrails.org/v2.3.8/classes/ActiveSupport/CoreExtensions/Hash/Slice.html

答案 3 :(得分: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添加更多属性。

优点:

+ 可扩展(甚至支持其他型号)

+ 可测试(即使没有主要点击你的数据库)

+ 可重复使用

缺点:

- 略多代码