<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Binary Logic &#187; searchgasm</title>
	<atom:link href="http://www.binarylogic.com/tag/searchgasm/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.binarylogic.com</link>
	<description>Ben Johnson's thoughts and programming techniques</description>
	<lastBuildDate>Sat, 23 Jan 2010 21:19:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Tutorial: Caching virtual attributes in the database</title>
		<link>http://www.binarylogic.com/2008/10/05/tutorial-caching-virtual-attributes-in-the-database/</link>
		<comments>http://www.binarylogic.com/2008/10/05/tutorial-caching-virtual-attributes-in-the-database/#comments</comments>
		<pubDate>Sun, 05 Oct 2008 16:32:00 +0000</pubDate>
		<dc:creator>benjohnson</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Searchlogic]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[searchgasm]]></category>
		<category><![CDATA[virtual_column]]></category>

		<guid isPermaLink="false">0/2009/03/23/tutorial-caching-virtual-attributes-in-the-database</guid>
		<description><![CDATA[Ever since I released Searchlogic I&#8217;ve been getting a lot of really cool feedback. I love when people contact me with a unique way they used Searchlogic or a challenging / cool new feature they would like to see added. Challenges are what make programming fun, to see what you are capable of. So here [...]]]></description>
			<content:encoded><![CDATA[<p>Ever since I released <a href="http://github.com/binarylogic/searchlogic">Searchlogic</a> I&#8217;ve been getting a lot of really cool feedback. I love when people contact me with a unique way they used <a href="http://github.com/binarylogic/searchlogic">Searchlogic</a> or a challenging / cool new feature they would like to see added. Challenges are what make programming fun, to see what you are capable of. So here is my challenge for the day:</p>
<p>I&#8217;ve been having a lot of conversations via email with people using <a href="http://github.com/binarylogic/searchlogic">Searchlogic</a>, that go like the following:</p>
<blockquote>
<p><strong>Some person:</strong> Hi Ben, How do I order by an order&#8217;s total with Searchlogic?</p>
<p><strong>Me:</strong> Cache the total in your database. Your idol, Ben</p>
<p><strong>Some person:</strong> Before Searchlogic, I was just doing: Order.all(:order =&gt; &#8220;(quantity * price) ASC&#8221;). Is there a way to do this in Searchlogic?</p>
<p><strong>Me:</strong> No, you shouldn&#8217;t order data like that. &#8230;long explanation of what to do&#8230;. Your idol, Ben</p>
<p><strong>Some person:</strong> Thank you so much Ben, I can&#8217;t thank you enough for everything you have done for me. You truly are my idol. There should be a statue in your honor.</p>
</blockquote>
<p>Maybe it didn&#8217;t go exactly like that, but you get the point. So instead of having to retype the &#8220;long explanation of what to do&#8221;, I can just link them to this post:</p>
<p>This can be simple or complicated depending on how you calculate your total. Let&#8217;s start with the simple:</p>
<p>            <span id="more-33"></span></p>
<h2>Simple solution</h2>
<p>Your total method looks something like to following. Dealing with only local attributes.</p>
<pre class="cobalt">
<span class="Keyword">def</span> <span class="Entity">total</span>
    quantity <span class="Keyword">*</span> price
<span class="Keyword">end</span>
</pre>
<p>Your first thought might be to sort via the ruby sort method. This is wrong on so many levels, not to mention you already have a tool that is extremely good at sorting data: your database.</p>
<p>Awesome! We&#8217;ll just do something like this:</p>
<pre class="cobalt">
<span class="Support">Order</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">all</span></span><span class="Punctuation">(</span><span class="Constant"><span class="Punctuation">:</span>order</span> <span class="Punctuation">=&gt;</span> <span class="String"><span class="Punctuation">&quot;</span>(quantity * price) ASC<span class="Punctuation">&quot;</span></span><span class="Punctuation">)</span>
</pre>
<p>Wrong again! This is bad for a number of reasons:</p>
<ol>
<li>Your code is no longer DRY. What if you want to add in tax later on down the road? You&#8217;ll have to do it in multiple places.</li>
<li>(quantity * price) can not be indexed. The whole point of indexing is to sort.</li>
</ol>
<p>Now you&#8217;re saying &#8220;WTF Ben?!?!?1!?11&#8243;. Relax, why not just cache the total in the database?</p>
<pre class="cobalt">
<span class="Keyword">class</span> <span class="Entity">Order<span class="EntityInheritedClass"> <span class="Punctuation">&lt;</span> ActiveRecord::Base</span></span>
    before_validation <span class="Constant"><span class="Punctuation">:</span>cache_virtual_columns</span>

    <span class="Keyword">def</span> <span class="Entity">total</span>
        quantity <span class="Keyword">*</span> price
    <span class="Keyword">end</span>

    <span class="Keyword">private</span>
        <span class="Keyword">def</span> <span class="Entity">cache_virtual_columns</span>
            <span class="LangVariable">self</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">total</span></span> <span class="Keyword">=</span> total
        <span class="Keyword">end</span>
<span class="Keyword">end</span>
</pre>
<p>Now you can index the total column and order just like you would with any other column. Yay!</p>
<p>Don&#8217;t celebrate yet. Chances are your total probably isn&#8217;t that simple.</p>
<h2>Advanced solution</h2>
<p>Maybe your total method looks like:</p>
<pre class="cobalt">
<span class="Keyword">def</span> <span class="Entity">total</span>
    line_items<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">sum</span></span><span class="Punctuation">(</span><span class="Constant"><span class="Punctuation">:</span>total</span><span class="Punctuation">)</span> <span class="Keyword">+</span> tax <span class="Keyword">+</span> shipping_cost
<span class="Keyword">end</span>
</pre>
<p>Oh no! What happens when the total of a line item changes? The total in the orders table is no longer accurate. Your total now depends on other models. This is where observers shine:</p>
<pre class="cobalt">
<span class="Keyword">class</span> <span class="Entity">OrderObserver<span class="EntityInheritedClass"> <span class="Punctuation">&lt;</span> ActiveRecord::Observer</span></span>
  observe <span class="Constant"><span class="Punctuation">:</span>order</span><span class="Punctuation">,</span> <span class="Constant"><span class="Punctuation">:</span>line_item</span>

  <span class="Keyword">def</span> <span class="Entity">before_validation</span><span class="Punctuation">(</span><span class="Variable">obj</span><span class="Punctuation">)</span>
    <span class="Keyword">case</span> obj
    <span class="Keyword">when</span> <span class="Variable">Order</span>
      obj<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">total</span></span> <span class="Keyword">=</span> obj<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">total</span></span>
    <span class="Keyword">end</span>
  <span class="Keyword">end</span>

  <span class="Keyword">def</span> <span class="Entity">after_save</span><span class="Punctuation">(</span><span class="Variable">obj</span><span class="Punctuation">)</span>
    <span class="Keyword">case</span> obj
    <span class="Keyword">when</span> <span class="Variable">LineItem</span>
      obj<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">order</span></span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">update_attribute</span></span><span class="Punctuation">(</span><span class="Constant"><span class="Punctuation">:</span>total</span><span class="Punctuation">,</span> obj<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">order</span></span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">total</span></span><span class="Punctuation">)</span>
    <span class="Keyword">end</span>
  <span class="Keyword">end</span>
<span class="Keyword">end</span>
</pre>
<p>You could really set this up a number of ways. You could create a CacheObserver that handles all caching for all models. This could get messy and confusing really fast, which is why I recommend the above example. My philosophy on OO programming is that classes should be responsible for their self. If the Order class is calculating the total it should be responsible for keeping it up to date in the database too.</p>
<p>&#8220;But Ben, this looks messy and complicated&#8221;. I agree with you, to an extent, but there is no simple solution here, because there is no pattern. Your total method could be anything you want. For all I know, your total method could be outsourced to a team in India that calculates the total by hand.</p>
<p>Sometimes in programming you have to give up something to gain something. I feel like writing some simple code in an observer is worth having a cached value of the total in the database. It makes everything so much cleaner, easier, and simpler in your controllers and views. Models should do all of the heavy lifting anyways.</p>
<p>Obviously, this is not just limited to total. You could do this for pretty much any virtual attribute in your models.</p>
<p>What do you think? I am always interested in feedback.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.binarylogic.com/2008/10/05/tutorial-caching-virtual-attributes-in-the-database/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Searchlogic 1.3.0 &#8211; Adding modifiers into the mix</title>
		<link>http://www.binarylogic.com/2008/10/02/searchlogic-1-3-0-adding-modifiers-into-the-mix/</link>
		<comments>http://www.binarylogic.com/2008/10/02/searchlogic-1-3-0-adding-modifiers-into-the-mix/#comments</comments>
		<pubDate>Thu, 02 Oct 2008 12:40:00 +0000</pubDate>
		<dc:creator>benjohnson</dc:creator>
				<category><![CDATA[Searchlogic]]></category>
		<category><![CDATA[modifiers]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[searchgasm]]></category>

		<guid isPermaLink="false">0/2009/03/23/searchlogic-1-3-0-adding-modifiers-into-the-mix</guid>
		<description><![CDATA[Searchlogic 1.3.0 was released today and has some pretty cool features, mainly modifiers. I&#8217;m going to assume you know what Searchlogic is. If you don&#8217;t, you&#8217;re missing out. Take a quick glance at the readme on github, otherwise this article probably won&#8217;t make a whole lot of sense.
        [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://github.com/binarylogic/searchlogic">Searchlogic 1.3.0</a> was released today and has some pretty cool features, mainly modifiers. I&#8217;m going to assume you know what <a href="http://github.com/binarylogic/searchlogic">Searchlogic</a> is. If you don&#8217;t, you&#8217;re missing out. Take <a href="http://github.com/binarylogic/searchlogic">a quick glance at the readme</a> on github, otherwise this article probably won&#8217;t make a whole lot of sense.</p>
<p>            <span id="more-44"></span></p>
<h2>Why modifiers are necessary?</h2>
<p>ActiveRecord does a great job when it comes to keeping your code database agnostic. But I feel like it neglected searching when it came to that goal. What if you want to find all records that were created after 7am? Depending on your database you would have to do something like the following:</p>
<pre><code>MySQL:        HOUR(created_at)
PostgreSQL:   date_part('hour', created_at)
SQLite:       strftime('%H', created_at)
</code></pre>
<p>All of a sudden your app is not database agnostic. Oh no!</p>
<p>All of that bragging to your girlfriend about how you can switch databases in a matter of minutes was all a lie. How&#8217;s she going to feel when she finds out HOUR(created_at) is a MySQL specific function? Searchlogic to the rescue!</p>
<h2>Searchlogic modifiers</h2>
<p>Remember how you can do this in searchlogic?</p>
<pre class="cobalt">
<span class="Support">User</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">all</span></span><span class="Punctuation">(</span><span class="Constant"><span class="Punctuation">:</span>condition</span> <span class="Punctuation">=&gt;</span> <span class="Punctuation">{</span><span class="Constant"><span class="Punctuation">:</span>created_at_gt</span> <span class="Punctuation">=&gt;</span> <span class="Support">Time</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">parse</span></span><span class="Punctuation">(</span><span class="String"><span class="Punctuation">&quot;</span>Jan 1, 2008<span class="Punctuation">&quot;</span></span><span class="Punctuation">)</span><span class="Punctuation">}</span><span class="Punctuation">)</span>
<span class="Comment"><span class="Punctuation">#</span> =&gt; &quot;created_at &gt; 2008-01-01 00:00:00</span>
</pre>
<p>Now you can do this too:</p>
<pre class="cobalt">
<span class="Support">User</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">all</span></span><span class="Punctuation">(</span><span class="Constant"><span class="Punctuation">:</span>conditions</span> <span class="Punctuation">=&gt;</span> <span class="Punctuation">{</span><span class="Constant"><span class="Punctuation">:</span>hour_of_created_at_gt</span> <span class="Punctuation">=&gt;</span> <span class="Constant">10</span><span class="Punctuation">}</span><span class="Punctuation">)</span>
<span class="Comment"><span class="Punctuation">#</span> =&gt; HOUR(created_at) &gt; 10</span>
</pre>
<p>or this:</p>
<pre class="cobalt">
<span class="Support">User</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">all</span></span><span class="Punctuation">(</span><span class="Constant"><span class="Punctuation">:</span>conditions</span> <span class="Punctuation">=&gt;</span> <span class="Punctuation">{</span><span class="Constant"><span class="Punctuation">:</span>tan_of_sin_of_cos_of_minute_of_created_at_gt</span> <span class="Punctuation">=&gt;</span> <span class="Constant">20</span><span class="Punctuation">}</span><span class="Punctuation">)</span>
<span class="Comment"><span class="Punctuation">#</span> =&gt; TAN(SIN(COS(MINUTE(created_at)))) &gt; 20</span>
</pre>
<p>What the hell was that? That was me making the point that you can chain modifiers. Obviously a very unrealistic example, but cool none-the-less.</p>
<p><a href="http://github.com/binarylogic/searchlogic">Check out the readme for a list of modifiers</a> and <a href="http://github.com/binarylogic/searchlogic/tree/master/CHANGELOG.rdoc">check out the changelog for a complete list of changes</a></p>
<p>What do you think?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.binarylogic.com/2008/10/02/searchlogic-1-3-0-adding-modifiers-into-the-mix/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Tutorial: Pagination, ordering, and searching with Searchlogic</title>
		<link>http://www.binarylogic.com/2008/09/07/tutorial-pagination-ordering-and-searching-with-searchlogic/</link>
		<comments>http://www.binarylogic.com/2008/09/07/tutorial-pagination-ordering-and-searching-with-searchlogic/#comments</comments>
		<pubDate>Sun, 07 Sep 2008 01:05:00 +0000</pubDate>
		<dc:creator>benjohnson</dc:creator>
				<category><![CDATA[Searchlogic]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[ordering]]></category>
		<category><![CDATA[pagination]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[searchgasm]]></category>
		<category><![CDATA[searching]]></category>

		<guid isPermaLink="false">0/2009/03/23/tutorial-pagination-ordering-and-searching-with-searchlogic</guid>
		<description><![CDATA[Paginating, ordering, searching &#8211; no longer a pain in the ass
Maybe it&#8217;s not a pain in the ass for you, maybe it is, or maybe it is and you don&#8217;t know it. We&#8217;ll never know. Either way, this tutorial is pain-in-the-ass free. Guaranteed. That&#8217;s what this is all about, making your life easier when it [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Paginating, ordering, searching &#8211; no longer a pain in the ass</strong></p>
<p>Maybe it&#8217;s not a pain in the ass for you, maybe it is, or maybe it is and you don&#8217;t know it. We&#8217;ll never know. Either way, this tutorial is pain-in-the-ass free. Guaranteed. That&#8217;s what this is all about, making your life easier when it comes to paginating, ordering, and searching. Things you do multiple times in almost every application.</p>
<p>My solution: <a href="http://github.com/binarylogic/searchlogic">Searchlogic</a>. It has saved me a lot time, shortened my code, and ultimately given me the proper tools to paginate, order, and search my data. Hopefully it will do the same for you.</p>
<p>            <span id="more-13"></span></p>
<p>Enough talk, let&#8217;s dive in.</p>
<p>&#8220;Does this really work? Am I about to waste my time?&#8221;. I hope not. But just for you, I made this live example:</p>
<h3><a href="http://searchlogic_example.binarylogic.com">Live example based on this tutorial</a></h3>
<p>Paginating, ordering, and searching doesn&#8217;t get any easier than this. Before we start I want to make the following assumptions about you:</p>
<ol>
<li>You have a working rails application on rails edge (rake rails:freeze:edge)</li>
<li>You have the following model structure: UserGroup =&gt; User =&gt; Order (=&gt; = has_many). Make sure you have the has_many and belongs_to relationships set up. The fields are irrelevant, just change the field names in the view to whatever you have.</li>
</ol>
<div class="spacer5"></div>
<h2>1. Install <a href="http://github.com/binarylogic/searchlogic">Searchlogic</a></h2>
<pre class="cobalt">
$ sudo gem install searchlogic
</pre>
<p>Now add the gem dependency to your rails config:</p>
<pre class="cobalt">
<span class="Comment"><span class="Punctuation">#</span> config/environment.rb</span>
config<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">gem</span></span> <span class="String"><span class="Punctuation">&quot;</span>searchlogic<span class="Punctuation">&quot;</span></span>
</pre>
<p>As always you can install searchlogic as a plugin, but plugins are becoming a thing of the past. I recommend the above approach, but here is the plugin installation if you prefer to do it this way:</p>
<pre class="cobalt">
$ script/plugin install git://github.com/binarylogic/searchlogic.git
</pre>
<div class="spacer5"></div>
<h2>2. Create your controller</h2>
<p>Let&#8217;s create a controller that searches, orders, and paginates users. Like an admin area. Create app/controllers/users_controller.rb with the following content:</p>
<pre class="cobalt">
<span class="Comment"><span class="Punctuation">#</span> app/controllers/users_controller.rb</span>
<span class="Keyword">class</span> <span class="Entity">UsersController<span class="EntityInheritedClass"> <span class="Punctuation">&lt;</span> ApplicationController</span></span>
    <span class="Keyword">def</span> <span class="Entity">index</span>
        <span class="Variable"><span class="Punctuation">@</span>search</span> <span class="Keyword">=</span> <span class="Support">User</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">new_search</span></span><span class="Punctuation">(</span>params<span class="Punctuation">[</span><span class="Constant"><span class="Punctuation">:</span>search</span><span class="Punctuation">]</span><span class="Punctuation">)</span>
        <span class="Variable"><span class="Punctuation">@</span>users</span><span class="Punctuation">,</span> <span class="Variable"><span class="Punctuation">@</span>users_count</span> <span class="Keyword">=</span> <span class="Variable"><span class="Punctuation">@</span>search</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">all</span></span><span class="Punctuation">,</span> <span class="Variable"><span class="Punctuation">@</span>search</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">count</span></span>
    <span class="Keyword">end</span>
<span class="Keyword">end</span>
</pre>
<h3>What did we do here?</h3>
<p>It&#8217;s simple actually, if you haven&#8217;t looked at <a href="http://github.com/binarylogic/searchlogic">Searchlogic</a> I suggest you take a quick glance. I&#8217;m not going to get into crazy detail about what it does, because the README in the library covers that, but to make this short it &#8220;enhances&#8221; searching with ActiveRecord.</p>
<p>Notice that we started a new search with the @search object. This lets you search via an object, which is really handy for your view, which you will see below. It also added in some nifty methods such as page, per_page, order_by, order_as, and a plethora of conditions for each of your columns. The second line does a simple search and counts the results. The thing to remember here is that the .count method ignores pagination. It ignores the limit and offset values. So if you want to know how many users matched the search, use count, not @users.size. If the first page is limited to 10 reconds @user.size will return 10.</p>
<div class="spacer5"></div>
<h2>3. Create the view and your&#8217;re done</h2>
<pre class="cobalt">
# app/views/users/index.html.erb
<span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> <span class="Keyword">if</span> <span class="Variable"><span class="Punctuation">@</span>users_count</span> <span class="Keyword">&gt;</span> <span class="Constant">0</span> <span class="Punctuation">%&gt;</span></span>
    <span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> <span class="Variable"><span class="Punctuation">@</span>users_count</span> <span class="Punctuation">%&gt;</span></span> users found

    <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">table</span> <span class="MetaTagA">border</span>=<span class="String"><span class="Punctuation">&quot;</span>1<span class="Punctuation">&quot;</span></span> <span class="MetaTagA">cellpadding</span>=<span class="String"><span class="Punctuation">&quot;</span>5<span class="Punctuation">&quot;</span></span><span class="Punctuation">&gt;</span></span>
        <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">tr</span><span class="Punctuation">&gt;</span></span>
            <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">th</span><span class="Punctuation">&gt;</span></span><span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> order_by_link <span class="Constant"><span class="Punctuation">:</span>id</span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">th</span><span class="Punctuation">&gt;</span></span>
            <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">th</span><span class="Punctuation">&gt;</span></span><span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> order_by_link <span class="Constant"><span class="Punctuation">:</span>user_group</span> <span class="Punctuation">=&gt;</span> <span class="Constant"><span class="Punctuation">:</span>name</span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">th</span><span class="Punctuation">&gt;</span></span>
            <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">th</span><span class="Punctuation">&gt;</span></span><span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> order_by_link <span class="Constant"><span class="Punctuation">:</span>first_name</span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">th</span><span class="Punctuation">&gt;</span></span>
            <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">th</span><span class="Punctuation">&gt;</span></span><span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> order_by_link <span class="Constant"><span class="Punctuation">:</span>last_name</span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">th</span><span class="Punctuation">&gt;</span></span>
            <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">th</span><span class="Punctuation">&gt;</span></span><span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> order_by_link <span class="Punctuation">[</span><span class="Constant"><span class="Punctuation">:</span>email</span><span class="Punctuation">,</span> <span class="Constant"><span class="Punctuation">:</span>first_name</span><span class="Punctuation">]</span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">th</span><span class="Punctuation">&gt;</span></span>
        <span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">tr</span><span class="Punctuation">&gt;</span></span>
        <span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> <span class="Variable"><span class="Punctuation">@</span>users</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">each</span></span> <span class="Keyword">do </span><span class="Punctuation">|</span><span class="Variable">user</span><span class="Punctuation">|</span> <span class="Punctuation">%&gt;</span></span>
            <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">tr</span><span class="Punctuation">&gt;</span></span>
                <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">td</span><span class="Punctuation">&gt;</span></span><span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> user<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">id</span></span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">td</span><span class="Punctuation">&gt;</span></span>
                <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">td</span><span class="Punctuation">&gt;</span></span><span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> user<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">user_group</span></span> <span class="Keyword">?</span> user<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">user_group</span></span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">name</span></span> <span class="Punctuation">:</span> <span class="String"><span class="Punctuation">&quot;</span>-<span class="Punctuation">&quot;</span></span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">td</span><span class="Punctuation">&gt;</span></span>
                <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">td</span><span class="Punctuation">&gt;</span></span><span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> user<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">first_name</span></span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">td</span><span class="Punctuation">&gt;</span></span>
                <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">td</span><span class="Punctuation">&gt;</span></span><span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> user<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">last_name</span></span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">td</span><span class="Punctuation">&gt;</span></span>
                <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">td</span><span class="Punctuation">&gt;</span></span><span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> user<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">email</span></span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">td</span><span class="Punctuation">&gt;</span></span>
            <span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">tr</span><span class="Punctuation">&gt;</span></span>
        <span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> <span class="Keyword">end</span> <span class="Punctuation">%&gt;</span></span>
    <span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">table</span><span class="Punctuation">&gt;</span></span>

    <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">br</span> /<span class="Punctuation">&gt;</span></span>
    <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">br</span> /<span class="Punctuation">&gt;</span></span>

    Per page: <span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> per_page_select <span class="Punctuation">%&gt;</span></span>

    <span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> <span class="Keyword">if</span> <span class="Variable"><span class="Punctuation">@</span>search</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">page_count</span></span> <span class="Keyword">&gt;</span> <span class="Constant">1</span> <span class="Punctuation">%&gt;</span></span>
        <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">br</span> /<span class="Punctuation">&gt;</span></span>Page: <span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> page_select <span class="Punctuation">%&gt;</span></span>
    <span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> <span class="Keyword">end</span> <span class="Punctuation">%&gt;</span></span>
<span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> <span class="Keyword">else</span> <span class="Punctuation">%&gt;</span></span>
    No users were returned
<span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> <span class="Keyword">end</span> <span class="Punctuation">%&gt;</span></span>
</pre>
<h3>What did we do here?</h3>
<p>All that we did was iterate through our users, list them in a table format, and then add page and per_page controls. Notice any unusual helpers? (order_by_link, per_page_select, and page_select). I won&#8217;t go into detail about these helpers because its all <a href="http://searchlogic.rubyforge.org">in the documentation</a> under Searchlogic::Helpers::ControlTypes.</p>
<p>These are only a few ways to use these helpers, this is really just the tip of the iceberg. The sky is the limit: create a select that lets users navigate through the pages, create a list of links (like flickr) that lets you navigate through pages, create a link that lets you order by any number of columns you want, etc. I know ruby has a bad rep when it comes to documentation, but I actually put some decent time into the <a href="http://searchlogic.rubyforge.org">Searchlogic documentation</a> and I think you will find it helpful. That&#8217;s your best resource for finding out everything <a href="http://github.com/binarylogic/searchlogic">Searchlogic</a> has to offer.</p>
<div class="spacer5"></div>
<h2>Adding a search form</h2>
<p>&#8220;This is all great, but you said I could search my data&#8221;. Searching your data is just as easy. Just add this to the top of your index.html.erb</p>
<pre class="cobalt">
# app/views/users/index.html.erb
<span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> form_for <span class="Variable"><span class="Punctuation">@</span>search</span> <span class="Keyword">do </span><span class="Punctuation">|</span><span class="Variable">f</span><span class="Punctuation">|</span> <span class="Punctuation">%&gt;</span></span>
    <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">fieldset</span><span class="Punctuation">&gt;</span></span>
        <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">legend</span><span class="Punctuation">&gt;</span></span>Search Users<span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">legend</span><span class="Punctuation">&gt;</span></span>

        <span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> f<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">fields_for</span></span> <span class="Variable"><span class="Punctuation">@</span>search</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">conditions</span></span> <span class="Keyword">do </span><span class="Punctuation">|</span><span class="Variable">users</span><span class="Punctuation">|</span> <span class="Punctuation">%&gt;</span></span>
            <span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> users<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">label</span></span> <span class="Constant"><span class="Punctuation">:</span>first_name_keywords</span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">br</span> /<span class="Punctuation">&gt;</span></span>
            <span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> users<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">text_field</span></span> <span class="Constant"><span class="Punctuation">:</span>first_name_keywords</span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">br</span> /<span class="Punctuation">&gt;</span></span>
            <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">br</span> /<span class="Punctuation">&gt;</span></span>

            <span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> users<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">fields_for</span></span> users<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">object</span></span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">orders</span></span> <span class="Keyword">do </span><span class="Punctuation">|</span><span class="Variable">orders</span><span class="Punctuation">|</span> <span class="Punctuation">%&gt;</span></span>
                <span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> orders<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">label</span></span> <span class="Constant"><span class="Punctuation">:</span>total_gt</span><span class="Punctuation">,</span> <span class="String"><span class="Punctuation">&quot;</span>Has orders with a total greater than<span class="Punctuation">&quot;</span></span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">br</span> /<span class="Punctuation">&gt;</span></span>
                $<span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> orders<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">text_field</span></span> <span class="Constant"><span class="Punctuation">:</span>total_gt</span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">br</span> /<span class="Punctuation">&gt;</span></span>
                <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">br</span> /<span class="Punctuation">&gt;</span></span>
            <span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> <span class="Keyword">end</span> <span class="Punctuation">%&gt;</span></span>

            <span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> users<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">fields_for</span></span> users<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">object</span></span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">user_group</span></span> <span class="Keyword">do </span><span class="Punctuation">|</span><span class="Variable">user_group</span><span class="Punctuation">|</span> <span class="Punctuation">%&gt;</span></span>
                <span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> user_group<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">label</span></span> <span class="Constant"><span class="Punctuation">:</span>name_starts_with</span><span class="Punctuation">,</span> <span class="String"><span class="Punctuation">&quot;</span>Belongs to user group with name that starts with<span class="Punctuation">&quot;</span></span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">br</span> /<span class="Punctuation">&gt;</span></span>
                <span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> user_group<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">text_field</span></span> <span class="Constant"><span class="Punctuation">:</span>name_starts_with</span> <span class="Punctuation">%&gt;</span></span><span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">br</span> /<span class="Punctuation">&gt;</span></span>
                <span class="MetaTagA"><span class="Punctuation">&lt;</span><span class="MetaTagA">br</span> /<span class="Punctuation">&gt;</span></span>
            <span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> <span class="Keyword">end</span> <span class="Punctuation">%&gt;</span></span>
        <span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> <span class="Keyword">end</span> <span class="Punctuation">%&gt;</span></span>
    <span class="MetaTagA"><span class="Punctuation">&lt;/</span><span class="MetaTagA">fieldset</span><span class="Punctuation">&gt;</span></span>
    <span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> f<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">submit</span></span> <span class="String"><span class="Punctuation">&quot;</span>Search<span class="Punctuation">&quot;</span></span> <span class="Punctuation">%&gt;</span></span>
<span class="EmbeddedSource"><span class="Punctuation">&lt;%</span> <span class="Keyword">end</span> <span class="Punctuation">%&gt;</span></span>
</pre>
<p>As I mentioned above <a href="http://github.com/binarylogic/searchlogic">Searchlogic</a> creates default conditions on your columns based on the type. Letting you use a form builder to call those conditions. When it receives these conditions on the back-end it will do its &#8220;magic&#8221; and creates the proper SQL. Don&#8217;t worry about SQL injections, <a href="http://github.com/binarylogic/searchlogic">Searchlogic</a> has you covered on that (see <a href="http://searchlogic.rubyforge.org">the documentation</a> for more info).</p>
<p>What&#8217;s great about this method of searching?</p>
<ol>
<li>Your search logic is in one place: the view.</li>
<li>You can add conditions by doing f.text_field &#8220;[column name]_[condition]&#8220;. So when your picky client calls up and says &#8220;Hey, we need a search field for finding emails that end with&#8230;&#8221; No prob: f.text_field :email_ends_with. Done!</li>
<li>You can traverse your relationships with fields_for and set conditions on related objects. Saweet!</li>
</ol>
<div class="spacer5"></div>
<h2>Ajaxified</h2>
<p>So you&#8217;re saying &#8220;this is great, but super old school, where&#8217;s the AJAX?!?!?&#8221; So you&#8217;re all about AJAX? No problem. In the example I have 3 examples: a <a href="http://searchlogic_example.binarylogic.com/non_ajax/users">non AJAX example</a>, an <a href="http://searchlogic_example.binarylogic.com/rails_ajax/users">AJAX example using the built in rails helpers</a>, and <a href="http://searchlogic_example.binarylogic.com/jquery/users">a jQuery AJAX example</a>. Check them out. You can <a href="https://github.com/binarylogic/searchlogic_example">view the source of the examples on github</a> (each example if named spaced into its own controller). On a side note, I highly recommend <a href="http://jquery.com/">jQuery</a>. I recently started using it and love it. I actually get excited to write javascript because I always find something new when digging through the documentation or plugins and unobtrusive javascript never felt so good.</p>
<div class="spacer5"></div>
<h2>Some helpful links</h2>
<p>This tutorial is really just the tip of the ice berg with <a href="http://github.com/binarylogic/searchlogic">Searchlogic</a>. Checkout these links to see all it has to offer:</p>
<ul>
<li><a href="http://searchlogic_example.binarylogic.com">Live example based on this tutorial</a></li>
<li><a href="http://github.com/binarylogic/searchlogic_example">Source code for the live tutorial</a></li>
<li><a href="http://github.com/binarylogic/searchlogic">Searchlogic, the library that makes all of this magic happen</a></li>
<li><a href="http://searchlogic.rubyforge.org">Searchlogic documentation</a></li>
</ul>
<p>I am always interested in hearing feedback. Let me know what you think, what you like, what you don&#8217;t, that you hate the name, etc. I love criticism. <a href="http://github.com/binarylogic/searchlogic">Searchlogic</a> is under active development and I am always trying to improve it. I hope this tutorial was helpful to you and ultimately makes your life easier.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.binarylogic.com/2008/09/07/tutorial-pagination-ordering-and-searching-with-searchlogic/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
		<item>
		<title>Searchlogic released!</title>
		<link>http://www.binarylogic.com/2008/09/01/searchlogic-released/</link>
		<comments>http://www.binarylogic.com/2008/09/01/searchlogic-released/#comments</comments>
		<pubDate>Mon, 01 Sep 2008 21:56:00 +0000</pubDate>
		<dc:creator>benjohnson</dc:creator>
				<category><![CDATA[Searchlogic]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[searchgasm]]></category>
		<category><![CDATA[searching]]></category>

		<guid isPermaLink="false">0/2009/03/23/searchlogic-released</guid>
		<description><![CDATA[Searchlogic&#8217;s inspiration comes right from ActiveRecord. ActiveRecord lets you create objects that represent a record in the database, so why can&#8217;t you create objects that represent searching the database? Now you can! It&#8217;s searching, ordering, and pagination all in one.
            
Enough said, let me [...]]]></description>
			<content:encoded><![CDATA[<p><strong><a href="http://github.com/binarylogic/searchlogic/">Searchlogic&#8217;s</a> inspiration comes right from ActiveRecord. ActiveRecord lets you create objects that represent a record in the database, so why can&#8217;t you create objects that represent searching the database? Now you can! It&#8217;s searching, ordering, and pagination all in one.</strong></p>
<p>            <span id="more-12"></span></p>
<p>Enough said, let me show you some of my favorite features. If you are still interested you can just jump over to the <a href="http://github.com/binarylogic/searchlogic/">searchlogic github page</a> for a more detailed explanation.</p>
<p><strong>For the following examples lets assume these relationships: User =&gt; Orders =&gt; LineItems</strong></p>
<h2>Simple Searching Example</h2>
<pre class="cobalt">
<span class="Support">User</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">all</span></span><span class="Punctuation">(</span>
  <span class="Constant"><span class="Punctuation">:</span>conditions</span> <span class="Punctuation">=&gt;</span> <span class="Punctuation">{</span>
    <span class="Constant"><span class="Punctuation">:</span>first_name_contains</span> <span class="Punctuation">=&gt;</span> <span class="String"><span class="Punctuation">&quot;</span>Ben<span class="Punctuation">&quot;</span></span><span class="Punctuation">,</span>          <span class="Comment"><span class="Punctuation">#</span> first_name like '%Ben%'</span>
    <span class="Constant"><span class="Punctuation">:</span>email_ends_with</span> <span class="Punctuation">=&gt;</span> <span class="String"><span class="Punctuation">&quot;</span>binarylogic.com<span class="Punctuation">&quot;</span></span>   <span class="Comment"><span class="Punctuation">#</span> email like '%binarylogic.com'</span>
  <span class="Punctuation">}</span><span class="Punctuation">,</span>
  <span class="Constant"><span class="Punctuation">:</span>per_page</span> <span class="Punctuation">=&gt;</span> <span class="Constant">20</span><span class="Punctuation">,</span>                      <span class="Comment"><span class="Punctuation">#</span> limit 20</span>
  <span class="Constant"><span class="Punctuation">:</span>page</span> <span class="Punctuation">=&gt;</span> <span class="Constant">3</span><span class="Punctuation">,</span>                           <span class="Comment"><span class="Punctuation">#</span> offset 40, which starts us on page 3</span>
  <span class="Constant"><span class="Punctuation">:</span>order_as</span> <span class="Punctuation">=&gt;</span> <span class="String"><span class="Punctuation">&quot;</span>ASC<span class="Punctuation">&quot;</span></span><span class="Punctuation">,</span>
  <span class="Constant"><span class="Punctuation">:</span>order_by</span> <span class="Punctuation">=&gt;</span> <span class="Punctuation">{</span><span class="Constant"><span class="Punctuation">:</span>user_group</span> <span class="Punctuation">=&gt;</span> <span class="Constant"><span class="Punctuation">:</span>name</span><span class="Punctuation">}</span>   <span class="Comment"><span class="Punctuation">#</span> order user_groups.name ASC</span>
<span class="Punctuation">)</span>
</pre>
<p>same as above, but object based</p>
<pre class="cobalt">
search <span class="Keyword">=</span> <span class="Support">User</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">new_search</span></span>
search<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">conditions</span></span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">first_name_contains</span></span> <span class="Keyword">=</span> <span class="String"><span class="Punctuation">&quot;</span>Ben<span class="Punctuation">&quot;</span></span>
search<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">conditions</span></span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">email_ends_with</span></span> <span class="Keyword">=</span> <span class="String"><span class="Punctuation">&quot;</span>binarylogic.com<span class="Punctuation">&quot;</span></span>
search<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">per_page</span></span> <span class="Keyword">=</span> <span class="Constant">20</span>
search<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">page</span></span> <span class="Keyword">=</span> <span class="Constant">3</span>
search<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">order_as</span></span> <span class="Keyword">=</span> <span class="String"><span class="Punctuation">&quot;</span>ASC<span class="Punctuation">&quot;</span></span>
search<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">order_by</span></span> <span class="Keyword">=</span> <span class="Punctuation">{</span><span class="Constant"><span class="Punctuation">:</span>user_group</span> <span class="Punctuation">=&gt;</span> <span class="Constant"><span class="Punctuation">:</span>name</span><span class="Punctuation">}</span>
search<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">all</span></span>
</pre>
<p>In both examples, instead of using the &#8220;all&#8221; method you could use any search method: first, find(:all), find(:first), count, sum, average, etc, just like ActiveRecord.</p>
<h2>The beauty of searchlogic, integration with rails</h2>
<p>Using Searchlogic in rails is the best part, because rails has all kinds of nifty methods to make dealing with ActiveRecord objects quick and easy, especially with forms. So let’s take advantage of them! That’s the idea behind this plugin. Searchlogic is searching, ordering, and pagination all rolled into one simple plugin. Take all of that pagination and searching cruft out of your models and let Searchlogic handle it. Check it out: </p>
<pre class="cobalt">
<span class="Comment"><span class="Punctuation">#</span> app/controllers/users_controller.rb</span>
<span class="Keyword">def</span> <span class="Entity">index</span>
    <span class="Variable"><span class="Punctuation">@</span>search</span> <span class="Keyword">=</span> <span class="Support">User</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">new_search</span></span><span class="Punctuation">(</span>params<span class="Punctuation">[</span><span class="Constant"><span class="Punctuation">:</span>search</span><span class="Punctuation">]</span><span class="Punctuation">)</span>
    <span class="Variable"><span class="Punctuation">@</span>users</span><span class="Punctuation">,</span> <span class="Variable"><span class="Punctuation">@</span>users_count</span> <span class="Keyword">=</span> <span class="Variable"><span class="Punctuation">@</span>search</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">all</span></span><span class="Punctuation">,</span> <span class="Variable"><span class="Punctuation">@</span>search</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">count</span></span>
<span class="Keyword">end</span>
</pre>
<p>Now your view.</p>
<pre class="cobalt">
# app/views/users/index.html.haml
- form_for @search do |f|
 - f.fields_for @search.conditions do |users|
  = users.text_field :first_name_contains
  = users.calendar_date_select :created_after # nice rails plugin for replacing date_select
  - users.fields_for users.object.orders do |orders|
    = orders.select :total_gt, (1..100)
  = f.submit &quot;Search&quot;

- if @users_count &gt; 0
  %table
    %tr
      %th= order_by_link :account =&gt; :name
      %th= order_by_link :first_name
      %th= order_by_link :last_name
      %th= order_by_link :email
    - @users.each do |user|
      %tr
        %td= user.first_name
        %td= user.last_name
        %td= user.email

  Per page:
  = per_page_select
  Page:
  = page_select
- else
  No users returned
</pre>
<h3>Things to notice</h3>
<ol>
<li>Passing a search object right into form_for and fields_for</li>
<li>The built in conditions for each column and how you can traverse the relationships and set conditions on them</li>
<li>The order_by_link helper</li>
<li>The page_select and per_page_select helpers</li>
<li>All of your search logic is in 1 spot: your view. Nice and DRY.</li>
</ol>
<p><strong><a href="http://www.binarylogic.com/2008/9/7/tutorial-pagination-ordering-and-searching-with-searchlogic">See my tutorial on this example</a></strong></p>
<h2>Nifty methods for searching trees</h2>
<p>Just like the conditions you automatically get with each column. You automatically get conditions for searching tree data structures, if you&#8217;re model is a tree data structure.</p>
<pre class="cobalt">
<span class="Comment"><span class="Punctuation">#</span> User is a tree data structure.</span>
conditions <span class="Keyword">=</span> <span class="Support">User</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">new_conditions</span></span>
conditions<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">child_of</span></span> <span class="Keyword">=</span> <span class="Support">User</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">roots</span></span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">first</span></span>                  <span class="Comment"><span class="Punctuation">#</span> Finds all children</span>
conditions<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">sibling_of</span></span> <span class="Keyword">=</span> <span class="Support">User</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">first</span></span>                      <span class="Comment"><span class="Punctuation">#</span> Finds siblings</span>
conditions<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">descendant_of</span></span> <span class="Keyword">=</span> <span class="Support">User</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">roots</span></span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">first</span></span>             <span class="Comment"><span class="Punctuation">#</span> Finds all children, grandchildren, etc</span>
conditions<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">inclusive_descendant_of</span></span> <span class="Keyword">=</span> <span class="Support">User</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">roots</span></span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">first</span></span>   <span class="Comment"><span class="Punctuation">#</span> Includes root + children, grandchildren, etc.</span>
</pre>
<p>Any of these conditions can accept a User object or a User id.</p>
<h2>Get Started</h2>
<p>Check out the GitHub repository to get started:</p>
<p><strong><a href="http://github.com/binarylogic/searchlogic/">http://github.com/binarylogic/searchlogic/</a></strong></p>
<p>Or a tutorial I posted on using Searchlogic in rails:</p>
<p><strong><a href="http://www.binarylogic.com/2008/9/7/tutorial-pagination-ordering-and-searching-with-searchlogic">http://www.binarylogic.com/2008/9/7/tutorial-pagination-ordering-and-searching-with-searchlogic</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.binarylogic.com/2008/09/01/searchlogic-released/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
	</channel>
</rss>
