<?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; rails</title>
	<atom:link href="http://www.binarylogic.com/tag/rails/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>Searchlogic v2 beta released</title>
		<link>http://www.binarylogic.com/2009/06/09/searchlogic-v2-beta-released/</link>
		<comments>http://www.binarylogic.com/2009/06/09/searchlogic-v2-beta-released/#comments</comments>
		<pubDate>Tue, 09 Jun 2009 04:07:14 +0000</pubDate>
		<dc:creator>benjohnson</dc:creator>
				<category><![CDATA[Searchlogic]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[v2]]></category>

		<guid isPermaLink="false">http://www.binarylogic.com/?p=756</guid>
		<description><![CDATA[Searchlogic v2 beta was released today, it is a complete rewrite of the library, no code was reused. Right now its in a separate branch under the Searchlogic project, and will be merged when it is taken out of beta status. Let me explain how it&#8217;s different.
So, the project I&#8217;m working on now required something [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://github.com/binarylogic/searchlogic/tree/v2">Searchlogic v2 beta</a> was released today, it is a <strong>complete</strong> rewrite of the library, no code was reused. Right now its in a separate branch under the <a href="http://github.com/binarylogic/searchlogic/tree/master">Searchlogic project</a>, and will be merged when it is taken out of beta status. Let me explain how it&#8217;s different.</p>
<p>So, the project I&#8217;m working on now required something from Searchlogic v1 that it couldn&#8217;t provide. That is, searching with existing named scopes. I could do this, but it wasn&#8217;t as elegant as it was with the built in conditions (Ex: username_like, etc.).</p>
<h2>The idea behind Searchlogic v2</h2>
<p>So this got me thinking, how can I get Searchlogic v1 to use existing named scopes? That&#8217;s when it hit me, why not use named scopes for everything?<span id="more-756"></span>I think we can all agree named scopes are the heart of searching and breaking up common search logic in your models. Instead of having all of this crazy logic write SQL and chain it together, as in v1, why not have Searchlogic dynamically create these common named scopes for you and then just leverage those? That&#8217;s exactly what v2 does. Instead of going into detail about v2, check out the <a href="http://github.com/binarylogic/searchlogic/tree/v2">current README</a>. It explains everything v2 has to offer up to this point.</p>
<p>The best part about this approach is that it fits nicely into your application. All that it is doing is creating named scopes. More importantly, if you need some condition that Searchlogic doesn&#8217;t offer, no problem, just create your own named scope. This is what you should be doing anyways.</p>
<p>To bring it all home, let me show a simple search form that uses v2. Assume we have</p>
<pre>
User(name:string, age:integer)
Order(user_id:integer, total:float)

User.has_many :orders
User.named_scope :four_year_olds, :conditions => {:age => 4}
User.named_scope :name_sounds_like, lamda { |value| {:conditions => ["name SOUNDS LIKE ?", value]} }
</pre>
<p>Your search form could look like this:</p>
<pre class="ruby">
- form_for @search do |f|
  = f.text_field :name_like
  = f.select :age_greater_than, (1..100)
  = f.text_field :orders_total_less_than
  = f.text_field :name_sounds_like
  = f.check_box :four_year_olds
  = f.submit
</pre>
<p>Notice the use of custom named scopes. Also the other conditions are also named scopes that searchlogic dynamically defines as you need them.</p>
<h2>The best part of v2</h2>
<ul>
<li><strong>V1:</strong> ~2300 lines of code</li>
<li><strong>V2:</strong> ~350 lines of code</li>
</ul>
<p>As you might have saw <a href="http://www.binarylogic.com/2009/04/17/need-some-help-searchlogic-20/">in this post</a> Searchlogic v1 was too big for me to handle. The issues people were having would take way too long to solve and I just didn&#8217;t like the code. The library really wasn&#8217;t advancing and it was just an annoyance. It was regretably the first library I ever wrote, and as such there are a lot of things I would do differently, which should be evident in v2.</p>
<p>That being said, v2 is lean, makes sense, and just feels right. I&#8217;m really looking forward to maintaing the library and seeing where it goes. I hope everyone enjoys it. Let me know what you think. There are just a couple of things left to do before I officially release it.</p>
<h2>Applications using v1</h2>
<p>Lastly, because this is such a big change, backwards compatibility <em>will</em> be broken. Before I officially release the library I will write a document explaining the differences and how to transition. In the mean time, your gem declarations in your application should look like this, so that your app doesn&#8217;t break when the new version is released:</p>
<pre>
 config.gem "searchlogic", :version => "~> 1.6.6"
# the ~ will let you advance minor and tiny versions, but not major versions.
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.binarylogic.com/2009/06/09/searchlogic-v2-beta-released/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Tutorial: Using OpenID with Authlogic</title>
		<link>http://www.binarylogic.com/2008/11/21/tutorial-using-openid-with-authlogic/</link>
		<comments>http://www.binarylogic.com/2008/11/21/tutorial-using-openid-with-authlogic/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 02:12:00 +0000</pubDate>
		<dc:creator>benjohnson</dc:creator>
				<category><![CDATA[Authlogic]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">0/2009/03/30/tutorial-using-openid-with-authlogic</guid>
		<description><![CDATA[Please note this tutorial is outdated and has been deleted, please see the official Authlogic OpenID addon, which makes OpenID integration extrmely easy. The content that used to be in this tutorial was for Authlogic 1.x and will not work properly with Authlogic 2.x.
]]></description>
			<content:encoded><![CDATA[<p><strong>Please note this tutorial is outdated and has been deleted, please see <a href="http://github.com/binarylogic/authlogic_openid">the official Authlogic OpenID addon</a>, which makes OpenID integration extrmely easy. The content that used to be in this tutorial was for Authlogic 1.x and will not work properly with Authlogic 2.x.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.binarylogic.com/2008/11/21/tutorial-using-openid-with-authlogic/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Authlogic shares the love, merb support added</title>
		<link>http://www.binarylogic.com/2008/11/05/authlogic-shares-the-love-merb-support-added/</link>
		<comments>http://www.binarylogic.com/2008/11/05/authlogic-shares-the-love-merb-support-added/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 19:06:00 +0000</pubDate>
		<dc:creator>benjohnson</dc:creator>
				<category><![CDATA[Authlogic]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[merb]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">0/2009/03/23/authlogic-shares-the-love-merb-support-added</guid>
		<description><![CDATA[Rails doesn&#8217;t have to hog all of the Authlogic love, it&#8217;s time to start sharing. So I decided to send a little love to the merb peeps and add in a merb adapter. Just install the Authlogic gem and include it as a dependency and you are good to go. Authentication in your app is [...]]]></description>
			<content:encoded><![CDATA[<p>Rails doesn&#8217;t have to hog all of the <a href="http://github.com/binarylogic/authlogic">Authlogic</a> love, it&#8217;s time to start sharing. So I decided to send a little love to the merb peeps and add in a merb adapter. Just install the <a href="http://github.com/binarylogic/authlogic">Authlogic</a> gem and include it as a dependency and you are good to go. Authentication in your app is as easy as setting up a resource for a model.</p>
<p>I think this is just the beginning though, here are my thoughts&#8230;.</p>
<p>            <span id="more-163"></span></p>
<h2>The Big Picture</h2>
<p>Thanks to things like <a href="http://rack.rubyforge.org/">Rack</a>, the MVC design pattern, and ActiveRecord / DataMapper, all of these frameworks look very similar. They all have a similar pattern, which is the inherent nature of the MVC design pattern. So I decided to take advantage of this with Authlogic. Any specific framework implementation is extracted out into an adapter. Similar to how ActiveRecord has an adapter for each database type, except the Authlogic adapters are much simpler.</p>
<p>Probably the main reason these adapters are so simple / similar is because of Rack. Thanks to Rack, there is a request standard across all of these frameworks. &#8220;But Ben, why not skip all of this nonsense and implement this right into Rack?&#8221;. The reason I didn&#8217;t go right into Rack is&#8230;</p>
<ol>
<li>Not every &#8220;Rack compatible&#8221; framework uses the Rack libraries. After digging through the rails internals I found that the RackRequest class extends AbstractRequest, which has nothing to do with Rack. Lastly, older versions of rails aren&#8217;t rack compatible.</li>
<li>I need to hook into the controller anyways with a before_filter</li>
<li>With my implementation you get the best of both worlds. I designed the AbstractAdapter to conform to the rack standards, and any framework specific implementation can subclass this and do it&#8217;s magic.</li>
</ol>
<p>So what&#8217;s the big picture here? The big picture is that there is no reason Authlogic can&#8217;t be an authentication solution for virtually any ruby framework out there. Why reinvent the wheel for every framework?</p>
<h2>What about framework X?</h2>
<p>Since writing adapters for rails and merb was so simple, why not keep going? Here are a few frameworks I plan to write an adapter for:</p>
<ol>
<li><a href="http://www.mackframework.com/">Mack</a></li>
<li><a href="http://ramaze.net/">Ramaze</a></li>
<li><a href="http://sinatra.rubyforge.org/">Sinatra</a></li>
</ol>
<p>If you are feeling generous and want to write an adapter for a framework other than rails or merb, please do so. Let me know about it and I will add it into the source.</p>
<h2>Final thoughts</h2>
<p>Authlogic loves you regardless of your framework</p>
]]></content:encoded>
			<wfw:commentRss>http://www.binarylogic.com/2008/11/05/authlogic-shares-the-love-merb-support-added/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Settingslogic, a great settings solution or the greatest?</title>
		<link>http://www.binarylogic.com/2008/11/03/settingslogic-a-great-settings-solution-or-the-greatest/</link>
		<comments>http://www.binarylogic.com/2008/11/03/settingslogic-a-great-settings-solution-or-the-greatest/#comments</comments>
		<pubDate>Mon, 03 Nov 2008 02:26:00 +0000</pubDate>
		<dc:creator>benjohnson</dc:creator>
				<category><![CDATA[Settingslogic]]></category>
		<category><![CDATA[config]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[settings]]></category>

		<guid isPermaLink="false">0/2009/03/23/settingslogic-a-great-settings-solution-or-the-greatest</guid>
		<description><![CDATA[If there is one thing we can all agree on, say it with me&#8230;ruby doesn&#8217;t have enough settings solutions. You finished the sentence without even reading it didn&#8217;t you?
Actually considering there are a million settings solutions, this is probably the last thing we need. That being said, I decided to add my own personal settings [...]]]></description>
			<content:encoded><![CDATA[<p>If there is one thing we can all agree on, say it with me&#8230;ruby doesn&#8217;t have enough settings solutions. You finished the sentence without even reading it didn&#8217;t you?</p>
<p>Actually considering there are a million settings solutions, this is probably the last thing we need. That being said, I decided to add my own personal settings solution to the mix called <a href="http://github.com/binarylogic/settingslogic/tree/master">Settingslogic</a>. It&#8217;s nothing crazy or new. Just a simple solution to a simple problem. <a href="http://github.com/binarylogic/settingslogic/tree/master">Settingslogic</a> provides globally accessible settings via an ERB enabled YAML file. It has been great for my apps, maybe you will enjoy it too. Here&#8217;s how it works&#8230;</p>
<p>            <span id="more-132"></span></p>
<h2>Create your settings</h2>
<p>This is a typical YAML file, notice ERB is allowed.</p>
<pre class="cobalt">
<span class="Comment"><span class="Punctuation">#</span> app/config/application.yml</span>
<span class="MetaTagA"><span class="MetaTagA">defaults</span><span class="Punctuation">:</span> </span><span class="Variable"><span class="Punctuation">&amp;</span>defaults</span>
  <span class="MetaTagA"><span class="MetaTagA">cool</span><span class="Punctuation">:</span></span>
    <span class="String"><span class="Entity">saweet<span class="Punctuation">:</span></span> <span class="String">nested settings</span></span>
  <span class="Constant"><span class="Entity">neat_setting<span class="Punctuation">:</span></span> 24</span>
  <span class="MetaTagA"><span class="MetaTagA">awesome_setting</span><span class="Punctuation">:</span> </span><span class="EmbeddedSource"><span class="Punctuation">&lt;%=</span> <span class="String"><span class="Punctuation">&quot;</span>Did you know 5 + 5 = <span class="Punctuation">&quot;</span></span> <span class="Keyword">+</span> <span class="Punctuation">(</span><span class="Constant">5</span> <span class="Keyword">+</span> <span class="Constant">5</span><span class="Punctuation">)</span> <span class="Keyword">+</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="MetaTagA">development</span><span class="Punctuation">:</span></span>
  <span class="Keyword"><span class="Entity">&lt;&lt;</span>: <span class="Keyword"><span class="Punctuation">*</span>defaults</span></span>
  <span class="Constant"><span class="Entity">neat_setting<span class="Punctuation">:</span></span> 800</span>

<span class="MetaTagA"><span class="MetaTagA">test</span><span class="Punctuation">:</span></span>
  <span class="Keyword"><span class="Entity">&lt;&lt;</span>: <span class="Keyword"><span class="Punctuation">*</span>defaults</span></span>

<span class="MetaTagA"><span class="MetaTagA">production</span><span class="Punctuation">:</span></span>
  <span class="Keyword"><span class="Entity">&lt;&lt;</span>: <span class="Keyword"><span class="Punctuation">*</span>defaults</span></span>
</pre>
<h2>Access your settings</h2>
<pre class="cobalt">
  &gt;&gt; RAILS_ENV
  =&gt; &quot;development&quot;

  &gt;&gt; Settings.cool
  =&gt; &quot;#&lt;Settingslogic::Settings ... &gt;&quot;

  &gt;&gt; Settings.cool.saweet
  =&gt; &quot;nested settings&quot;

  &gt;&gt; Settings.neat_setting
  =&gt; 800

  &gt;&gt; Settings.awesome_setting
  =&gt; &quot;Did you know 5 + 5 = 10?&quot;
</pre>
<h2>Give me more</h2>
<p>You got it!</p>
<ul>
<li><strong>Repository:</strong> <a href="http://github.com/binarylogic/settingslogic/tree/master">http://github.com/binarylogic/settingslogic/tree/master</a></li>
<li><strong>Documentation:</strong> <a href="http://settingslogic.rubyforge.org/">http://settingslogic.rubyforge.org/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.binarylogic.com/2008/11/03/settingslogic-a-great-settings-solution-or-the-greatest/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Authlogic released! Rails authentication done right.</title>
		<link>http://www.binarylogic.com/2008/10/25/authlogic-released-rails-authentication-done-right/</link>
		<comments>http://www.binarylogic.com/2008/10/25/authlogic-released-rails-authentication-done-right/#comments</comments>
		<pubDate>Sat, 25 Oct 2008 12:24:00 +0000</pubDate>
		<dc:creator>benjohnson</dc:creator>
				<category><![CDATA[Authlogic]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[restful]]></category>
		<category><![CDATA[session]]></category>

		<guid isPermaLink="false">0/2009/03/23/authlogic-released-rails-authentication-done-right</guid>
		<description><![CDATA[The last thing we need is another authentication solution for rails, right? That&#8217;s what I thought until I tried out some of the current solutions. None of them felt right. They were either too complicated, bloated, littered my application with tons of code, or were just confusing. This is not the simple / elegant rails [...]]]></description>
			<content:encoded><![CDATA[<p>The last thing we need is another authentication solution for rails, right? That&#8217;s what I thought until I tried out some of the current solutions. None of them felt right. They were either too complicated, bloated, littered my application with tons of code, or were just confusing. This is not the simple / elegant rails we all fell in love with. We need a &#8220;rails like&#8221; authentication solution. Authlogic is my attempt to satisfy that need&#8230;</p>
<p>What if you could have authentication up and running in minutes without having to run a generator? All because it&#8217;s simple, like everything else in rails.</p>
<p>What if creating a user session could be as simple as&#8230;</p>
<pre class="cobalt">
<span class="Support">UserSession</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">create</span></span><span class="Punctuation">(</span>params<span class="Punctuation">[</span><span class="Constant"><span class="Punctuation">:</span>user</span><span class="Punctuation">]</span><span class="Punctuation">)</span>
</pre>
<p>What if your user sessions controller could look just like your other controllers&#8230;</p>
<p>            <span id="more-103"></span></p>
<pre class="cobalt">
<span class="Keyword">class</span> <span class="Entity">UserSessionsController<span class="EntityInheritedClass"> <span class="Punctuation">&lt;</span> ApplicationController</span></span>
  <span class="Keyword">def</span> <span class="Entity">new</span>
    <span class="Variable"><span class="Punctuation">@</span>user_session</span> <span class="Keyword">=</span> <span class="Support">UserSession</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">new</span></span>
  <span class="Keyword">end</span>

  <span class="Keyword">def</span> <span class="Entity">create</span>
    <span class="Variable"><span class="Punctuation">@</span>user_session</span> <span class="Keyword">=</span> <span class="Support">UserSession</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">new</span></span><span class="Punctuation">(</span>params<span class="Punctuation">[</span><span class="Constant"><span class="Punctuation">:</span>user_session</span><span class="Punctuation">]</span><span class="Punctuation">)</span>
    <span class="Keyword">if</span> <span class="Variable"><span class="Punctuation">@</span>user_session</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">create</span></span>
      redirect_to account_url
    <span class="Keyword">else</span>
      render <span class="Constant"><span class="Punctuation">:</span>action</span> <span class="Punctuation">=&gt;</span> <span class="Constant"><span class="Punctuation">:</span>new</span>
    <span class="Keyword">end</span>
  <span class="Keyword">end</span>

  <span class="Keyword">def</span> <span class="Entity">destroy</span>
    current_user_session<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">destroy</span></span>
  <span class="Keyword">end</span>
<span class="Keyword">end</span>
</pre>
<p>Look familiar? If you didn&#8217;t know any better, you would think UserSession was an ActiveRecord model. I think that&#8217;s pretty cool. Why is that cool? Because it fits nicely into the RESTful development pattern and its a style we all know and love. Wouldn&#8217;t this be cool too&#8230;</p>
<pre class="cobalt">
<span class="Keyword">&lt;</span><span class="Keyword">%=</span> error_messages_for <span class="String"><span class="Punctuation">&quot;</span>user_session<span class="Punctuation">&quot;</span></span> <span class="String"><span class="Punctuation">%&gt;</span></span>
<span class="String">&lt;% form_for @user_session do |f| %<span class="Punctuation">&gt;</span></span>
  <span class="Keyword">&lt;</span><span class="Keyword">%=</span> f<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">label</span></span> <span class="Constant"><span class="Punctuation">:</span>login</span> <span class="String"><span class="Punctuation">%&gt;</span>&lt;br /<span class="Punctuation">&gt;</span></span>
  <span class="Keyword">&lt;</span><span class="Keyword">%=</span> f<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">text_field</span></span> <span class="Constant"><span class="Punctuation">:</span>login</span> <span class="String"><span class="Punctuation">%&gt;</span>&lt;br /<span class="Punctuation">&gt;</span></span>
  <span class="Keyword">&lt;</span>br <span class="Keyword">/</span><span class="Keyword">&gt;</span>
  <span class="Keyword">&lt;</span><span class="Keyword">%=</span> f<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">label</span></span> <span class="Constant"><span class="Punctuation">:</span>password</span> <span class="String"><span class="Punctuation">%&gt;</span>&lt;br /<span class="Punctuation">&gt;</span></span>
  <span class="Keyword">&lt;</span><span class="Keyword">%=</span> f<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">password_field</span></span> <span class="Constant"><span class="Punctuation">:</span>password</span> <span class="String"><span class="Punctuation">%&gt;</span>&lt;br /<span class="Punctuation">&gt;</span></span>
  <span class="Keyword">&lt;</span>br <span class="Keyword">/</span><span class="Keyword">&gt;</span>
  <span class="Keyword">&lt;</span><span class="Keyword">%=</span> f<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">submit</span></span> <span class="String"><span class="Punctuation">&quot;</span>Login<span class="Punctuation">&quot;</span></span> <span class="String"><span class="Punctuation">%&gt;</span></span>
<span class="String">&lt;% end %<span class="Punctuation">&gt;</span></span>
</pre>
<p>Or what about persisting the session&#8230;</p>
<pre class="cobalt">
<span class="Keyword">class</span> <span class="Entity">ApplicationController</span>
  helper_method <span class="Constant"><span class="Punctuation">:</span>current_user_session</span><span class="Punctuation">,</span> <span class="Constant"><span class="Punctuation">:</span>current_user</span>

  <span class="Keyword">protected</span>
    <span class="Keyword">def</span> <span class="Entity">current_user_session</span>
      <span class="Keyword">return</span> <span class="Variable"><span class="Punctuation">@</span>current_user_session</span> <span class="Keyword">if</span> <span class="Keyword">defined?</span><span class="Punctuation">(</span><span class="Variable"><span class="Punctuation">@</span>current_user_session</span><span class="Punctuation">)</span>
      <span class="Variable"><span class="Punctuation">@</span>current_user_session</span> <span class="Keyword">=</span> <span class="Support">UserSession</span><span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">find</span></span>
    <span class="Keyword">end</span>

    <span class="Keyword">def</span> <span class="Entity">current_user</span>
      <span class="Keyword">return</span> <span class="Variable"><span class="Punctuation">@</span>current_user</span> <span class="Keyword">if</span> <span class="Keyword">defined?</span><span class="Punctuation">(</span><span class="Variable"><span class="Punctuation">@</span>current_user</span><span class="Punctuation">)</span>
      <span class="Variable"><span class="Punctuation">@</span>current_user</span> <span class="Keyword">=</span> current_user_session <span class="Keyword">&amp;&amp;</span> current_user_session<span class="FunctionCall"><span class="Punctuation">.</span><span class="Entity">user</span></span>
    <span class="Keyword">end</span>
<span class="Keyword">end</span>
</pre>
<p>Authlogic makes this a reality.</p>
<h2>Reclaim your UsersController</h2>
<p>This is one of my favorite features that I think its pretty cool. It&#8217;s things like this that make a library great and let you know you are on the right track.</p>
<p>Just to clear up any confusion, Authlogic does not store the plain id in the session. It stores a token. This token changes with the password, this way stale sessions can not be persisted.</p>
<p>That being said..What if a user changes their password? You have to re-log them in with the new password, recreate the session, etc, pain in the ass. Or what if a user creates a new user account? You have to do the same thing. Here&#8217;s an even better one: what if a user is in the admin area and changes his own password? There might even be another place passwords can change. It shouldn&#8217;t matter, your code should be written in a way where you don&#8217;t have to remember to do this.</p>
<p>Instead of updating sessions all over the place, doesn&#8217;t it make sense to do this at a lower level? Like the User model? You&#8217;re saying &#8220;but Ben, models can&#8217;t mess around with sessions and cookies&#8221;. True&#8230;but Authlogic can, and you can access Authlogic just like a model. I know in most situations it&#8217;s not good practice to do this but I view this in the same class as sweepers, and feel like it actually is good practice here. User sessions are directly tied to users, they should be connected on the model level.</p>
<p>Fear not, because the acts_as_authentic method you call in your model takes care of this for you, by adding an after_create and after_update callback to automatically keep the session up to date. You don&#8217;t have to worry about it anymore. Don&#8217;t even think about it. Let your UsersController deal with users, not users <em>AND</em> sessions. <em>ANYTIME</em> the user changes his password in <em>ANY</em> way, his session will be updated.</p>
<p>Here is basically what is done&#8230;</p>
<pre class="cobalt">
<span class="Keyword">class</span> <span class="Entity">User<span class="EntityInheritedClass"> <span class="Punctuation">&lt;</span> ActiveRecord::Base</span></span>
  after_save <span class="Constant"><span class="Punctuation">:</span>maintain_sessions!</span>

  <span class="Keyword">private</span>
    <span class="Keyword">def</span> <span class="Entity">create_sessions!</span>
<span class="Comment">      <span class="Punctuation">#</span> create a new UserSession if they are not logged in</span>
    <span class="Keyword">end</span>

    <span class="Keyword">def</span> <span class="Entity">maintain_sessions!</span>
<span class="Comment">      <span class="Punctuation">#</span> If we aren't logged in at all and the password was changed, go ahead and log the user in</span>
<span class="Comment">      <span class="Punctuation">#</span> If we are logged in and the password has change, update the sessions</span>
    <span class="Keyword">end</span>
<span class="Keyword">end</span>
</pre>
<p>Obviously there is a little more to it than this, but hopefully this clarifies any confusion.</p>
<p>When things come together like this I think its a sign that you are doing something right. Put that in your pipe and smoke it!</p>
<h2>Authlogic arouses me</h2>
<p>That&#8217;s great, here are some resources:</p>
<ul>
<li><strong>Repository:</strong> <a href="http://github.com/binarylogic/authlogic">http://github.com/binarylogic/authlogic</a></li>
<li><strong>Documentation:</strong> <a href="http://authlogic.rubyforge.org/">http://authlogic.rubyforge.org/</a></li>
<li><strong>Tutorial:</strong> coming soon&#8230;</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.binarylogic.com/2008/10/25/authlogic-released-rails-authentication-done-right/feed/</wfw:commentRss>
		<slash:comments>29</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>
	</channel>
</rss>
