<?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>Pieces of Web</title>
	<atom:link href="http://danengle.us/feed/" rel="self" type="application/rss+xml" />
	<link>http://danengle.us</link>
	<description>Dan Engle's Rails and Web Development Blog</description>
	<lastBuildDate>Fri, 29 May 2009 21:46:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Generating custom XML for your rails app</title>
		<link>http://danengle.us/2009/05/generating-custom-xml-for-your-rails-app/</link>
		<comments>http://danengle.us/2009/05/generating-custom-xml-for-your-rails-app/#comments</comments>
		<pubDate>Thu, 14 May 2009 00:46:42 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[builder]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://danengle.us/?p=83</guid>
		<description><![CDATA[Rails provides a very simple way to generate xml.  Most of the time though, it is much too verbose.  Current information obtained by google does not seem to provide all the info needed to generate custom xml.  Keep reading to find out how to generate your own custom xml for your rails 2.3 apps.]]></description>
			<content:encoded><![CDATA[<p>Recently, I needed to generate some xml for a rails 2.3 app.  What was supposed to be a fast and easy, turned out to take much longer than expected.  After all, rails already provides</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">respond_to <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>format<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">html</span> <span style="color:#008000; font-style:italic;"># index.html.erb</span>
  <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">xml</span>  <span style="color:#006600; font-weight:bold;">&#123;</span> render <span style="color:#ff3333; font-weight:bold;">:xml</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@posts</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The problem is that the generated xml is very verbose.  I spent some time googling and found plenty of information, but it was scattered and didn&#8217;t quite show the whole picture.</p>
<p>The rails api for <a href="http://api.rubyonrails.org/classes/Builder/XmlMarkup.html">Builder::XmlMarkup</a> uses both an &#8216;xm&#8217; and &#8216;xml&#8217; object to show how to work with xml, but only the &#8216;xml&#8217; object seems to work.  It also doesn&#8217;t clearly show how to setup the controller or that the code should go in an xml.builder file. Similarly <a href="http://www.tutorialspoint.com/ruby-on-rails/rails-and-xml.htm">here</a>, the xml object is used in the view correctly, but also fails mention anything about the controller or type of file the code should go in.</p>
<p>Over at <a href="http://www.xml.com/pub/a/2007/01/17/making-xml-in-a-rails-app-xml-builder.html?page=2">xml.com</a>, the tutorial creates an @xml instance variable of type Builder::XmlMarkup.new and then uses that object in an .rxml view (I know, its a little dated).</p>
<p>I was left with a bunch of puzzle pieces that didn&#8217;t quite fit together.  Eventually, I figured out what needed to be done, and this is how&#8230;</p>
<p>First, in the controller, remove the other bits in the format.xml line so it reads</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">respond_to <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>format<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">html</span> <span style="color:#008000; font-style:italic;"># index.html.erb</span>
  <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">xml</span> <span style="color:#008000; font-style:italic;"># index.xml.builder</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Second, you need to create an xml.builder file, in this case, index.xml.builder.  Inside the xml.builder view, you have access to an &#8216;xml&#8217; object that is used to generate the xml.  The xml for my sample @posts object can then look something like&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">xml.<span style="color:#9900CC;">instruct</span>!
xml.<span style="color:#9900CC;">posts</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  <span style="color:#0066ff; font-weight:bold;">@posts</span>.<span style="color:#5A0A0A; font-weight:bold;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>post<span style="color:#006600; font-weight:bold;">|</span>
    xml.<span style="color:#9900CC;">post</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      xml.<span style="color:#9900CC;">title</span> post.<span style="color:#9900CC;">title</span>
      xml.<span style="color:#9900CC;">body</span> post.<span style="color:#9900CC;">body</span>
      xml.<span style="color:#9900CC;">published_at</span> post.<span style="color:#9900CC;">published_at</span>
      xml.<span style="color:#9900CC;">comments</span> <span style="color:#9966CC; font-weight:bold;">do</span>
        post.<span style="color:#9900CC;">comments</span>.<span style="color:#5A0A0A; font-weight:bold;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>comment<span style="color:#006600; font-weight:bold;">|</span>
          xml.<span style="color:#9900CC;">comment</span> <span style="color:#9966CC; font-weight:bold;">do</span>
            xml.<span style="color:#9900CC;">body</span> comment.<span style="color:#9900CC;">body</span>
          <span style="color:#9966CC; font-weight:bold;">end</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now, when browsing to posts.xml, you&#8217;ll now see nicely formatted xml, without all the extra cruft added when using the default rails xml generation utility.  I hope that saves you some time.</p>
]]></content:encoded>
			<wfw:commentRss>http://danengle.us/2009/05/generating-custom-xml-for-your-rails-app/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Adding Some Additional Security Measures to restful_authentication</title>
		<link>http://danengle.us/2009/03/adding-some-additional-security-measures-to-restful_authentication/</link>
		<comments>http://danengle.us/2009/03/adding-some-additional-security-measures-to-restful_authentication/#comments</comments>
		<pubDate>Mon, 30 Mar 2009 01:55:14 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[restful_authentication]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://danengle.us/?p=68</guid>
		<description><![CDATA[Have you ever wanted to restful_authentication to lock out users after too many incorrect login attempts?  I've always want to do that and for this post, I'll show you what I came up with to do just that.  It really isn't that complicated and adds some extra security to your site.]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve been paying attention to the web lately, you&#8217;ve probably heard of twitter and probably also remember hearing about <a href="http://blog.wired.com/27bstroke6/2009/01/professed-twitt.html">this</a>.  Well, I&#8217;ve been wanting to implement something that would have prevented that hack into <a href="http://github.com/technoweenie/restful-authentication/tree/master">restful_authentication</a> for a long time and I finally got around to it.  I&#8217;ve been sitting on this for a bit because I wasn&#8217;t sure if I was ready to show it to the world, but I decided to just write about and release what I have thus far.  So I present to you, my first iteration of locking out user accounts after too many incorrect login attempts.  There are many ways to go about doing this, but the solution I settled on was to just lockout user accounts that have too many incorrect login attempts over a certain period of time.  Its pretty simple really.  This is done with the addition of one more table which is used to record incorrect logins.</p>
<p>For my example I&#8217;m going to spare you the details I used to get this running and only look at the lockout code.  Click <a href="http://github.com/danengle/lockout-example/tree/master">here</a> to go directly to the github repo.  I&#8217;m going to assume that you already have restful_authentication installed and running.  First thing to do then, is generate the model that will track incorrect login attempts, as well as add an extra field in the users table to keep track of when the account was locked out.  Just run&#8230;<br />
<code>./script/generate model login_attempt</code>&#8230;and make the migration look like this&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> CreateLoginAttempts <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">up</span>
    create_table <span style="color:#ff3333; font-weight:bold;">:login_attempts</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span>
      t.<span style="color:#CC0066; font-weight:bold;">integer</span> <span style="color:#ff3333; font-weight:bold;">:user_id</span>, <span style="color:#ff3333; font-weight:bold;">:null</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">false</span>
      t.<span style="color:#CC0066; font-weight:bold;">string</span> <span style="color:#ff3333; font-weight:bold;">:remote_ip</span>, <span style="color:#ff3333; font-weight:bold;">:user_agent</span>
      t.<span style="color:#9900CC;">timestamps</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    add_column <span style="color:#ff3333; font-weight:bold;">:users</span>, <span style="color:#ff3333; font-weight:bold;">:locked_out_at</span>, <span style="color:#ff3333; font-weight:bold;">:datetime</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">down</span>
    drop_table <span style="color:#ff3333; font-weight:bold;">:login_attempts</span>
    remove_column <span style="color:#ff3333; font-weight:bold;">:users</span>, <span style="color:#ff3333; font-weight:bold;">:locked_out_at</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>&#8230;and then migrate the database with&#8230;<br />
<code>rake db:migrate</code>From here, pretty much everything is in the sessions_controller.rb and user.rb files.  For the user model, we need to add a way to set lockout options (I just use a constant, but you could add another model to keep track of of these options too), another state and some transitions, and a couple of methods to determine the state of the user in the lockout process.  I&#8217;ll just paste my user.rb file, sans the validation methods that would just be taking up unnecessary space here.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'digest/sha1'</span>
<span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  <span style="color:#9966CC; font-weight:bold;">include</span> Authentication
  <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Authentication::ByPassword</span>
  <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Authentication::ByCookieToken</span>
  <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Authorization::AasmRoles</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># here is how I setup the lockout options </span>
  LOCKOUT_OPTIONS = <span style="color:#006600; font-weight:bold;">&#123;</span>
    <span style="color:#ff3333; font-weight:bold;">:lockout_period</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">1</span>, <span style="color:#008000; font-style:italic;"># in minutes</span>
    <span style="color:#ff3333; font-weight:bold;">:login_attempts</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">3</span>, <span style="color:#008000; font-style:italic;"># number of tries</span>
    <span style="color:#ff3333; font-weight:bold;">:attempt_window</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">4</span> <span style="color:#008000; font-style:italic;"># can have x number of login_attempts in this many minutes</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  has_many <span style="color:#ff3333; font-weight:bold;">:login_attempts</span>
&nbsp;
  named_scope <span style="color:#ff3333; font-weight:bold;">:with_allowed_states</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:state</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#996600;">'suspended'</span>, <span style="color:#996600;">'locked_out'</span>, <span style="color:#996600;">'active'</span> <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># A locked out account is different from a suspended account, so these are necessary</span>
  aasm_state <span style="color:#ff3333; font-weight:bold;">:locked_out</span>, <span style="color:#ff3333; font-weight:bold;">:enter</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:set_locked_out_at</span>
  aasm_event <span style="color:#ff3333; font-weight:bold;">:lock_out</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    transitions <span style="color:#ff3333; font-weight:bold;">:from</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:active</span>, <span style="color:#ff3333; font-weight:bold;">:to</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:locked_out</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  aasm_event <span style="color:#ff3333; font-weight:bold;">:end_lock_out</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    transitions <span style="color:#ff3333; font-weight:bold;">:from</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:locked_out</span>, <span style="color:#ff3333; font-weight:bold;">:to</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:active</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># HACK HACK HACK -- how to do attr_accessible from here?</span>
  <span style="color:#008000; font-style:italic;"># prevents a user from submitting a crafted form that bypasses activation</span>
  <span style="color:#008000; font-style:italic;"># anything else you want your user to change should be added here.</span>
  attr_accessible <span style="color:#ff3333; font-weight:bold;">:login</span>, <span style="color:#ff3333; font-weight:bold;">:email</span>, <span style="color:#ff3333; font-weight:bold;">:name</span>, <span style="color:#ff3333; font-weight:bold;">:password</span>, <span style="color:#ff3333; font-weight:bold;">:password_confirmation</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> max_login_attempts?
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">login_attempts</span>.<span style="color:#9900CC;">by_attempt_window</span><span style="color:#006600; font-weight:bold;">&#40;</span>LOCKOUT_OPTIONS<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:attempt_window</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">all</span>.<span style="color:#9900CC;">size</span> <span style="color:#006600; font-weight:bold;">&gt;</span> LOCKOUT_OPTIONS<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:login_attempts</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> lock_out_ended?
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">locked_out_at</span> <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span> <span style="color:#006600; font-weight:bold;">-</span> LOCKOUT_OPTIONS<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:lockout_period</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">minutes</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> login=<span style="color:#006600; font-weight:bold;">&#40;</span>value<span style="color:#006600; font-weight:bold;">&#41;</span>
    write_attribute <span style="color:#ff3333; font-weight:bold;">:login</span>, <span style="color:#006600; font-weight:bold;">&#40;</span>value ? value.<span style="color:#9900CC;">downcase</span> : <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> email=<span style="color:#006600; font-weight:bold;">&#40;</span>value<span style="color:#006600; font-weight:bold;">&#41;</span>
    write_attribute <span style="color:#ff3333; font-weight:bold;">:email</span>, <span style="color:#006600; font-weight:bold;">&#40;</span>value ? value.<span style="color:#9900CC;">downcase</span> : <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> admin?
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">role</span> == <span style="color:#996600;">'admin'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
protected
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> set_locked_out_at
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">locked_out_at</span> = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> make_activation_code
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">deleted_at</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">activation_code</span> = <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9966CC; font-weight:bold;">class</span>.<span style="color:#9900CC;">make_token</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Next thing to do is to edit the sessions controller.  Open it up and make it look like&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># This controller handles the login/logout function of the site.  </span>
<span style="color:#9966CC; font-weight:bold;">class</span> SessionsController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController
  <span style="color:#008000; font-style:italic;"># render new.rhtml</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> new
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> create
    logout_keeping_session!
    <span style="color:#0066ff; font-weight:bold;">@login</span>       = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:login</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#0066ff; font-weight:bold;">@remember_me</span> = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:remember_me</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#0066ff; font-weight:bold;">@user</span> = User.<span style="color:#9900CC;">with_allowed_states</span>.<span style="color:#9900CC;">find_by_login</span><span style="color:#006600; font-weight:bold;">&#40;</span>@login<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@user</span>
      <span style="color:#9966CC; font-weight:bold;">case</span> <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">aasm_current_state</span>
      <span style="color:#9966CC; font-weight:bold;">when</span> <span style="color:#ff3333; font-weight:bold;">:suspended</span>
        flash_and_render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:error</span>, <span style="color:#996600;">&quot;Your account is suspended&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">when</span> <span style="color:#ff3333; font-weight:bold;">:locked_out</span>
        <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">lock_out_ended</span>?
          LoginAttempt.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span>@user.<span style="color:#9900CC;">login_attempts</span><span style="color:#006600; font-weight:bold;">&#41;</span>
          <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">end_lock_out</span>!
          proceed_to_login
        <span style="color:#9966CC; font-weight:bold;">else</span>
          flash_and_render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:error</span>, <span style="color:#996600;">&quot;Your account is locked out&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">else</span> <span style="color:#008000; font-style:italic;"># is active</span>
        proceed_to_login
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      flash_and_render
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> destroy
    logout_killing_session!
    flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;You have been logged out.&quot;</span>
    redirect_back_or_default<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'/'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
protected
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> proceed_to_login
    <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">authenticated</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:password</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">current_user</span> = <span style="color:#0066ff; font-weight:bold;">@user</span>
      LoginAttempt.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span>@user.<span style="color:#9900CC;">login_attempts</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      new_cookie_flag = <span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:remember_me</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#996600;">&quot;1&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      handle_remember_cookie! new_cookie_flag
      flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:success</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;Logged in successfully&quot;</span>
      redirect_back_or_default<span style="color:#006600; font-weight:bold;">&#40;</span>root_path<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">login_attempts</span>.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:remote_ip</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> request.<span style="color:#9900CC;">remote_ip</span>, <span style="color:#ff3333; font-weight:bold;">:user_agent</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> request.<span style="color:#9900CC;">user_agent</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">max_login_attempts</span>?
        <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">lock_out</span>!
        flash_and_render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:error</span>, <span style="color:#996600;">&quot;Your account is locked out&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        flash_and_render
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> flash_and_render<span style="color:#006600; font-weight:bold;">&#40;</span>type = <span style="color:#ff3333; font-weight:bold;">:notice</span>, message = <span style="color:#996600;">&quot;Incorrect username or password&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    flash<span style="color:#006600; font-weight:bold;">&#91;</span>type<span style="color:#006600; font-weight:bold;">&#93;</span> = message
    <span style="color:#008000; font-style:italic;"># done to clear out unneeded flash values since this isn't a redirect...know a better way to do this?</span>
    flash.<span style="color:#9900CC;">delete_if</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>key, value<span style="color:#006600; font-weight:bold;">|</span> key != type <span style="color:#006600; font-weight:bold;">&#125;</span>
    render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'new'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>And thats about it.  User accounts now get locked out for however many minutes you specify after however many login attempts you deem are inappropriate.  In my example I have them set really low for testing purposes, but in the real world, I would probably up the login attempts to 10 or 15 tries and the lock out time for 10 to 15 minutes to balance not annoying your users and securing your site.  But, that&#8217;s really up to you to decide whats appropriate in your case.</p>
<p>My sample app that uses this code is available on github <a href="http://github.com/danengle/lockout-example/tree/master">here</a>.  I have some additional plans, but wanted to get this posted before I took any longer.  For one, if a user mistakenly locks themselves out of their account, they should be able to click on a link to reset their password and not wait for their account to let them log in again and I would also like to restrict the IP address of users who lock out multiple accounts within a certain amount of time.  I also want to get this integrated into restful_authentication so its just as easy to have account lockouts as it is to setup restful_authentication.  As always, comments and suggestions are welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://danengle.us/2009/03/adding-some-additional-security-measures-to-restful_authentication/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Extending the will_paginate Rails Plugin</title>
		<link>http://danengle.us/2009/03/extending-the-will_paginate-rails-plugins/</link>
		<comments>http://danengle.us/2009/03/extending-the-will_paginate-rails-plugins/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 19:09:48 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[will_paginate]]></category>

		<guid isPermaLink="false">http://danengle.us/?p=44</guid>
		<description><![CDATA[Sometimes plugins only give you 99% of what you need.  What do you do when you need a little more functionality?  You add it yourself.  See how I added a couple extra methods to Mislav's will_paginate plugin here.]]></description>
			<content:encoded><![CDATA[<p>Recently I needed a little extra functionality for paginating.  Specifically, I wanted to know if I was on the last page, and if so, add some content below my list of paginated stuff.  Unfortunately, <a href="http://github.com/mislav/will_paginate/tree/master">Mislav&#8217;s, will_paginate plugin</a> does not provide those methods.  All I wanted to be able to (with a collection of @products) do is&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@products</span>.<span style="color:#5A0A0A; font-weight:bold;">last_page</span>? <span style="color:#006600; font-weight:bold;">%&gt;</span>
  here is the content
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></pre></div></div>

<p>Adding that method is actually pretty easy.  While I&#8217;m at it, it makes sense to add a first_page? method also.  Will_paginate has the WillPaginate::Collection class that already adds some additional properties to make paginating in views easy.  I just needed to add a little more to it.  To start, I created a new file named will_paginate_ext.rb in my lib directory.  Inside I added&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> WillPaginateExt
  <span style="color:#9966CC; font-weight:bold;">def</span> first_page?
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">current_page</span> == <span style="color:#006666;">1</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> last_page?
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">current_page</span> == <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">total_pages</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#6666ff; font-weight:bold;">WillPaginate::Collection</span>
  <span style="color:#9966CC; font-weight:bold;">include</span> WillPaginateExt
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>&#8230;and inside my environment.rb file, below and outside of the Rails::Initializer block, add the line&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'will_paginate_ext'</span></pre></div></div>

<p>With those simple additions, I add two new methods to the will_paginate plugin and am now able to figure out if I am on the first or last page of pagination and add content as necessary.</p>
<p>Is there a better way to add functionality to plugins or other objects?  Let me know in the comments below.</p>
]]></content:encoded>
			<wfw:commentRss>http://danengle.us/2009/03/extending-the-will_paginate-rails-plugins/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>More Advanced Searching Techniques with Rails</title>
		<link>http://danengle.us/2009/03/more-advanced-searching-techniques-with-rails/</link>
		<comments>http://danengle.us/2009/03/more-advanced-searching-techniques-with-rails/#comments</comments>
		<pubDate>Fri, 06 Mar 2009 19:10:30 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[jqueryui]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[scopes]]></category>
		<category><![CDATA[searching]]></category>

		<guid isPermaLink="false">http://danengle.us/?p=12</guid>
		<description><![CDATA[Another look at using anonymous scopes inside a rails app to apply different sets of conditions to an advanced search.  Also, instead of using the boring rails date_select helper to select dates, I chose to use Filament Groups jQuery Date Range Picker plugin to select a range of dates.]]></description>
			<content:encoded><![CDATA[<p>For my first real post, I want to start off looking at searching and drilling down a list of objects.  It&#8217;s based on <a href="http://railscasts.com/episodes/112-anonymous-scopes">Railscast 112</a>, the one on anonymous scopes, but with a few other things thrown in for good measure.  For the purposes of this example, I&#8217;m going to use these classes</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># models/employee.rb</span>
<span style="color:#9966CC; font-weight:bold;">class</span> Employee <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:employer</span>
  validates_presence_of <span style="color:#ff3333; font-weight:bold;">:employer_id</span>, <span style="color:#ff3333; font-weight:bold;">:first_name</span>, <span style="color:#ff3333; font-weight:bold;">:last_name</span>, <span style="color:#ff3333; font-weight:bold;">:start_date</span>, <span style="color:#ff3333; font-weight:bold;">:salary</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># models/employer.rb</span>
<span style="color:#9966CC; font-weight:bold;">class</span> Employer <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:region</span>
  has_many <span style="color:#ff3333; font-weight:bold;">:employees</span>
  validates_presence_of <span style="color:#ff3333; font-weight:bold;">:name</span>
  validates_uniqueness_of <span style="color:#ff3333; font-weight:bold;">:name</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># models/region.rb</span>
<span style="color:#9966CC; font-weight:bold;">class</span> Region <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  has_many <span style="color:#ff3333; font-weight:bold;">:employers</span>
  validates_presence_of <span style="color:#ff3333; font-weight:bold;">:name</span>
  validates_uniqueness_of <span style="color:#ff3333; font-weight:bold;">:name</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>One thing that always seems to be a problem for me, is working with dates in rails.  So, instead of using the classic rails date_select, I am going to use <a href="http://www.filamentgroup.com/lab/date_range_picker_using_jquery_ui_16_and_jquery_ui_css_framework/">Filament Groups jQuery UI Date Range Picker</a>.</p>
<p>To begin, I generated the scaffold for the three models</p>
<pre>./script/generate scaffold region name:string
./script/generate scaffold employer name:string region_id:integer
./script/generate scaffold employee employer_id:integer first_name:string last_name:string start_date:date salary:integer</pre>
<p>I made a few changes to the views to include select lists where appropriate, but thats not so important at the moment.  Take a look at the download if you would like to see those view changes.</p>
<p>The main stuff happens in the employees_controller.  I wanted to keep this fairly simple, so there is no separate search action. It works out better this way anyway.  Here is what the employees index action looks like</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> index
  <span style="color:#0066ff; font-weight:bold;">@search</span> = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:search</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>? ? <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span> : params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:search</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  get_dates
  collect_employees
  <span style="color:#0066ff; font-weight:bold;">@employees</span> = <span style="color:#0066ff; font-weight:bold;">@scope</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:order</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'employers.name, last_name'</span>, <span style="color:#ff3333; font-weight:bold;">:include</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:employer</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  respond_to <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>format<span style="color:#006600; font-weight:bold;">|</span>
    <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">html</span> <span style="color:#008000; font-style:italic;"># index.html.erb</span>
    <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">xml</span>  <span style="color:#006600; font-weight:bold;">&#123;</span> render <span style="color:#ff3333; font-weight:bold;">:xml</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@employees</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>As you can see, @search will be a blank hash if there is not an incoming search parameter.</p>
<p>Both the get_dates and collect_employees methods, are protected methods in the employees controller.  The method get_dates, takes the single input field of the calendar select, and splits up the dates so employees start_dates can be filtered through any range of dates.  It looks like this&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> get_dates
  <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@search</span>.<span style="color:#9900CC;">blank</span>?
    dates = <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:start</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'-'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    dates.<span style="color:#9900CC;">each_with_index</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>d, i<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;date_#{i}&quot;</span>.<span style="color:#9900CC;">to_sym</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#CC00FF; font-weight:bold;">Date</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>d.<span style="color:#9900CC;">strip</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> d.<span style="color:#9900CC;">blank</span>?
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The get_dates method extracts the two dates from @search[:start] and creates two new attributes, date_0 and date_1.  This also keeps the :start attribute intact, and allows it to be redisplayed in the view.  Also, if the start field only includes 1 date, the query will find all employees that started on that date till now.</p>
<p>The next method should look familiar if you watched <a href="http://railscasts.com/episodes/112-anonymous-scopes">railscast 112</a> .  Here it is&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> collect_employees
  <span style="color:#0066ff; font-weight:bold;">@scope</span> = Employee.<span style="color:#9900CC;">scoped</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#0066ff; font-weight:bold;">@scope</span> = <span style="color:#0066ff; font-weight:bold;">@scope</span>.<span style="color:#9900CC;">scoped</span> <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'first_name like ?'</span>, <span style="color:#996600;">&quot;%#{@search[:first_name]}%&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:first_name</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>?
  <span style="color:#0066ff; font-weight:bold;">@scope</span> = <span style="color:#0066ff; font-weight:bold;">@scope</span>.<span style="color:#9900CC;">scoped</span> <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'last_name like ?'</span>, <span style="color:#996600;">&quot;%#{@search[:last_name]}%&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:last_name</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>?
  <span style="color:#0066ff; font-weight:bold;">@scope</span> = <span style="color:#0066ff; font-weight:bold;">@scope</span>.<span style="color:#9900CC;">scoped</span> <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:employer_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:employer_id</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:employer_id</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>?
  <span style="color:#0066ff; font-weight:bold;">@scope</span> = <span style="color:#0066ff; font-weight:bold;">@scope</span>.<span style="color:#9900CC;">scoped</span> <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:employers</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:region_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:region_id</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:region_id</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>?
  <span style="color:#0066ff; font-weight:bold;">@scope</span> = <span style="color:#0066ff; font-weight:bold;">@scope</span>.<span style="color:#9900CC;">scoped</span> <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'salary &gt;= ?'</span>, <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:salary_min</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:salary_min</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>?
  <span style="color:#0066ff; font-weight:bold;">@scope</span> = <span style="color:#0066ff; font-weight:bold;">@scope</span>.<span style="color:#9900CC;">scoped</span> <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'salary &lt;= ?'</span>, <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:salary_max</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:salary_max</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>?
  <span style="color:#0066ff; font-weight:bold;">@scope</span> = <span style="color:#0066ff; font-weight:bold;">@scope</span>.<span style="color:#9900CC;">scoped</span> <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'start_date &gt;= ?'</span>, <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:date_0</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:date_0</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>?
  <span style="color:#0066ff; font-weight:bold;">@scope</span> = <span style="color:#0066ff; font-weight:bold;">@scope</span>.<span style="color:#9900CC;">scoped</span> <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'start_date &lt;= ?'</span>, <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:date_1</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:date_1</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>?
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>As you can see, there is more going on than just refining the results by attributes of the employee.  You can also find employees by their employer and even employees by the region their employer is located in.</p>
<p>I wanted to use a search model, like in <a href="http://railscasts.com/episodes/111-advanced-search-form">railscast 111</a>, so I could use f.text_field throughout the form, but I didn&#8217;t want to create a database object, and my attempts to finesse the code to work in that way proved fruitless.  So, for the view, I used the generic form_for and text_field_tag&#8217;s like this&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#5A0A0A; font-weight:bold;">form_for</span> <span style="color:#ff3333; font-weight:bold;">:search</span>, <span style="color:#ff3333; font-weight:bold;">:url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:controller</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'employees'</span>, <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'index'</span> <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
  &lt;div&gt;
    &lt;label for=&quot;search_first_name&quot;&gt;First Name:&lt;/label&gt;&lt;br /&gt;
    <span style="color:#006600; font-weight:bold;">&lt;%</span>= text_field_tag <span style="color:#996600;">'search[first_name]'</span>, <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:first_name</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'search_first_name'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
  &lt;/div&gt;
  &lt;div&gt;
    &lt;label for=&quot;search_last_name&quot;&gt;Last Name:&lt;/label&gt;&lt;br /&gt;
    <span style="color:#006600; font-weight:bold;">&lt;%</span>= text_field_tag <span style="color:#996600;">'search[last_name]'</span>, <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:last_name</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'search_last_name'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
  &lt;/div&gt;
  &lt;div&gt;
    &lt;label for=&quot;search_employer_name&quot;&gt;Employer:&lt;/label&gt;&lt;br /&gt;
    <span style="color:#006600; font-weight:bold;">&lt;%</span>= select_tag <span style="color:#996600;">'search[employer_id]'</span>, employee_select_helper<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'Employer'</span><span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'search_employer_name'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
  &lt;/div&gt;
  &lt;div&gt;
    &lt;label for=&quot;search_region_name&quot;&gt;Region:&lt;/label&gt;&lt;br /&gt;
    <span style="color:#006600; font-weight:bold;">&lt;%</span>= select_tag <span style="color:#996600;">'search[region_id]'</span>, employee_select_helper<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'Region'</span><span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'search_region_name'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
  &lt;/div&gt;
  &lt;div&gt;
    &lt;label&gt;Salary&lt;/label&gt;&lt;br /&gt;
    <span style="color:#006600; font-weight:bold;">&lt;%</span>= text_field_tag <span style="color:#996600;">'search[salary_min]'</span>, <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:salary_min</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'search_salary_min'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span> -
    <span style="color:#006600; font-weight:bold;">&lt;%</span>= text_field_tag <span style="color:#996600;">'search[salary_max]'</span>, <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:salary_max</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'search_salary_max'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
  &lt;/div&gt;
  &lt;div id=&quot;date_search&quot;&gt;
    &lt;label for=&quot;search_start&quot;&gt;Start Date&lt;/label&gt;&lt;br /&gt;
    <span style="color:#006600; font-weight:bold;">&lt;%</span>= text_field_tag <span style="color:#996600;">'search[start]'</span>, <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:start</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'search_start'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
  &lt;/div&gt;
  <span style="color:#006600; font-weight:bold;">&lt;%</span>= submit_tag <span style="color:#996600;">&quot;search&quot;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></pre></div></div>

<p>The employee_select_helper is in the employeesHelper and thanks to some ruby magic, it looks like&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> employee_select_helper<span style="color:#006600; font-weight:bold;">&#40;</span>object<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#996600;">'&lt;option&gt;&lt;/option&gt;'</span> <span style="color:#006600; font-weight:bold;">+</span> options_from_collection_for_select<span style="color:#006600; font-weight:bold;">&#40;</span>object.<span style="color:#9900CC;">constantize</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:order</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'name'</span><span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#996600;">'id'</span>, <span style="color:#996600;">'name'</span>, <span style="color:#0066ff; font-weight:bold;">@search</span><span style="color:#006600; font-weight:bold;">&#91;</span>object.<span style="color:#9900CC;">foreign_key</span>.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_i</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>I ran into a couple of issues with the daterangepicker plugin displaying the dropdown correctly.  The daterangepicker, by default, appends the slick looking calendar picker to the html document body, but this creates a problem whenever there is data after the daterangepicker, causing it to append to the bottom of the page and not work as expected.  To fix that, I edited the daterangepicker.jQuery.js (around line 269) like this&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// from</span>
jQuery<span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">appendTo</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">append</span><span style="color: #009900;">&#40;</span>rp<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #006600; font-style: italic;">// to</span>
jQuery<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">after</span><span style="color: #009900;">&#40;</span>rp<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>And application.js is simple as this&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#search_start&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">daterangepicker</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
		latestDate<span style="color: #339933;">:</span> Date.<span style="color: #660066;">today</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>As for the daterangepicker plugin, I placed all the js files in the javascripts directory and all the css files inside the stylesheets directory.  The plugin also includes an images directory, and in order to avoid having to edit all the image urls inside the css, I just placed the images directory inside the stylesheets directory.  Maybe not a best practice, but it makes things easier at this point.</p>
<p>Now, you can search for employees in any combination of employer, employers region, a start date range, salary range, or first and last name.  This concludes my further exploration of anonymous scopes and the Filament Group jQuery UI Date Range Picker.  Hopefully you found something of value.  The included app uses sqlite3 and also has a little sample data with it.  You should only need to download, unzip and run script/server to see the basic, no style applied employee search app. As always, comments, suggestions and improvements are welcome.</p>
<p><span class="download_link">Download: <a href="http://danengle.us/wp-content/files/searching.zip">searching</a></span></p>
]]></content:encoded>
			<wfw:commentRss>http://danengle.us/2009/03/more-advanced-searching-techniques-with-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

