这段代码感觉不对。我正试图让我的控制器变得粗糙,我觉得控制器动作中有太多逻辑。
组织此代码的更好方法是什么?
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
随着搜索表单的增长,此控制器操作也将增长。如何保持我的控制器骨瘦如柴?
答案 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
添加更多属性。
优点:
+ 可扩展(甚至支持其他型号)
+ 可测试(即使没有主要点击你的数据库)
+ 可重复使用
缺点:
- 略多代码