Rails 4 searching multiple models in a separate controller

I am trying to implement a complex model search in a separate controller. I have a student model. The whole app has a front page handled by a separate main_controller that doesn't have a model. Master_controller and its associated index pointer should provide the first page and display data from multiple models.

Now I want to search for a model with multiple search criteria of different types. Search criteria: string comparison, number comparison, and boolean (e.g. active if true, only active students show all students). Railscast # 111 showed how to create such a search based on a model and a separate search controller. I created a controller like this and it works great. I am stuck showing the relevant parts in my main / index.

Here is the code:

Main / index.html.haml

 - model_class = Adult
 - model_class = Pupil
 - model_class = MainSearch

.page-header
= render :partial => 'main_searches/form', :main_search => MainSearch.new

      

Only the form call is here at the moment.

models / main_search.rb

class MainSearch < ActiveRecord::Base

  def pupils
    @pupils ||= find_pupils
  end

  private
    def find_pupils
      pupils = Pupil.order(:name_sur)
      pupils = pupils.where(id: id_search) if id_search.present?
      pupils = pupils.where("name_first like ?", "%#{name_first}%") if name_first.present?
      pupils = pupils.where("name_sur like ?", "%#{name_sur}%") if name_sur.present?
      pupils = pupils.where(active: "true") if active == true  #show only active or all
      pupils
    end
end

      

This defines the search.

Controllers / main_searches_controller.rb

class MainSearchesController < ApplicationController
  before_action :set_main_search, only: [:show, :update, :destroy]

  def show
    @main_search = MainSearch.find(params[:id])
  end

  def new
    @main_search = MainSearch.new
  end

  def create
    @main_search = MainSearch.new(main_search_params)

    if @main_search.save
      redirect_to root_path, notice: 'Main search was successfully created.'
    else
      render action: 'new'
    end
  end
end

      

As shown in railscast.

view / main_searches / _form.html.haml

%h1 Advanced Search

  = form_for :main_search, :url => main_searches_path do |f|
    .field
      = f.label :id_search
      %br/
      = f.text_field :id_search
    [... ommitted some fields here ...]
    .field
      = f.label :active
      %br/
      = f.check_box :active, {}, true, false


  .actions= f.submit "Search"

      

Displays in a new view.

view / main_searches / _results.html.haml

%h1 Search Results

.container-fluid
  .row-fluid
    .span4

      %table.table{style: "table-layout:fixed"}
        %thead
          %tr
            %th= "id"
            %th= "name_sur"
            %th= "name first"
            %th= "a"
      %div{style: "overflow-y:scroll; height: 200px"}
        %table.table.table-striped{style: "table-layout:fixed"}
          %tbody
            - @main_search.pupils.each do |pupil|
              %tr
                %td= pupil.id
                %td= link_to pupil.name_sur, pupil_path(pupil)
                %td= pupil.name_first
                %td= pupil.active

      

Displays the results.

So basically everything works for one model, as shown on railscast. What I need now is to allow the user to handle everything in the main_controller. At the moment, I cannot get the @main_search object passed to the _results.html.haml particle. What am I missing here? Or is this even the correct way to do such a search?

Thanks for your help in advance.

+3


source to share


1 answer


Brians' solution actually worked well enough. I created a separate model with no corresponding database and put all the search logic in this file. Note that this is only a class and is not associated with ActiveRecord.

class MainSearch

  def self.for(id_search, name_sur, name_first, active)

      #escape for security
      name_sur = "%#{name_sur}%"
      name_first = "%#{name_first}%"
      active = "%#{active}%"

      pupils = Pupil.order(:name_sur)
      pupils = pupils.where(id: id_search) if id_search.present?
      pupils = pupils.where("name_first like ?", "%#{name_first}%") if name_first.present?
      pupils = pupils.where("name_sur like ?", "%#{name_sur}%") if name_sur.present?
      pupils = pupils.where(active: "true") if active == true  #show only active or all
  end
end

      

Now my main_controller can call this function and pass values ​​from the params hash:

    @pupils = MainSearch.for(params[:id_search], params[:name_sur], params[:name_first], params[:active])

      

The parameters come from views / main / _form_search.html.haml:



.search-box
  = form_tag root_path, method: :get do

    = label_tag :id_search
    %br/
    = text_field_tag 'id_search', nil
    %br/
    = label_tag :name_sur
    %br/
    = text_field_tag 'name_sur', nil
    %br/
    = label_tag :name_sur
    [...]
    = submit_tag "Submit"

      

The last step is to show the results. As you can see in the main_controller, I just populate the @pupils object and thus can easily display it in any view. Here is an excerpt from views / main / index.html.haml

.span8
  .row-fluid
    %table.table{style: "table-layout:fixed"}
      %thead
        %tr
          %th= "id"
          %th= sortable "name_sur"
          %th= "name first"
          %th= "a"
    %div{style: "overflow-y:scroll; height: 200px"}
      %table.table.table-striped{style: "table-layout:fixed"}
        %tbody
          - @pupils.each do |pupil|
            %tr
              %td= pupil.id
              %td= link_to pupil.name_sur, pupil_path(pupil)
              %td= pupil.name_first
              %td= pupil.active

    = render :partial => 'form_search'

      

This setting saves all controls in main_controller and only requires one external file (search model). In this model, I can search data across multiple models (as shown in the video) and combine the search criteria as I please, and even make some performance synonyms there. I am quite happy with the result. SO thanks for all the input.

+2


source







All Articles