我对Ruby on Rails很新,并尝试创建一个允许用户同时搜索多个参数的搜索功能;来自和。要记住的是,在开发过程中可能会有更多的参数。我在搜索其中一个字段时已经开始工作,但不会超过这个。
搜索视图:
<%= form_tag(journeys_path, :method => "get", from: "search-form") do %>
<%= text_field_tag :search_from, params[:search_from], placeholder: "Search from", :class => 'input' %>
<%= text_field_tag :search_to, params[:search_to], placeholder: "Search to", :class => 'input' %>
<%= submit_tag "Search", :class => 'submit' %>
<% end %>
方法:
class Journey < ActiveRecord::Base
def self.search(search_from)
self.where("from_place LIKE ?", "%#{search_from}%")
end
end
控制器:
class JourneysController < ApplicationController
def index
@journeys = Journey.all
if params[:search_from]
@journeys = Journey.search(params[:search_from])
else
@journeys = Journey.all.order('created_at DESC')
end
end
def search
@journeys = Journey.search(params[:search_from])
end
end
我已尝试过一些宝石和我在其他问题中找到的所有解决方案,但我对RoR还不够好,但在没有帮助的情况下成功地正确应用它们。我很感激能得到的任何帮助。
谢谢!
答案 0 :(得分:0)
型号:
class Journey < ActiveRecord::Base
def self.search(search_from, search_to)
self.where("from_place LIKE ? and to_place LIKE ?", "%#{search_from}%", "%#{search_to}%")
end
end
控制器:
class JourneysController < ApplicationController
def index
if params[:search_from] and params[:search_to]
@journeys = search
else
@journeys = Journey.all.order('created_at DESC')
end
end
def search
@journeys = Journey.search(params[:search_from], params[:search_to])
end
end
答案 1 :(得分:0)
这里最好的方法是将搜索表单封装为单独的Ruby类。在这里使用Virtus有助于免费获得类型强制。
class SearchForm
include Virtus.model # Our virtus module
include ActiveModel::Model # To get ActiveRecord-like behaviour for free.
attribute :from, String
attribute :to, String
# Just to check if any search param present,
# you could substitute this with validations and just call valid?
def present?
attributes.values.any?{|value| value.present?}
end
```
在Rails 3 IIRC中,您还必须包含ActiveModel :: Validations,以便在需要时验证表单输入。 现在,让我们看看如何重构控制器。我们从params实例化form对象并将其传递给模型查询方法以获取所需的记录。我还移动了if子句的命令,并使用符号排序参数 - 更清洁的IMO。
def index
@search_form = SearchForm.new(search_params)
if @search_form.valid? && @search_form.present?
@journeys = Journey.search(@search_form)
else
@journeys = Journey.all
end
@journeys = @journeys.order(created_at: :desc)
end
def search
@journeys = Journey.search(SearchForm.new(search_params)
end
private
def search_params
params.require(:search_form).permit(:from, :to)
end
现在到视图:form_for将与我们的表单对象完美配合,simple_form_for
也是如此<%= form_for @search_form, url: journeys_path, method: :get do |f| %>
<%= f.text_field :from, placeholder: "Search from", class: 'input' %>
<%= f.text_field :to, placeholder: "Search to", class: 'input' %>
<%= f.submit "Search", class: 'submit' %>
<% end %>
查看现在看起来更短更清洁。在对象中包含params使搜索参数更容易处理。
型号:
class Journey < ActiveRecord::Base
def self.search(search_form)
if search_form.kind_of?(SearchForm)
journeys = all # I'm calling Journey.all here to build ActiveRecord::Relation object
if search_form.from.present?
journeys = journeys.where("from_place LIKE ?", "%#{search_form.from}%")
end
if search_form.to.present?
journeys = journeys.where("to_place LIKE ?", "%#{search_form.to}%")
end
else
raise ArgumentError, 'You should pass SearchForm instance to Journey.search method'
end
end
end
注意我如何通过调用Journeys.all
并应用每个搜索参数(如果存在)来构建ActiveRecord :: Relation对象。像这样链接where
会自动将AND
置于其中,如果需要OR
,Rails 4会将其Journey.or(condition)
。{{1}}。
这种方法的优点: