#370 Ransack
Ransack allows you to easily build complex search forms. It also helps in adding sortable links and building a dynamic advanced search page.
- Download:
- source codeProject Files in Zip (59.2 KB)
- mp4Full Size H.264 Video (29 MB)
- m4vSmaller H.264 Video (12.7 MB)
- webmFull Size VP8 Video (15 MB)
- ogvFull Size Theora Video (30.7 MB)
Resources
- Ransack
- Ransack Demo
- Define Searchable Attributes in Ransack
- Episode 196: Nested Model Form (revised)
- Episode 111: Advanced Search Form (revised)
Gemfile
gem 'ransack'
products_controller.rb
def index @search = Product.search(params[:q]) @products = @search.result end
products/index.html.erb
<%= search_form_for @search, url: search_products_path, method: :post do |f| %> <%= f.condition_fields do |c| %> <%= render "condition_fields", f: c %> <% end %> <p><%= link_to_add_fields "Add Conditions", f, :condition %></p> <div class="field"> Sort: <%= f.sort_fields do |s| %> <%= s.sort_select %> <% end %> </div> <div class="actions"><%= f.submit "Search" %></div> <% end %> <table id="products"> <tr> <th><%= sort_link @search, :name, "Product Name" %></th> <th><%= sort_link @search, :released_on, "Release Date" %></th> <th><%= sort_link @search, :price, "Price" %></th> </tr> <% @products.each do |product| %> <tr> <td><%= link_to(product.name, product) %></td> <td><%= product.released_on.strftime("%B %e, %Y") %></td> <td><%= number_to_currency(product.price) %></td> </tr> <% end %> </table>
Advanced Search Form
config/routes.rb
resources :products do collection { post :search, to: 'products#index' } end
products_controller.rb
def index @search = Product.search(params[:q]) @products = @search.result @search.build_condition if @search.conditions.empty? @search.build_sort if @search.sorts.empty? end
products/index.html.erb
<%= search_form_for @search, url: search_products_path, method: :post do |f| %> <%= f.condition_fields do |c| %> <%= render "condition_fields", f: c %> <% end %> <p><%= link_to_add_fields "Add Conditions", f, :condition %></p> <div class="field"> Sort: <%= f.sort_fields do |s| %> <%= s.sort_select %> <% end %> </div> <div class="actions"><%= f.submit "Search" %></div> <% end %>
products/_condition_fields.html.erb
<div class="field"> <%= f.attribute_fields do |a| %> <%= a.attribute_select associations: [:category] %> <% end %> <%= f.predicate_select %> <%= f.value_fields do |v| %> <%= v.text_field :value %> <% end %> <%= link_to "remove", '#', class: "remove_fields" %> </div>
application_helper.rb
def link_to_add_fields(name, f, type) new_object = f.object.send "build_#{type}" id = "new_#{type}" fields = f.send("#{type}_fields", new_object, child_index: id) do |builder| render(type.to_s + "_fields", f: builder) end link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")}) end
products.js.coffee
jQuery -> $('form').on 'click', '.remove_fields', (event) -> $(this).closest('.field').remove() event.preventDefault() $('form').on 'click', '.add_fields', (event) -> time = new Date().getTime() regexp = new RegExp($(this).data('id'), 'g') $(this).before($(this).data('fields').replace(regexp, time)) event.preventDefault()