bo-*_*-oz 9 ruby-on-rails ransack
我有一个配方模型,其中包含很多成分,每种成分都属于一个项目.在我的高级搜索表单中,我希望用户选择多种成分,让Ransack找到包含用户选择的所有成分的配方.
我尝试了以下搜索字段:
= f.collection_select(:ingredients_item_id_in, Item.all, :id, :name, {}, {multiple: true})
Run Code Online (Sandbox Code Playgroud)
但从逻辑上讲,这会导致显示的所有配方都含有任何选定的成分.
由于一条记录不能包含多个item_id值,因此更改:ingredients_item_id_in为:ingredients_item_id_in_all不正确的查询结果.
有关在Ransack中创建此搜索参数的任何想法,还是应该为此创建子查询?
根据要求,我的控制器搜索方法:
def search
@q = Recipe.ransack(params[:q])
@recipes = @q.result(distinct: true).include_related_models.published
end
Run Code Online (Sandbox Code Playgroud)
我最近在我的项目中遇到了类似的任务(Rails 4.2.4 / Ruby 2.3.1)。
庄园有很多舒适设施。我需要获得所有房产,其中包括所有选定的舒适设施。
这是我如何解决它的方法Ransack
就我而言,我有has_many :through关系。
房地产.rb
class Estate < ActiveRecord::Base
has_many :estate_comforts
has_many :comforts, through: :estate_comforts
end
Run Code Online (Sandbox Code Playgroud)
舒适.rb
class Comfort < ActiveRecord::Base
has_many :estate_comforts
has_many :estates, through: :estate_comforts
end
Run Code Online (Sandbox Code Playgroud)
庄园舒适.rb
class EstateComfort < ActiveRecord::Base
belongs_to :estate
belongs_to :comfort
end
Run Code Online (Sandbox Code Playgroud)
对于复杂的查询,您需要通过 进行搜索post。为此,您必须像这样编辑路线。并将search动作添加到estates_controlle.rb. 欲了解更多信息,请阅读 Ransack wiki
路线.rb
...
resources :estates
collection do
match 'search' => 'estates#search', via: %i[get post], as: :search
end
end
Run Code Online (Sandbox Code Playgroud)
Estates_controller.rb
class EstatesController < ApplicationController
...
def index
@q = Estate.ransack(params[:q])
@estates =
if params[:q]&.has_key?(:estate_comforts_comfort_id_eq_any)
# Store checked comforts
session[:estate_comforts_comfort_id_eq_any] = params[:q][:estate_comforts_comfort_id_eq_any]
comforts_count = params[:q][:estate_comforts_comfort_id_eq_any].count
ids = @q.result.includes(:estate_comforts).group_by(&:id).select { |_, v| v.count == comforts_count}.keys
Estate.where(id: ids)
else
@q.result(distinct: true)
end
end
def search
index
render :index
end
end
Run Code Online (Sandbox Code Playgroud)
最后是模板部分......
庄园/index.haml
= search_form_for @q, url: search_estates_path, html: { method: :post } do |f|
# here goes the form inputs
# Polulate checkboxes with previously checked comforts
- Comfort.find_each do |comfort|
# Was checked previously?
- checked = comfort.id.to_s.in?(session[:estate_comforts_comfort_id_eq_any].to_a)
%div
%input{ name: 'q[estate_comforts_comfort_id_eq_any][]',
type: "checkbox",
id: "checkbox#{comfort.id}",
value: comfort.id,
checked: checked }
%label{for: "checkbox#{comfort.id}"}= comfort.name
Run Code Online (Sandbox Code Playgroud)
将生成以下html
class Estate < ActiveRecord::Base
has_many :estate_comforts
has_many :comforts, through: :estate_comforts
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
942 次 |
| 最近记录: |