DRY和Elegant方式代表所有搜索组合而不会成倍增长?

时间:2015-01-23 07:20:01

标签: ruby-on-rails ruby ruby-on-rails-4

现在我可以搜索以下内容

1)leaving_from location

2)going_to location

3)leaving_from&     go_to location

if params[:leaving_from].present? && params[:going_to].present?
  @flights = Flight.where(:source => params[:leaving_from]).where(:destination => params[:going_to])      

elsif params[:leaving_from].present?
  @flights = Flight.where(:source => params[:leaving_from])

elsif params[:going_to].present?
  @flights = Flight.where(:destination => params[:going_to])  

end 

上面有代表这个代码的方法吗?基本上它的搜索功能受到2个下拉搜索框的影响。一个用于从位置离开而另一个用于到达位置。可选择通过两个位置或仅一个位置缩小范围。

它现在工作正常,但它不具备可扩展性。如果我添加了更多的搜索参数,例如价格和时间,它将呈指数级增长,以便能够代表所有州。

例如,如果我添加价格,我的新组合将是

1)leaving_from location

2)going_to location

3)leaving_from&     go_to location

4)价格

5)leaving_from location&价

6)going_to location&价

7)leaving_from location& go_to location&价

我需要帮助来找出一种更好的方式来表示这一点,否则会让我的控制器变得非常臃肿。

编辑表格代码 -

=form_tag '/flights', :method =>  :get
 %h4
        Leaving From:   
        =select_tag 'leaving_from', content_tag(:option,'select one...',:value=>"")+options_for_select(@flights_source, 'source'),  { :class => 'form-control' }

 %h4
        Going To:
        =select_tag 'going_to', content_tag(:option,'select one...',:value=>"")+options_for_select(@flights_destination, 'destination'), { :class => 'form-control' }
        %h4=submit_tag "Search", :name => nil, :class => 'btn btn-success btn-md btn-block'             

4 个答案:

答案 0 :(得分:2)

代替使用leaving_fromgoing_to使用sourcedestination代替并在key下移动所有必需参数,例如,此解决方案将为任何没有工作。的钥匙

'required' => { 'source' => value, 'destination' => value, 'price' => value }

现在在控制器中私下定义此方法

def get_flights(params) 
  possible_combination = [] 
  conditions = {}   
  key_array = params['required'].keys

  1.upto(key_array.length) { |i| possible_combination + key_array.combination(i).to_a }

  possible_combination.reverse.each do |comb|      
    if comb.collect{ |key| params['required'][key].present? }.inject(:&)
      comb.map { |key| conditions[key] = params['required'][key] }
      break
    end
  end

  Flight.where(conditions)
end

从任何操作中调用此方法

@flights = get_flights(params)

希望这有效!它是一个让这个东西变得动态的总体想法,你可以根据你的需要重构代码!

答案 1 :(得分:1)

首先要做的事情是:您的代码没有按照您的想法执行,因为没有办法执行第三个if(每次第三个if都是true ,第一个if也是如此)。关于你的问题:

@flights = Flight
@flights = @flights.where(:source => params[:leaving_from]) if params[:leaving_from].present?
@flights = @flights.where(:destination => params[:going_to]) if params[:going_to].present?

或者

conditions = {}
conditions[:source] = params[:leaving_from] if params[:leaving_from].present?
conditions[:destination] = params[:going_to] if params[:going_to].present?
@flights = Flight.where(conditions)

答案 2 :(得分:0)

使用ransack如何轻松地将搜索功能添加到搜索功能。

如果您使用ransack,请写下面的内容。

# View (Search Form)
<%= search_form_for @q do |f| %>
  From: <%= f.text_field :leaving_from_cont %>
  To  : <%= f.text_field :going_to_cont %>
  Price:
  <%= f.text_field :price_gteq %> 〜 <%= f.text_field :price_lteq %>

  <%= f.submit %>
<% end %> 

# Controller
def index
  @q = Flight.ransack(parmas[:q])
  @flights = @q.result(distinct: true)
end

如果用户没有输入任何字段,则hansack不会使用非输入字段值。这意味着不要在DB中添加WHERE条件。

  • column_name _cont表示包含(与DB中相似)。
  • column_name _eq表示相等(==在DB中)。
  • column_name _gteq表示大于等于(&lt; =在DB中)。
  • column_name _lteq表示小于等于(&gt; =在DB中)。
  • 等...

您还可以使用sort_link的{​​{1}}方法轻松对搜索结果进行排序。

请查看ransack

答案 3 :(得分:0)

我无法获得@RSB's代码,但我能够使用他的示例创建一个可行的方法。我在行动中调用了以下代码。

@flights = get_flights(search_params)

search_params方法如下:

def search_params
    params.permit(:leaving_from, :going_to)
    params_hash = {'required' => { 'source' => params[:leaving_from], 'destination' => params[:going_to]}}
end

最后get_flights方法是:

def get_flights(params) 

    possible_combination = [] 
    conditions = {}
    key_array = params['required'].keys

    possible_combination = (possible_combination + key_array.combination(key_array.length).to_a).flatten

    possible_combination.each do |comb|
        conditions[comb] = params['required'][comb] if params['required'][comb].present?
    end  

    Flight.where(conditions)
end

我对ruby和rails仍然很陌​​生,所以任何反馈或改进建议都会受到欢迎。谢谢!