Ransack,查找包含所有相关记录的记录 [英] Ransack, find record that has all related records

查看:33
本文介绍了Ransack,查找包含所有相关记录的记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个配方模型,它有_许多成分,每种成分都属于一个项目.在我的高级搜索表单中,我希望用户选择多种成分,然后让 Ransack 找到包含用户选择的所有成分的食谱.

我尝试了以下搜索字段:

= f.collection_select(:ingredients_item_id_in, Item.all, :id, :name, {}, {multiple: true})

但从逻辑上讲,这会导致显示包含任何选定成分的所有食谱.

:ingredients_item_id_in 更改为 :ingredients_item_id_in_all 会导致查询错误,因为一条记录不能包含 item_id 的多个值.

关于在 Ransack 中创建这个搜索参数的任何想法,或者我应该为此创建一个子查询吗?

根据要求,我的控制器搜索方法:

 定义搜索@q = Recipe.ransack(params[:q])@recipes = @q.result(distinct: true).include_related_models.published结尾

解决方案

我最近在我的项目中遇到了类似的任务 (Rails 4.2.4/Ruby 2.3.1).

庄园有很多舒适的地方.我需要获得所有资产,其中包括所有选定的舒适设施.

这是我使用 Ransack

解决它的方法

就我而言,我有 has_many :through 关系.

estate.rb

class Estate 

comfort.rb

class Comfort <ActiveRecord::Basehas_many :estate_comfortshas_many :estates, 通过: :estate_comforts结尾

estate_comfort.rb

class EstateComfort 

对于复杂的查询,您需要通过 post 进行搜索.为此,您必须像这样编辑路线.并将 search 动作添加到 estates_controlle.rb.有关更多信息,请阅读 Ransack wiki

routes.rb

<预><代码>...资源:地产收藏做匹配搜索"=>'estates#search', via: %i[get post], as: :search结尾结尾

estates_controller.rb

class EstatesController <应用控制器...定义索引@q = Estate.ransack(params[:q])@estates =如果 params[:q]&.has_key?(:estate_comforts_comfort_id_eq_any)# 存储已检查的舒适度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].countids = @q.result.includes(:estate_comforts).group_by(&:id).select { |_, v|v.count ==comforts_count}.keysEstate.where(id: ids)别的@q.result(不同:真实)结尾结尾定义搜索指数渲染:索引结尾结尾

最后是模板部分...

estates/index.haml

= search_form_for @q, url: search_estates_path, html: { method: :post } do |f|# 这里是表单输入# 使用先前检查过的舒适度来填充复选框- Comfort.find_each 做|舒适|# 之前检查过吗?- 选中=comfort.id.to_s.in?(session[:estate_comforts_comfort_id_eq_any].to_a)%div%input{ name: 'q[estate_comforts_comfort_id_eq_any][]',类型:复选框",id: "复选框#{comfort.id}",值:comfort.id,检查:检查}%label{for: "checkbox#{comfort.id}"}=comfort.name

将生成以下html

<form class="estate_search" id="estate_search" action="/estates/search" accept-charset="UTF-8方法=发布"><div><input checked="" id="checkbox1" name="q[estate_comforts_comfort_id_eq_any][]" type="checkbox" value="1"><label for="checkbox1">舒适名称 1</label>

<div><input id="checkbox2" name="q[estate_comforts_comfort_id_eq_any][]" type="checkbox" value="2"><label for="checkbox2">舒适名称2</label>

I have a recipe model which has_many ingredients and each ingredient belongs to an item. In my advanced search form, I would like a user to select multiple ingredients and let Ransack find a recipe that contains all the ingredients selected by the user.

I tried the following searchfield:

= f.collection_select(:ingredients_item_id_in, Item.all, :id, :name, {}, {multiple: true})

But logically, this results in all recipes being shown that contain any of the selected ingredients.

changing :ingredients_item_id_in to :ingredients_item_id_in_all results in an incorrect Query since one record cannot contain multiple values of item_id.

Any ideas on creating this search parameter within Ransack, or should I create a subquery for this?

Upon request, my controller method for search:

  def search
    @q = Recipe.ransack(params[:q])
    @recipes = @q.result(distinct: true).include_related_models.published
  end

解决方案

I recently came across similar task for my project (Rails 4.2.4 / Ruby 2.3.1).

Estate has many comforts. I need to get all estates, which include all selected comforts.

Here is how I resolved it using Ransack

In my case I have has_many :through relation.

estate.rb

class Estate < ActiveRecord::Base
  has_many :estate_comforts
  has_many :comforts, through: :estate_comforts
end

comfort.rb

class Comfort < ActiveRecord::Base
  has_many :estate_comforts
  has_many :estates, through: :estate_comforts
end

estate_comfort.rb

class EstateComfort < ActiveRecord::Base
  belongs_to :estate
  belongs_to :comfort
end

For complex queries you'll need to do search via post. For that you have to edit routes like this. And add search action to estates_controlle.rb. For more info read Ransack wiki

routes.rb

...
resources :estates
  collection do
    match 'search' => 'estates#search', via: %i[get post], as: :search
  end
end

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

And finally the template portion...

estates/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

Will generate following html

<form class="estate_search" id="estate_search" action="/estates/search" accept-charset="UTF-8" method="post">
  <div>
    <input checked="" id="checkbox1" name="q[estate_comforts_comfort_id_eq_any][]" type="checkbox" value="1">
    <label for="checkbox1">Comfort Name 1</label>
  </div>
  <div>
    <input id="checkbox2" name="q[estate_comforts_comfort_id_eq_any][]" type="checkbox" value="2">
    <label for="checkbox2">Comfort Name 2</label>
  </div>
</form>

这篇关于Ransack,查找包含所有相关记录的记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆