Question

This works:

Baseline Controller

@search = Baseline.search(params[:search])

@baselines = @search.paginate :page => params[:page], :per_page => params[:per_page]

baseline index view

<% form_for @search do |f| %>
  <%= f.text_field :baseline_name_like_or_description_like %>
  <%= submit_tag 'Search' %>
<% end %>

Where would I trim the leading and trailing whitespace in the text_field? Could I use a .strip! somewhere?

Was it helpful?

Solution

Nick, surprisingly, it's quite difficult to find information on advanced Searchlogic techniques. Sanitization has been particularly difficult for me to deal with.

Here's a pretty nifty (and quick) way to deal with your issue.

controller

stays the same

views/baselines/index.html.erb

<% form_for @search do |f| %>
  <%= f.text_field :keywords %>
  <%= submit_tag 'Search' %>
<% end %>

models/baseline.rb

class Baseline < ActiveRecord::Base
  scope_procedure :keywords, lambda { |query|
    baseline_name_like_or_description_like(query.strip)
  }
end

Extras

I'm excited to share the other cool things I've learned with Searchlogic, so I'll share them here.

First, with very little work, you can power-up that keywords scope_procedure with minimal effort.

scope_procedure :keywords, lambda { |query|
  baseline_name_like_any_or_description_like_any(query.strip.split(/\s+/))
}

Note the addition of the any operator to each named_scope

This will allow you to enter searches like "foo bar" and it will match baseline_names like "i can foo haz bar" or "bar time, foo!" This would even match a Baseline if the name was "foo" and the description was "bar"; point being, you get tons of extra control if you use scope_procedure instead of a predefined named_scope in your Searchlogic forms.

Second, you can sanitize your search forms with a little extra effort. This one took quite a while to figure out, but I decided to create a subclass of the Searchlogic::Search class. Check it out:

models/baseline_search.rb

class BaselineSearch < Searchlogic::Search
  def initialize(params, klass, current_scope)

    allowed_params = [:keywords, :name_like_any, :foo_equals, :order]

    conditions = {}

    for x in allowed_params 
      conditions[x] = params[x] unless params[x].blank?
    end

    super(klass, current_scope, conditions)
  end
end

If you're wondering where I found that initialize method signature, check Searchlogic::Search

Now, instead of invoking Searchlogic::Search on your model, you need to create a simple override in your baseline.rb. Here, we'll implement our own Searchlogic::Search::Implementation

models/baseline.rb

class Baseline < ActiveRecord::Base

  # cool scope procedures
  # ...

  def self.search(params={})
    BaselineSearch.new(params || {}, self, scope(:find))
  end
end

Now, when you call Baseline.search(params[:search]), it will invoke a new BaselineSearch instead of the Searchlogic::Search default. The cool thing here is, if you want to skip using your BaselineSearch, you can call Baseline.searchlogic(params[:search]) to use the Searchlogic default instead.

OTHER TIPS

In your controller:

params[:search][:baseline_name_like_or_description_like].strip!

Or for strip all searches in your app, put this into ApplicationController

before_filter :strip_search_parameters      

def strip_search_parameters
  return if params[:search].blank?
  params[:search].each_value {|val| val.strip!}
  return
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top