我正在构建一个rails应用程序,我有一个使用范围的搜索查询。代码正在运行,但我很确定它不是最好的方式,如果我想添加一些东西,我想在未来中提高它的可靠性。
这是我的观点:
<%= form_tag spendings_path, method: :get do %>
<%= date_field_tag "search[date_from]", @search.date_from, class: 'form-control col-2 d-inline-block' %>
<%= date_field_tag "search[date_to]", @search.date_to, class: 'form-control col-2 d-inline-block' %>
<%= select_tag "search[user_id]", options_from_collection_for_select(User.all, :id, :firstname, params[:user_id]), include_blank: "All Users", class: 'form-control col-2 d-inline-block' %>
<%= select_tag "search[currency_id]", options_from_collection_for_select(Currency.all, :id, :name, params[:currency_id]), include_blank: "All Currencies", class: 'form-control col-2 d-inline-block' %>
<%= submit_tag "Search", name: nil, class: "btn btn-secondary d-inline-block" %> <%= link_to "Reset", spendings_path, class: "btn btn-secondary d-inline-block" %>
<% end %>
在这里,我正在刷新页面以“重置”过滤器。这是一个不错的选择吗? 我的控制器:
@search = SpendingSearch.new(params[:search])
我的帮手:
@search.scope.order('date DESC').paginate(:page => params[:page], :per_page => 10)
最后我的模型只为此搜索目的而创建:
class SpendingSearch
attr_reader :date_from, :date_to, :user_id, :currency_id
def initialize(params)
params ||= {}
@date_from = parsed_date(params[:date_from], 1.month.ago.to_date.to_s)
@date_to = parsed_date(params[:date_to], Date.tomorrow.to_s)
@user_id = params[:user_id]
@currency_id = params[:currency_id]
end
def scope
if @user_id.present? && @currency_id.present?
Spending.where("date BETWEEN ? AND ? AND user_id = ? AND currency_id = ?", @date_from, @date_to, @user_id, @currency_id)
elsif @user_id.present?
Spending.where("date BETWEEN ? AND ? AND user_id = ?", @date_from, @date_to, @user_id)
elsif @currency_id.present?
Spending.where("date BETWEEN ? AND ? AND currency_id = ?", @date_from, @date_to, @currency_id)
else
Spending.where("date BETWEEN ? AND ?", @date_from, @date_to)
end
end
private
def parsed_date(date_string, default)
Date.parse(date_string)
rescue ArgumentError, TypeError
default
end
end
正如你所看到的,最糟糕的是......这个范围有点荒谬。
基本上我正在寻找dates
,user_id
和currency_id
。如果currency_id
和user_id
留空(因为我在视图中包含空白),我希望结果显示所有user_id
和currency_id
。
我确信有更好的方法可以做到这一点,我只是不知道它可能是哪一种。
同样,我知道这是给我代码的重点,我只是想在这里改进,所以任何类似的东西,也许你应该检查一下,或者这里有一个可以帮助非常好的链接。
也许我应该改变一切,我只是不知道,我不是铁杆专家,任何提示,技巧或提示都非常感激。
非常感谢。
答案 0 :(得分:0)
请尝试以下scope
方法:
def scope
s_scope = Spending.where('date BETWEEN ? AND ?', @date_from, @date_to)
s_scope = s_scope.where(user_id: @user_id) if @user_id.present?
s_scope = s_scope.where(currency_id: @currency_id) if @currency_id.present?
s_scope
end
另外,我相信你可以改变:
@date_from = parsed_date(params[:date_from], 1.month.ago.to_date.to_s)
@date_to = parsed_date(params[:date_to], Date.tomorrow.to_s)
到
@date_from = parsed_date(params[:date_from], 1.month.ago.to_date)
@date_to = parsed_date(params[:date_to], Date.tomorrow)