Skip to content

How To: Search Using Ransack

Arthur Miranda Moreira edited this page Feb 23, 2021 · 6 revisions

Add ransack to your gemfile:

gem 'ransack'

Make a custom resource index view at app/views/trestle/resource/index.html.haml:

- content_for(:title, t("admin.titles.index", default: "Listing %{pluralized_model_name}", model_name: admin.model_name.titleize, pluralized_model_name: admin.model_name.plural.titleize))

- content_for(:primary_toolbar) do
  = link_to admin.path(:new), class: "btn btn-default btn-lg" do
    = icon("fa fa-plus")
    %span.sr-only= t("admin.buttons.new", default: "New %{model_name}", model_name: admin.model_name)
- end unless admin.readonly?

- content_for(:utilities) do
  = render "scopes" if admin.scopes.any?
- end if admin.scopes.any?

- content_for :sidebar do
  - if admin.search_form
    %h1 Search
    = search_form_for @q, url: admin.path(:index), builder: NoErrorsFormBuilder do |f|
      = with_form(f) { admin.search_form.render(self, @q) }
      = f.submit "Search", class: 'btn btn-primary'
      = link_to 'Reset', admin.path(:index)

-# Wrap this render in a non_haml block makes it work
-# This is because the layout that we are rendering in is not haml....I think
- non_haml do 
  = render layout: "layout" do
    = render "table"

Add this to the bottom of your config/initializers/trestle.rb outside the config block:

# These next few classes and overrides all allow a search form to be set inside of admin builders
# so that we can get a search sidebar next to tables
module RansackableAdminBuilder
  def search_form(collection=nil, &block)
    ransackable(collection)
    admin.search_form = Trestle::Form.new(&block)
  end

  def ransackable(base_collection=nil)
    q = nil

    before_action do
      @q = q
    end

    collection do |params|
      if base_collection.nil?
        q = model.search(params[:q])
      else
        q = base_collection.call.search(params[:q])
      end
      q.result
    end
  end
end
Trestle::Resource::Builder.send(:prepend, RansackableAdminBuilder)

module Trestle
  class Resource
    class << self
      attr_accessor :search_form
    end
  end
end

class NoErrorsFormBuilder < Trestle::Form::Builder
  def errors(name)
    []
  end
end

And now inside any admin builder:

Trestle.resource(:users) do
  # ...
  search_form do |q|
    text_field :name_cont, label: "Name", readonly: false
  end
  # ...
end