views:

142

answers:

2

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?

+1  A: 

In your controller:

params[:search][:baseline_name_like_or_description_like].strip!
nicholasklick
that worked, except when they are going to the main URL:http://example.com/baselines/it brings up The error occurred while evaluating nil.[] should I put a if end or an unless around it?
Nick
Yeah.if params[:search] params[:search][:baseline_name_like_or_description_like].strip!end@search = Baseline.search(params[:search])
nicholasklick
giraff
double checking this and it does not work..see below:During the search: strip takes out the white space and shows this:Parameters: {"commit"=>"Search", "action"=>"index", "controller"=>"baselines", "search"=>{"order"=>"", "device_id"=>"", "baseline_name_like_or_description_like"=>"build"}}(that makes sense right)Then the results come back and show all the baselines and the text field does not have the search string in it. This appears to be something with searchlogic?
Nick
Not sure what this means: "Then the results come back and show all the baselines and the text field does not have the search string in it."
nicholasklick
Sorry, what I was trying to say was that the search is not functioning, it returns the same results if you didn't search for anything at all
Nick
+1  A: 

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.

macek
Nice macek! That is awesome stuff, I bet I use all of that at one point or another!!
Nick