<?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>me, Patterson</title>
	<atom:link href="http://blog.digimonkey.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.digimonkey.com</link>
	<description>writing, coding, babbling</description>
	<lastBuildDate>Sun, 21 Feb 2010 02:42:11 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Nested forms, hashes, checkboxes and MongoMapper</title>
		<link>http://blog.digimonkey.com/2010/02/nested-forms-hashes-checkboxes-and-mongomapper/</link>
		<comments>http://blog.digimonkey.com/2010/02/nested-forms-hashes-checkboxes-and-mongomapper/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 02:39:09 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[inherited_resources]]></category>
		<category><![CDATA[mongod]]></category>
		<category><![CDATA[mongomapper]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[solr]]></category>
		<category><![CDATA[sunspot]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=92</guid>
		<description><![CDATA[<p>While working on my upcoming BigAuthor project, I came upon an interesting challenge that turned out to be so simple with MongoMapper that I just have to share it here.  Need to create a hash of multiple filter parameters on a MongoMapper document using a form that is cleanly resource-based, using InheritedResources?  It&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>While working on my upcoming BigAuthor project, I came upon an interesting challenge that turned out to be so simple with MongoMapper that I just have to share it here.  Need to create a hash of multiple filter parameters on a MongoMapper document using a form that is cleanly resource-based, using InheritedResources?  It&#8217;s not as difficult as you might think&#8230;<br />
<span id="more-92"></span><br />
In my MongoMapper::Document model, I have the following keys:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">key <span style="color:#ff3333; font-weight:bold;">:title</span>, <span style="color:#CC0066; font-weight:bold;">String</span><br />
key <span style="color:#ff3333; font-weight:bold;">:filters</span>, <span style="color:#CC00FF; font-weight:bold;">Hash</span>, <span style="color:#ff3333; font-weight:bold;">:index</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span></div></div>
<p>Now, I&#8217;m expecting to stick a Hash into &#8216;filters&#8217; in the form:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">'colors'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'red'</span>,<span style="color:#996600;">'green'</span>,<span style="color:#996600;">'blue'</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <br />
&nbsp; <span style="color:#996600;">'people'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'joe'</span>,<span style="color:#996600;">'mary'</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <br />
&nbsp; <span style="color:#996600;">'tags'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'dog cat vampire zombie'</span><span style="color:#006600; font-weight:bold;">&#125;</span></div></div>
<p>So, the idea is, the object that is saved with the above filters Hash provides a context for searching through another collection of objects (let&#8217;s call it OtherThings) using the filters.  (think email rules in Outlook).  Anyway, don&#8217;t worry too much about that.  It&#8217;ll become more clear once I launch BigAuthor in a few weeks or so.</p>
<p>Using <a href="http://github.com/josevalim/inherited_resources">InheritedResources</a> + <a href="http://github.com/justinfrench/formtastic">Formtastic</a> gives you a big advantage in creating resourceful controllers and their associated semantic forms really, really quickly.</p>
<p>The controller:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> ThingsController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">InheritedResources::Base</span><br />
&nbsp; respond_to <span style="color:#ff3333; font-weight:bold;">:html</span>, <span style="color:#ff3333; font-weight:bold;">:xml</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>Seriously.  It&#8217;s that empty.</p>
<p>The &#8216;new&#8217; form page (in HAML, of course):</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">%</span>h1 Add a New Thing<br />
<span style="color:#006600; font-weight:bold;">-</span> semantic_form_for <span style="color:#0066ff; font-weight:bold;">@things</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>form<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">-</span> form.<span style="color:#9900CC;">inputs</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; = form.<span style="color:#9900CC;">input</span> <span style="color:#ff3333; font-weight:bold;">:title</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">-</span> form.<span style="color:#9900CC;">semantic_fields_for</span> <span style="color:#ff3333; font-weight:bold;">:filters</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>sub<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#CC0066; font-weight:bold;">sub</span>.<span style="color:#9900CC;">inputs</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; = <span style="color:#CC0066; font-weight:bold;">sub</span>.<span style="color:#9900CC;">input</span> <span style="color:#ff3333; font-weight:bold;">:tags</span><br />
&nbsp; &nbsp; &nbsp; = <span style="color:#CC0066; font-weight:bold;">sub</span>.<span style="color:#9900CC;">input</span> <span style="color:#ff3333; font-weight:bold;">:colors</span>, <span style="color:#ff3333; font-weight:bold;">:collection</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">Thing::COLORS</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:check_boxes</span><br />
&nbsp; &nbsp; &nbsp; = <span style="color:#CC0066; font-weight:bold;">sub</span>.<span style="color:#9900CC;">input</span> <span style="color:#ff3333; font-weight:bold;">:people</span>, <span style="color:#ff3333; font-weight:bold;">:collection</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> People.<span style="color:#9900CC;">for_filters</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:check_boxes</span> &nbsp; &nbsp; &nbsp; <br />
&nbsp; <span style="color:#006600; font-weight:bold;">-</span> form.<span style="color:#9900CC;">buttons</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; = form.<span style="color:#9900CC;">commit_button</span> <span style="color:#ff3333; font-weight:bold;">:label</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Create Thing&quot;</span></div></div>
<p>Again, that&#8217;s it.  Really.  The checkboxes that are checked get put into Arrays within a params['thing']['filters'] Hash and persist naturally to MongoDB through MongoMapper.  No extra work needed.</p>
<p>In fact, the only extra thing I did was to write a short override into the create/update methods so that it strips the blanks from the internal filter arrays.  (formtastic&#8217;s checkboxes post an empty string for every checkbox that is not checked, which in this case wasn&#8217;t what I wanted, but it might be fine or even required for your purposes)</p>
<p>BONUS!</p>
<p>Using <a href="http://outoftime.github.com/sunspot/">Sunspot</a> and Solr for your search solution in your MongoMapper app?  Here&#8217;s a sample of the search method that my OtherThing class has for creating a search result set based on the filters:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">search_with_filters</span><span style="color:#006600; font-weight:bold;">&#40;</span>filters<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; Sunspot.<span style="color:#9900CC;">search</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; keywords filters<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'tags'</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; with<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:color</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">any_of</span> filters<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'colors'</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; with<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:people</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">any_of</span> filters<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'people'</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; order_by <span style="color:#ff3333; font-weight:bold;">:created_at</span>, <span style="color:#ff3333; font-weight:bold;">:desc</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>Exactly how my Sunspot/Solr is setup, I&#8217;ll leave for the reader to imagine, but don&#8217;t overthink it&#8230; it&#8217;s not complicated and the above works fast&#8230; really, really fast.  So fast, that instead of pre-creating and caching the results sets, I just re-generate them on the fly, thereby ensuring they&#8217;re always up-to-the-second with the latest OtherThings that have been added to the database.</p>
<p>Once again, Mongo and MongoMapper blows me away with its simplicity, further supported by the brilliant <a href="http://github.com/josevalim/inherited_resources">inherited_resources</a> and <a href="http://github.com/justinfrench/formtastic">formtastic</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.digimonkey.com/2010/02/nested-forms-hashes-checkboxes-and-mongomapper/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Starting a new Rails app?  Here&#8217;s my skeleton&#8230;</title>
		<link>http://blog.digimonkey.com/2010/02/starting-a-new-rails-app-heres-my-skeleton/</link>
		<comments>http://blog.digimonkey.com/2010/02/starting-a-new-rails-app-heres-my-skeleton/#comments</comments>
		<pubDate>Mon, 15 Feb 2010 20:02:19 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[mongomapper]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=81</guid>
		<description><![CDATA[<p>Not meant to be a &#8220;this is what should be done&#8221; as much as a &#8220;this is what Matt uses, based largely on community popularity, best practice, and Matt&#8217;s personal tastes.&#8221;</p>
<p>Take it for what it is: a point of discussion.</p>
<p>Of course, the skeleton of any Rails app will vary from project to project, depending on [...]]]></description>
			<content:encoded><![CDATA[<p>Not meant to be a &#8220;this is what should be done&#8221; as much as a &#8220;this is what Matt uses, based largely on community popularity, best practice, and Matt&#8217;s personal tastes.&#8221;</p>
<p>Take it for what it is: a point of discussion.</p>
<p>Of course, the skeleton of any Rails app will vary from project to project, depending on needs.  Agile approach is to only add it to your framework if you actually need it <em>right now</em>, though some stuff tends to be easier to use (like authentication systems and databases) if you build it in up-front.  That tends to be my approach for green-fielding Rails apps.</p>
<p>If you&#8217;ve got some favorites that <em>you</em> use, feel free to post in the comments about it!  I&#8217;m always interested in hearing about new stuff that makes my life easier/more fun.<br />
<span id="more-81"></span></p>
<h3>FOR MY ACTIVERECORD-BASED APPS</h3>
<ul>
<li> <strong>inherited_resources</strong>
<ul>
<li> for building clean, simple resource-oriented controllers.  the Rails 3.0 guys <a id="j8wo" title="recommend you start using this" href="http://www.enlightsolutions.com/articles/five-ways-to-prepare-your-application-for-ruby-on-rails-3-today/">recommend you start using this</a> with Rails 2.3.5 apps because Rails 3.0&#8217;s new controller syntax is basically derived from inherited_resources (and jose valim is on the rails core team now)</li>
</ul>
</li>
<li> <strong>authlogic</strong>
<ul>
<li> the reigning champ (in my opinion) for a while in terms of a really simple, basic user authentication solution.  i&#8217;ve also tried clearance, lockdown, ye olde restful_authentication, and others.  I still like authlogic alot, but the new Devise system seems to be really solid and might be good enough to get me to switch for new apps</li>
</ul>
</li>
<li> <strong>searchlogic</strong>
<ul>
<li> really handy extra methods for activerecord queries</li>
</ul>
</li>
<li> <strong>haml / sass</strong>
<ul>
<li> blah blah blah <a href="http://blog.digimonkey.com/2010/02/why-use-haml-and-sass-i-already-know-html/">http://blog.digimonkey.com/2010/02/why-use-haml-and-sass-i-already-know-html/ </a></li>
</ul>
</li>
<li> <strong>formtastic</strong> &#8212; <a href="http://github.com/justinfrench/formtastic">http://github.com/justinfrench/formtastic</a>
<ul>
<li> if you intend to produce semantically-correct, standards-compliant xhtml, your biggest enemy is trying to get forms to both look right and be semantic xhtml.  formtastic takes you a long way towards that goal, while also cleaning up your views significantly. and if you need to do something weird for a form that doesn&#8217;t quite work with formtastic, it doesn&#8217;t get in your way.</li>
</ul>
</li>
<li> <strong>compass + blueprint</strong>
<ul>
<li> blueprint is just a CSS framework for laying out 950px wide fixed layouts in a clean way; particularly great for multi-column layouts, which can be notoriously tricky to get right and cross-browser</li>
<li> compass adds a layer on top of blueprint + Sass to make html/css design really easy and slick; saves you a TON of time and makes it easier to get the cross-browser stuff working (or 99% working) on the first try, instead of spending a whole day fighting IE 7</li>
</ul>
</li>
<li> <strong>hoptoad</strong>
<ul>
<li> exception notification to a third-party service that integrates with lighthouse, github, et al</li>
</ul>
</li>
<li> <strong>acts_as_state_machine</strong>
<ul>
<li> self-explanatory</li>
</ul>
</li>
<li> <strong>acts_as_taggable_on_steroids</strong></li>
<li> <strong>acts_as_rateable_with_weights</strong> (mine) &#8211; <a id="u20v" title="http://github.com/mepatterson/acts_as_rateable_with_weights" href="http://github.com/mepatterson/acts_as_rateable_with_weights">http://github.com/mepatterson/acts_as_rateable_with_weights</a>
<ul>
<li> forked my own version of acts_as_rateable to add weighted ratings and bayesian averages</li>
</ul>
</li>
<li> <strong>will_paginate</strong>
<ul>
<li> makes it much easier to handle pagination on <em>any </em>enumerable object collection (ActiveRecord objects or not)</li>
</ul>
</li>
<li> <strong>ssl_requirement</strong>
<ul>
<li> allows you to lock down controller methods so they won&#8217;t work unless the requestor is hitting them through SSL</li>
</ul>
</li>
<li> <strong>statistics</strong> &#8211; <a id="zf5s" title="http://github.com/acatighera/statistics" href="http://github.com/acatighera/statistics">http://github.com/acatighera/statistics</a>
<ul>
<li> have used this exactly once.  liked it, but didn&#8217;t use a ton of its features.  seems pretty robust though.</li>
</ul>
</li>
<li> <strong>jrails</strong> plugin (+ nuke the prototype stuff and replace with jquery)
<ul>
<li> self-explanatory; prototype is dead. long live jquery.</li>
</ul>
</li>
<li> <strong>xapian</strong> or <strong>thinking_sphinx</strong>
<ul>
<li> i&#8217;ve gone through so many different search engines for so many projects.  I think I&#8217;m the only one using Xapian.  It actually works pretty well, but is lacking in a lot of ways.  Thinking sphinx is similar; easier Rails integration, but missing some stuff, though it&#8217;s highlighting and excerpting work nicely.</li>
</ul>
</li>
<li> <strong>paperclip</strong>
<ul>
<li> super-simple file attachments on ActiveRecord models</li>
</ul>
</li>
<li> <strong>carmen</strong> &#8212; <a id="nu18" title="http://github.com/jim/carmen" href="http://github.com/jim/carmen">http://github.com/jim/carmen</a>
<ul>
<li> &#8220;helpful collection of geographic names and abbreviations for Rails apps (includes replacements for country_select and state_select)&#8221;</li>
</ul>
</li>
<li> <strong>stringex</strong> &#8212; <a id="fv2l" title="http://github.com/rsl/stringex" href="http://github.com/rsl/stringex">http://github.com/rsl/stringex</a>
<ul>
<li> helpful assortment of extra string methods</li>
</ul>
</li>
<li> <strong>admin-data</strong> &#8212; <a id="qqkd" title="http://github.com/neerajdotname/admin_data" href="http://github.com/neerajdotname/admin_data">http://github.com/neerajdotname/admin_data</a>
<ul>
<li> every app ends up needing some sort of admin backend to rifle through the data layer, at the very least in development mode; pretty useful</li>
</ul>
</li>
<li> <strong>bullet</strong> &#8212; <a id="agmh" title="http://github.com/flyerhzm/bullet" href="http://github.com/flyerhzm/bullet">http://github.com/flyerhzm/bullet</a>
<ul>
<li> stupid-simple plugin that helps you find N+1 queries and other query performance problems</li>
</ul>
</li>
<li> <strong>factory_girl</strong>, <strong>shoulda</strong>, <strong>faker</strong>
<ul>
<li> i liked factory_girl a lot until my company started using machinist, so now I think I like that better.  shoulda is great.  faker is indispensable, imho.</li>
</ul>
</li>
<li> <strong>db-populate </strong>&#8211; <a id="bxz9" title="http://github.com/ffmike/db-populate" href="http://github.com/ffmike/db-populate">http://github.com/ffmike/db-populate</a>
<ul>
<li> i&#8217;ve been using this in my older AR-backed apps.  probably won&#8217;t need it in 2.3.5 or 3.0 apps, though i do like how ffmike did db-populate.  i think it might still be more robust than the db:seed thing built-in to Rails</li>
</ul>
</li>
</ul>
<h3>FOR MY MONGO_MAPPER APPS</h3>
<ul>
<li> <strong>mongo</strong>
<ul>
<li> [GEM] the base MongoDB ruby driver</li>
</ul>
</li>
<li> <strong>mongo_ext</strong>
<ul>
<li> [GEM] C-extensions for the above to make it perform better</li>
</ul>
</li>
<li> <strong>mongo_mapper</strong>
<ul>
<li> [GEM] John Nunemaker&#8217;s thin ORM layer for Mongo.  fairly young and poorly documented, but it&#8217;s such a thin wrapper that it hasn&#8217;t been a problem for me.  just gives you some basic ActiveRecord-ish relationships and conveniences for using Mongo Documents and EmbeddedDocuments with standard Ruby models.</li>
<li> <a href="http://railstips.org/blog/archives/2009/06/27/mongomapper-the-rad-mongo-wrapper/">http://railstips.org/blog/archives/2009/06/27/mongomapper-the-rad-mongo-wrapper/</a></li>
<li> <a href="http://railstips.org/blog/archives/2009/12/18/why-i-think-mongo-is-to-databases-what-rails-was-to-frameworks/">http://railstips.org/blog/archives/2009/12/18/why-i-think-mongo-is-to-databases-what-rails-was-to-frameworks/</a></li>
<li> <a id="tlav" title="http://rdoc.info/projects/jnunemaker/mongomapper" href="http://rdoc.info/projects/jnunemaker/mongomapper">http://rdoc.info/projects/jnunemaker/mongomapper</a></li>
</ul>
</li>
<li> <strong>sunspot</strong>[GEM] + <strong>sunspot_rails</strong>[GEM] (with custom config for mongo support) &#8211; <a id="yy.0" title="http://github.com/outoftime/sunspot" href="http://github.com/outoftime/sunspot">http://github.com/outoftime/sunspot</a>
<ul>
<li> found that sunspot integrates the solr search engine more easily with mongo than anything else out there.  has a lot of nice features, and it does automatic indexing on the fly, rather than requiring some sort of nasty cron job or handrolled delta-indexing solution</li>
</ul>
</li>
<li> <em>handrolled auth system derived in part from</em> <strong>authlogic</strong>
<ul>
<li> so, i probably should start using Devise, since it apparently has native mongo_mapper support.  but for the two mongo apps I&#8217;ve built thus far, i just handrolled a simple authentication system by adapting the core code from authlogic and removing all the ActiveRecord-specific bits.  works fine, easy to add on custom stuff.  but Devise is probably better for the future.</li>
</ul>
</li>
<li> <strong>machinist</strong>, <strong>shoulda</strong>, <strong>faker</strong>
<ul>
<li> see above</li>
</ul>
</li>
<li> <strong>acts_as_mongo_rateable</strong> (mine) &#8212; <a id="c2pf" title="http://github.com/mepatterson/acts_as_mongo_rateable" href="http://github.com/mepatterson/acts_as_mongo_rateable">http://github.com/mepatterson/acts_as_mongo_rateable</a>
<ul>
<li> I wrote this from scratch, inspired by the basic architecture of the acts_as_rateable plugin for ActiveRecord</li>
</ul>
</li>
<li> <strong>acts_as_mongo_taggable</strong> (mine) &#8211; <a id="hu4g" title="http://github.com/mepatterson/acts_as_mongo_taggable" href="http://github.com/mepatterson/acts_as_mongo_taggable">http://github.com/mepatterson/acts_as_mongo_taggable</a>
<ul>
<li> I wrote this from scratch, inspired by the basic architecture of the acts_as_taggable_on_steroids plugin for ActiveRecord</li>
</ul>
</li>
<li> <strong>will_paginate</strong>
<ul>
<li> works fine with any enumerable object, so works with Mongo</li>
</ul>
</li>
<li> <strong>compass</strong> + <strong>blueprint</strong>
<ul>
<li> see above</li>
</ul>
</li>
<li> <strong>haml</strong> / <strong>sass</strong>
<ul>
<li> see above</li>
</ul>
</li>
<li> <strong>jrails</strong> plugin (+ jquery instead of prototype)
<ul>
<li> see above</li>
</ul>
</li>
<li> <strong>inherited_resources</strong>
<ul>
<li> this works largely the same with Mongo, since your resource-based controller shouldn&#8217;t really have any direct dependence on your database ORM</li>
</ul>
</li>
<li> <strong>hoptoad</strong>
<ul>
<li> see above</li>
</ul>
</li>
</ul>
<h3>STUFF I&#8217;D LIKE TO USE/WANT TO INVESTIGATE FURTHER</h3>
<ul>
<li> <strong>devise</strong> &#8211; <a id="bkx-" title="http://github.com/plataformatec/devise" href="http://github.com/plataformatec/devise">http://github.com/plataformatec/devise</a>
<ul>
<li> has mongo support baked in!  looks really cool and has a lot of robust functionality.</li>
<li> example using with mongomapper &#8211; <a id="hpu." title="http://github.com/theshortcut/devise_mongomapper_example" href="http://github.com/theshortcut/devise_mongomapper_example">http://github.com/theshortcut/devise_mongomapper_example</a></li>
</ul>
</li>
<li> <strong>easy ESI</strong> &#8212; <a id="c_ix" title="http://github.com/grosser/easy_esi" href="http://github.com/grosser/easy_esi">http://github.com/grosser/easy_esi</a>
<ul>
<li> haven&#8217;t looked at it much; seems like an interesting approach</li>
</ul>
</li>
<li> <strong>aegis</strong> &#8211; <a id="g-bj" title="http://github.com/makandra/aegis" href="http://github.com/makandra/aegis">http://github.com/makandra/aegis</a>
<ul>
<li> seems like a really nice way to do complicated roles and permissions.  haven&#8217;t used it though.  dunno if it will work with any of the good auth systems like devise, clearance, authlogic, etc.  in most cases, might just be easier to write your own simple roles system (which is what i&#8217;ve done in ALL cases)</li>
</ul>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.digimonkey.com/2010/02/starting-a-new-rails-app-heres-my-skeleton/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Why use HAML (and SASS)? I already know HTML.</title>
		<link>http://blog.digimonkey.com/2010/02/why-use-haml-and-sass-i-already-know-html/</link>
		<comments>http://blog.digimonkey.com/2010/02/why-use-haml-and-sass-i-already-know-html/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 21:53:49 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[haml]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[sass]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=68</guid>
		<description><![CDATA[<p>The title of the post is more-or-less a verbatim quote from a coworker, as well as from an unrelated colleague of mine from a previous job.  I was asked that question and, to be honest, I was a little thrown both times.  I didn&#8217;t actually know why I use HAML.  I guess I&#8217;d [...]]]></description>
			<content:encoded><![CDATA[<p>The title of the post is more-or-less a verbatim quote from a coworker, as well as from an unrelated colleague of mine from a previous job.  I was asked that question and, to be honest, I was a little thrown both times.  I didn&#8217;t actually know <em>why</em> I use HAML.  I guess I&#8217;d never really considered it much after I started doing everything with it.  It just seemed <em>better</em> and more fun.</p>
<p>So I spent all last night thinking about the answer.  Why use HAML?  For that matter, why use SASS either?  It&#8217;s notable, I guess, that yesterday <a title="Chris Eppstein" href="http://chriseppstein.github.com/" target="_blank">Chris Eppstein</a> was polling his twitter followers on whether they wanted to break SASS and HAML apart to be separate gems &#8230; clearly others out there are using one but not the other.</p>
<p>And I suppose it&#8217;s not enough to answer that I use HAML and SASS because <a href="http://www.ralree.info/2007/2/8/cheating-on-erb-with-haml/" target="_blank">other</a> <a href="http://blog.obiefernandez.com/content/2008/01/are-you-using-h.html" target="_blank">luminaries</a> in the Ruby world <a href="http://railspikes.com/2007/4/9/haml-grigsby-s-first-rule" target="_blank">swear by it</a>.  As my Mom was fond of saying, &#8220;If all the other kids jumped off a cliff&#8230;&#8221;  So I guess that&#8217;s not entirely a valid reason.</p>
<p>So, here&#8217;s my attempt to coalesce <em>my</em> various reasons for using HAML (and SASS) into a single post, and to try and convince <em>you</em> why I think it&#8217;s a great idea.  And to throw a bone to Eppstein, I&#8217;ll try to make a case for why, though I have no problem with them being split into separate gems, I still believe they should always go together, just like peanut butter and grape jam.</p>
<p><span id="more-68"></span></p>
<h3>SIMPLER, SHORTER, LESS WORK</h3>
<p>So this is the obvious one.  Check out the two chunks of code below:</p>
<p>ERB (525 characters; 24 lines)</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:300px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><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;">@users</span>.<span style="color:#9900CC;">empty</span>? <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &lt;div class=&quot;empty_collection&quot;&gt;<br />
&nbsp; &nbsp; &lt;em&gt;Could not find any users.&lt;/em&gt;<br />
&nbsp; &lt;/div&gt;<br />
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">else</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &lt;table class=&quot;users_list&quot;&gt;<br />
&nbsp; &nbsp; &lt;thead&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;tr&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;th&gt;Name&lt;/th&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;th&gt;Email&lt;/th&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;th&gt;Age&lt;/th&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;/tr&gt;<br />
&nbsp; &nbsp; &lt;/thead&gt;<br />
&nbsp; &nbsp; &lt;tbody&gt;<br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#0066ff; font-weight:bold;">@users</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>user<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;tr class=&quot;<span style="color:#006600; font-weight:bold;">&lt;%</span>= cycle<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'odd'</span>,<span style="color:#996600;">'even'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;td&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= user.<span style="color:#9900CC;">name</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/td&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;td&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= user.<span style="color:#9900CC;">email</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/td&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;td&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= user.<span style="color:#9900CC;">age</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/td&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/tr&gt;<br />
&nbsp; &nbsp; &nbsp; <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><br />
&nbsp; &nbsp; &lt;/tbody&gt;<br />
&nbsp; &lt;/table&gt;<br />
<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></div></div>
<p>HAML (331 characters; 16 lines)</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">-</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@users</span>.<span style="color:#9900CC;">empty</span>?<br />
&nbsp; .<span style="color:#9900CC;">empty_collection</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>em Could <span style="color:#9966CC; font-weight:bold;">not</span> find any users<br />
<span style="color:#006600; font-weight:bold;">-</span> <span style="color:#9966CC; font-weight:bold;">else</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">%</span>table.<span style="color:#9900CC;">users_list</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>thead<br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>tr<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>th Name<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>th Email<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>th Age<br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>tbody<br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#0066ff; font-weight:bold;">@users</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>user<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>tr<span style="color:#006600; font-weight:bold;">&#123;</span>:<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> cycle<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'odd'</span>,<span style="color:#996600;">'even'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>td= user.<span style="color:#9900CC;">name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>td= user.<span style="color:#9900CC;">email</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>td= user.<span style="color:#9900CC;">age</span></div></div>
<p>Just in terms of key presses, you&#8217;re hitting the keys 37% less in this case if you use HAML.  In terms of lines of code, you&#8217;re getting a 33% reduction.  (Hell, Wordpress doesn&#8217;t even need to display a scrollbar for the HAML example).  I don&#8217;t know about you, but to me that&#8217;s a significant win right there.  Every second I spend typing monotonous stuff is a second I didn&#8217;t spend building a feature.  And when you&#8217;re writing hundreds of lines of code in a day, that can add up to a lot of extra time to either drink beer or add extra polish to the feature you&#8217;re implementing.</p>
<h3>COGNITIVE DISSONANCE BETWEEN HTML AND CSS</h3>
<p>That&#8217;s just a fancy way of saying &#8220;my brain has to switch gears too much or too drastically, reducing its efficiency.&#8221;  Anyone who has done significant amounts of HTML and CSS can tell you that the constant back-and-forth between the stylesheets and the html templates becomes something of a rhythm, a development pulse of sorts.  But with that rhythm comes delay and context shifts.</p>
<p>In HTML, I type:</p>
<div class="codecolorer-container html4strict blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;highlight&quot;</span>&gt;</span><br />
&nbsp; this is some stuff<br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span></div></div>
<p>In CSS, to style this, I type:</p>
<div class="codecolorer-container css blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="css codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #6666ff;">.highlight</span> <span style="color: #00AA00;">&#123;</span> <br />
&nbsp; <span style="color: #000000; font-weight: bold;">border</span><span style="color: #00AA00;">:</span> <span style="color: #933;">1px</span> <span style="color: #993333;">solid</span> <span style="color: #cc00cc;">#f00</span> <span style="color: #00AA00;">&#125;</span></div></div>
<p>For those of us well-versed in modern web development, that shift isn&#8217;t tough, but it&#8217;s still a shift.</p>
<p>Using HAML:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color:#9900CC;">highlight</span> <br />
&nbsp; this is some stuff</div></div>
<p>That alone improves the contextual parity some, even if you don&#8217;t use SASS and just use straight CSS.  You type &#8220;.highlight&#8221; to make the div.  You type &#8220;.highlight&#8221; to style it.  Simple.</p>
<p>If you use SASS, it gets even better:</p>
<div class="codecolorer-container css blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="css codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #6666ff;">.highlight</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">border</span><span style="color: #00AA00;">:</span> <span style="color: #933;">1px</span> <span style="color: #993333;">solid</span> <span style="color: #cc00cc;">#f00</span></div></div>
<p>Now, you don&#8217;t even have to worry about the curlies (which don&#8217;t exist in HTML, causing cognitive dissonance).  In fact, the &#8220;code&#8221; in both the HAML and SASS templates is nearly identical in structure.  The only difference is that in the former, you provide the data to display, and in the latter, you provide the presentation styling for that data.  If you buy the whole concept behind &#8220;separation of concerns&#8221; (and you should!), this makes life clean and satisfying.</p>
<h3>LOWER BARRIER TO REFACTORING</h3>
<p>If you&#8217;ve spent as much time as I have looking at someone else&#8217;s legacy code in massive enterprise apps, you know how painful it can be to jump in at first.  <em>What the hell does this construct even do?  Why did they implement this?  Why did someone write 6 lines of code that duplicate a function that Ruby/PHP/Java/whatever already has?  What are all these non-standard method calls and where do the actual methods live?</em></p>
<p>This path of fiery hoops must be jumped through before you can really get down to a level of comfort with the code.  And you need that comfort to reach your full development speed when implementing or refactoring in that part of the app.  The faster you can get there, the sooner you&#8217;ll be able to demonstrate your value to the team and to the product.  </p>
<p>The bane of my existence has been so-called &#8220;cowboy coders,&#8221; those individuals who feel it necessary to hack together fast, poorly-considered implementations in order to move on to the next thing and prove to their superiors how &#8220;awesome&#8221; they are, because they can knock out 10 new features a day.  Nice.  Good for you, buddy.  But you&#8217;re costing me, and your team, and therefore yourself, even more time in the long run, with your mistakes, poor architecture that becomes &#8220;too big to remove&#8221; (hmm&#8230;where have I heard that before?), and a product that becomes shackled to the cowboy, who is the only one who understands the parts of the app they wrote.  And God forbid if they ever leave the team&#8230;</p>
<p>HAML/SASS provide a buffer against the cowboy.</p>
<p><del datetime="2010-02-02T15:43:56+00:00">Forcing</del> <del datetime="2010-02-02T15:43:56+00:00">Harassing</del> Coercing your teammates to use HAML (and SASS) reduces the cognitive complexity of the presentation layer (aka the &#8216;view&#8217; for you MVC folk), both in terms of number of lines and characters your brain has to process, and in terms of its immediate understandability.  And that makes you faster, and your team faster, and your teammates faster.  Faster means more features with more polish sooner in the release cycle, with less bugs.  And the reduced complexity has the additional benefit of helping to prevent <em>future</em> bugs, because it&#8217;s more obvious what&#8217;s going on in a particular template.  Think of it as the programming equivalent of <a href="http://en.wikipedia.org/wiki/Scotchgard">Scotchgard</a> sprayed on your templates; it might not prevent every stain, but it helps you get the carpet clean quicker.  </p>
<p>Sure, the cowboy might still plow through poorly thought-out code (that&#8217;s a problem for another day), but at least now it&#8217;s easier to understand WHAT he&#8217;s doing with 200 lines of business logic jammed into the view.  And it&#8217;s easier to see why it should be refactored immediately!</p>
<h3>ENCOURAGING BEST PRACTICES</h3>
<p>At the risk of igniting some holy war about what actually <em>constitutes</em> best practices in the various spheres of HTML, CSS, Ruby, Rails, etc, I think it&#8217;s worth discussing the concept of &#8220;best practices.&#8221;  I think adopting Best Practices has gotten a bad rap in the eyes of some developers, especially those for whom learning the latest and greatest tech in the community seems like &#8220;following a fad.&#8221;  Sometimes, the latest and greatest is actually better, because people in the community are actively thinking about better ways to do the things we do every day.  Don&#8217;t dismiss it out of hand because you&#8217;re defending your little island of knowledge.  Any time you hear yourself saying, &#8220;I already know how to do this. Why should I learn something else?&#8221; &#8230; stop!  Pause and consider your own motivations.  There&#8217;s a chance you&#8217;re dismissing the new tech because you feel threatened by it.  Embrace change, people!  Embrace new ideas!  Try new things!  It will make you (A) more educated in your field and (B) more marketable, which gets you (C) better pay and more responsibility.  This is a much better and more-fulfilling path to job security than defending your turf and digging in your heels while the programming community moves on past you.</p>
<p>So, that said, I think HAML provides a major advantage here, as well.  It&#8217;s established best practice that presentation templates (whether in Rails, or Django, or home-brew MVC-based architectures) should not contain business logic or even much in the way of presentational logic.  HAML does a great job of gently encouraging you to avoid this problem:</p>
<p>This bit of ruby code is straightforward in HAML and, I would argue, reasonable in the view:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">-</span> <span style="color:#0066ff; font-weight:bold;">@users</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>user<span style="color:#006600; font-weight:bold;">|</span></div></div>
<p>But in ERB, you&#8217;ll sometimes see things like this:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">&lt;%</span> <br />
<span style="color:#0066ff; font-weight:bold;">@users</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>user<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; full_name = user.<span style="color:#9900CC;">first_name</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">' '</span> <span style="color:#006600; font-weight:bold;">+</span> user.<span style="color:#9900CC;">last_name</span><br />
&nbsp; savings = <span style="color:#CC0066; font-weight:bold;">sprintf</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;%.2f&quot;</span>, user.<span style="color:#9900CC;">savings</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> savings == 0.0<br />
&nbsp; &nbsp; savings = <span style="color:#0000FF; font-weight:bold;">false</span><br />
&nbsp; &nbsp; savings_row_class = <span style="color:#996600;">'red'</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#006600; font-weight:bold;">%&gt;</span></div></div>
<p>While you <em>could</em> do all that in HAML, the inability to break stuff across multiple lines without starting a new hyphen-fronted line makes it feel <em>icky</em> somehow.  So then it gently encourages you to break up that code into the model and/or helper methods, where it should have been in the first place.</p>
<p>I&#8217;m not saying that HAML and SASS are silver bullets that make you or your teammates code better, but it sure helps.  And when someone you know starts bitching about not being able to break a HAML ruby line into multiple lines, you&#8217;re probably safe in assuming that they are on the path to doing something Naughty&#0153;</p>
<h3>CONCLUSION</h3>
<p>So there you have it.  There are many other reasons to use HAML and SASS that I&#8217;m sure I didn&#8217;t cover here.  The &#8220;fun-ness&#8221; of it, the beauty of the syntax, the ability to have it render templates in different formatting modes depending on production or development environments, etc.  But hopefully this gives you some food for thought on why <em>I</em> use it, and why maybe you should give it a look (or a second look, maybe?)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.digimonkey.com/2010/02/why-use-haml-and-sass-i-already-know-html/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>Mongo Beauty #1</title>
		<link>http://blog.digimonkey.com/2010/02/mongo-beauty-1/</link>
		<comments>http://blog.digimonkey.com/2010/02/mongo-beauty-1/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 05:29:23 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[mongomapper]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=64</guid>
		<description><![CDATA[<p>Frequently, while working with MongoDB and MongoMapper, I run across an implementation of something that blows me away with its beauty.  This, my friends, is one of those times.  </p>
<p>Given: a Users collection where the users&#8217; names are stored in an Array key called name.  i.e. :name => ["Patterson", "Matt"].  It [...]]]></description>
			<content:encoded><![CDATA[<p>Frequently, while working with MongoDB and MongoMapper, I run across an implementation of something that blows me away with its beauty.  This, my friends, is one of those times.  </p>
<p>Given: a Users collection where the users&#8217; names are stored in an Array key called name.  i.e. :name => ["Patterson", "Matt"].  It can be any length, so if they want middle names or titles or whatever, it just gets stuck in there as an element on the array.</p>
<p>Problem: Need to create a really quick lookup to do autocomplete when someone is looking for a particular person in the database.</p>
<p>Solution:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">named</span><span style="color:#006600; font-weight:bold;">&#40;</span>query<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; User.<span style="color:#9900CC;">all</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">/</span>^<span style="color:#008000; font-style:italic;">#{query}.*/i })</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>So when the user types &#8220;m&#8221; into the autocomplete field, it will quickly populate the suggestions with ["Patterson", "Matt"] and ["Magdalene", "Mary"] and ["Munchausen", "Baron"] and ["Mr.", "John", "Arbuckle"].  But it won&#8217;t pickup people with &#8216;m&#8217; in the middle of any of their name components, like ["Hammer", "Captain"].</p>
<p>How simple is that?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.digimonkey.com/2010/02/mongo-beauty-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mongosphinx with MongoDB and MongoMapper</title>
		<link>http://blog.digimonkey.com/2010/01/mongosphinx-with-mongodb-and-mongomapper/</link>
		<comments>http://blog.digimonkey.com/2010/01/mongosphinx-with-mongodb-and-mongomapper/#comments</comments>
		<pubDate>Wed, 20 Jan 2010 23:29:53 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[sphinx]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=43</guid>
		<description><![CDATA[<p>Can that title have the word &#8216;mongo&#8217; in it any more times?  Well, fear not, I&#8217;m about to use it even more&#8230;</p>
<p>So, I had to fool around a bit to get the so-called &#8220;Mongosphinx&#8221; gem working with my app architecture.  Thought it might be helpful to others to demonstrate how I did it. [...]]]></description>
			<content:encoded><![CDATA[<p><em>Can that title have the word &#8216;mongo&#8217; in it any more times?  Well, fear not, I&#8217;m about to use it even more&#8230;</em></p>
<p>So, I had to fool around a bit to get the so-called &#8220;Mongosphinx&#8221; gem working with my app architecture.  Thought it might be helpful to others to demonstrate how I did it.  I&#8217;ll boil it down to a generic sort of implementation.  Hit the jump to see the whole bloody mess&#8230;<br />
<span id="more-43"></span></p>
<h2>app/models/document.rb</h2>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:300px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> Document<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">MongoMapper::Document</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:title</span>, &nbsp;<span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:content</span>, &nbsp;<span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; timestamps!<br />
<br />
&nbsp; <span style="color:#008000; font-style:italic;">#cached for the sphinx indexer</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:sphinx_tags</span>, <span style="color:#CC0066; font-weight:bold;">String</span><br />
<br />
&nbsp; <span style="color:#008000; font-style:italic;"># for mongosphinx</span><br />
&nbsp; fulltext_index <span style="color:#ff3333; font-weight:bold;">:title</span>, <span style="color:#ff3333; font-weight:bold;">:content</span><br />
&nbsp; REINDEX_INTERVAL = 10.<span style="color:#9900CC;">minutes</span><br />
&nbsp; INDEXED_FIELDS = <span style="color:#996600;">'_sphinx_id, title, content, sphinx_tags'</span><br />
&nbsp; before_save: cache_for_indexer<br />
&nbsp; after_save: reindex<br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">search</span><span style="color:#006600; font-weight:bold;">&#40;</span>query<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># method returns a sphinx resultset object with its own each() method</span><br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># iterate over that and pull each element out as an old-fashioned array of Documents</span><br />
&nbsp; &nbsp; by_fulltext_index<span style="color:#006600; font-weight:bold;">&#40;</span>query<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>p<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#CC0066; font-weight:bold;">p</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">xml_for_sphinx_pipe</span><br />
&nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#6666ff; font-weight:bold;">MongoSphinx::Indexer::XMLDocset</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>Document.<span style="color:#9900CC;">all</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:fields</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> INDEXED_FIELDS<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_s</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> cache_for_indexer<br />
&nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">sphinx_tags</span> = tag_words.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">' '</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">true</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> reindex<br />
&nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mongo/gridfs'</span><br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># we run this method whenever a doc is saved, but we only actually reindex every 10 minutes, max</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">unless</span> RAILS_ENV == <span style="color:#996600;">'test'</span><br />
&nbsp; &nbsp; &nbsp; db = MongoMapper.<span style="color:#9900CC;">database</span><br />
&nbsp; &nbsp; &nbsp; file = <span style="color:#996600;">&quot;indexer_next_run&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#6666ff; font-weight:bold;">GridFS::GridStore</span>.<span style="color:#9900CC;">exist</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>db, file<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; line = <span style="color:#6666ff; font-weight:bold;">GridFS::GridStore</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>db, file, <span style="color:#996600;">'r'</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#CC0066; font-weight:bold;">readlines</span><span style="color:#006600; font-weight:bold;">&#91;</span>0<span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#0000FF; font-weight:bold;">false</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span> <span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>line<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; &nbsp; next_run = <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> REINDEX_INTERVAL<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_s</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#6666ff; font-weight:bold;">GridFS::GridStore</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>db, file, <span style="color:#996600;">'w'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#CC0066; font-weight:bold;">puts</span> next_run <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; logger.<span style="color:#9900CC;">info</span> <span style="color:#996600;">&quot;Running document re-indexer&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">Process</span>.<span style="color:#CC0066; font-weight:bold;">fork</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">`rake sphinx:index rotate=true`</span> <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>I&#8217;ll illuminate some of that for you.</p>
<p>If you&#8217;ve been using MongoMapper, most of the key stuff should be obvious already.  The &#8217;sphinx_tags&#8217; is a special trick I cooked up to make this work well with my <a href="http://github.com/mepatterson/acts_as_mongo_taggable">acts_as_mongo_taggable</a> plugin.  Basically, whenever a Document is saved/updated, I jam a single string into the sphinx_tags field in Mongo.  This lets sphinx index those tags easily.</p>
<p>The search just takes advantage of Mongosphinx&#8217;s normal by_fulltext_index method.</p>
<p>The reindex thing, while probably a hacky solution, works well enough for now that I don&#8217;t have a need to do anything fancier.  This lets us have the app be reasonably quick to include newly-created documents in the index to be available for search.  And I take advantage of GridFS (built into Mongo) to store my last_run value so I don&#8217;t even need a cron job for this.  If my app starts getting significant document-creation traffic, I might want to do something more sophisticated like delta indexing or whatnot, but for now this is fine for me.</p>
<h2>lib/tasks/sphinx.rake</h2>
<p>Okay, moving on to the aforementioned rake tasks&#8230; Here are the contents of my lib/tasks/sphinx.rake file:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:300px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">namespace <span style="color:#ff3333; font-weight:bold;">:sphinx</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; desc <span style="color:#996600;">&quot;generate xml that is sphinx-friendly&quot;</span><br />
&nbsp; task <span style="color:#ff3333; font-weight:bold;">:genxml</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:environment</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># this will just puts() to stdout; useful for debugging</span><br />
&nbsp; &nbsp; Document.<span style="color:#9900CC;">xml_for_sphinx_pipe</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <br />
&nbsp; desc <span style="color:#996600;">&quot;start up the sphinx daemon&quot;</span><br />
&nbsp; task <span style="color:#ff3333; font-weight:bold;">:start</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:environment</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; cmd = <span style="color:#006600; font-weight:bold;">%</span><span style="color:#006600; font-weight:bold;">&#40;</span> searchd <span style="color:#006600; font-weight:bold;">--</span>config <span style="color:#996600;">&quot;#{Rails.root}/config/sphinx.conf&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">system</span>! cmd<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <br />
&nbsp; desc <span style="color:#996600;">&quot;stop the sphinx daemon&quot;</span><br />
&nbsp; task <span style="color:#ff3333; font-weight:bold;">:stop</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:environment</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">system</span>! <span style="color:#006600; font-weight:bold;">%</span><span style="color:#006600; font-weight:bold;">&#40;</span> searchd <span style="color:#006600; font-weight:bold;">--</span>config <span style="color:#996600;">&quot;#{Rails.root}/config/sphinx.conf&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <br />
&nbsp; desc <span style="color:#996600;">&quot;run the sphinx indexer&quot;</span><br />
&nbsp; task <span style="color:#ff3333; font-weight:bold;">:index</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:environment</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; cmd = <span style="color:#006600; font-weight:bold;">%</span><span style="color:#006600; font-weight:bold;">&#40;</span> indexer <span style="color:#006600; font-weight:bold;">--</span>config <span style="color:#996600;">&quot;#{Rails.root}/config/sphinx.conf&quot;</span> <span style="color:#006600; font-weight:bold;">--</span>all <span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; cmd <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#996600;">' --rotate'</span> <span style="color:#9966CC; font-weight:bold;">if</span> ENV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'rotate'</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> ENV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'rotate'</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">downcase</span> == <span style="color:#996600;">'true'</span><br />
&nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">system</span>! cmd<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#008000; font-style:italic;"># a fail-fast, hopefully helpful version of system</span><br />
<span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#CC0066; font-weight:bold;">system</span>!<span style="color:#006600; font-weight:bold;">&#40;</span>cmd<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#CC0066; font-weight:bold;">system</span><span style="color:#006600; font-weight:bold;">&#40;</span>cmd<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;-</span>SYSTEM_CALL_FAILED<br />
The following command failed:<br />
&nbsp; <span style="color:#008000; font-style:italic;">#{cmd}</span><br />
SYSTEM_CALL_FAILED<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>So this should be pretty self-explanatory, especially if you&#8217;ve already used acts_as_sphinx with a standard ActiveRecord-backed app.  After you&#8217;ve gotten everything (sphinx and the <a href="http://github.com/dacort/mongosphinx">mongosphinx gem</a>, specifically) installed, you should be able to use these rake tasks to start and stop the searchd daemon, as well as run the indexer.</p>
<p>(update 1/22/10: Note that I&#8217;m suggesting you get dacort&#8217;s fork of mongosphinx.  He&#8217;s done a nice job of adding excerpting, pagination, and better compatibility with the latest mongomapper.  He also pulled in my fix that makes it play nice with ruby 1.9.)</p>
<p>One nicety here is the sphinx:genxml task.  Running this is helpful when you&#8217;re trying to get everything setup, to prove that you&#8217;ve done things right.  It should output a big XML file of all the documents it would index.  If it doesn&#8217;t, or you get something weird, then <a href="http://icanhascheezburger.files.wordpress.com/2007/04/wrong-mike.jpg">ur doin&#8217; it wrong</a>.</p>
<h2>config/sphinx.conf</h2>
<p>Finally, to help you get up and running, here&#8217;s my config/sphinx.conf file.  Pretty standard:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:300px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">searchd <span style="color: #7a0874; font-weight: bold;">&#123;</span><br />
&nbsp; listen = 127.0.0.1<br />
&nbsp; port = 9312<br />
<br />
&nbsp; log = .<span style="color: #000000; font-weight: bold;">/</span>sphinx<span style="color: #000000; font-weight: bold;">/</span>searchd.log<br />
&nbsp; query_log = .<span style="color: #000000; font-weight: bold;">/</span>sphinx<span style="color: #000000; font-weight: bold;">/</span>searchd.query.log<br />
&nbsp; pid_file = .<span style="color: #000000; font-weight: bold;">/</span>sphinx<span style="color: #000000; font-weight: bold;">/</span>searchd.pid<br />
<span style="color: #7a0874; font-weight: bold;">&#125;</span><br />
<br />
<span style="color: #7a0874; font-weight: bold;">source</span> mongo_project <span style="color: #7a0874; font-weight: bold;">&#123;</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">type</span> = xmlpipe2<br />
<br />
&nbsp; xmlpipe_command = .<span style="color: #000000; font-weight: bold;">/</span>script<span style="color: #000000; font-weight: bold;">/</span>runner <span style="color: #ff0000;">&quot;Document.xml_for_sphinx_pipe&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">&#125;</span><br />
<br />
index mongo_project <span style="color: #7a0874; font-weight: bold;">&#123;</span><br />
&nbsp; <span style="color: #7a0874; font-weight: bold;">source</span> = mongo_project<br />
<br />
&nbsp; charset_type = utf-<span style="color: #000000;">8</span><br />
&nbsp; path = .<span style="color: #000000; font-weight: bold;">/</span>sphinx<span style="color: #000000; font-weight: bold;">/</span>sphinx_index_main<br />
<span style="color: #7a0874; font-weight: bold;">&#125;</span></div></div>
<p>Again, all of this may fall down spectacularly once you get up to some serious data being pushed from the app into the indexer.  At that point, do something else, something more awesome.  But consider this a basic start on jamming data from your mongo collection(s) right up sphinx&#8217;s pipe.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.digimonkey.com/2010/01/mongosphinx-with-mongodb-and-mongomapper/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Better Bundles: HAML and SASS</title>
		<link>http://blog.digimonkey.com/2010/01/better-bundles-haml-and-sass/</link>
		<comments>http://blog.digimonkey.com/2010/01/better-bundles-haml-and-sass/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 19:16:12 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=41</guid>
		<description><![CDATA[<p>I use HAML and SASS pretty heavily.  And it&#8217;s nice having a good Textmate bundle with macros and proper highlighting.  For whatever reason, the &#8217;standard&#8217; HAML and SASS bundles kind of petered out around 2008 and didn&#8217;t really keep up with the changes in HAML and SASS properly.  But that&#8217;s okay!  [...]]]></description>
			<content:encoded><![CDATA[<p>I use <a href="http://haml-lang.com/">HAML</a> and <a href="http://sass-lang.com/">SASS</a> pretty heavily.  And it&#8217;s nice having a good Textmate bundle with macros and proper highlighting.  For whatever reason, the &#8217;standard&#8217; HAML and SASS bundles kind of petered out around 2008 and didn&#8217;t really keep up with the changes in HAML and SASS properly.  But that&#8217;s okay!  Behold github and its community!  So here&#8217;s the two forked versions of the best original bundles that I&#8217;ve found and like the most:</p>
<p>SASS: </p>
<blockquote><p>git://github.com/charlesr/ruby-sass-tmbundle.git</p></blockquote>
<p>HAML:</p>
<blockquote><p>git://github.com/benhoskings/ruby-haml.tmbundle.git</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.digimonkey.com/2010/01/better-bundles-haml-and-sass/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rails Metal + Thin = no &#8216;each&#8217; for String?</title>
		<link>http://blog.digimonkey.com/2010/01/rails-metal-thin-no-each-for-string/</link>
		<comments>http://blog.digimonkey.com/2010/01/rails-metal-thin-no-each-for-string/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:31:17 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[thin]]></category>

		<guid isPermaLink="false">http://digimonkey.com/mepblog/?p=24</guid>
		<description><![CDATA[<p>Just solved an interesting problem when using the latest Thin web server (1.2.5) with Ruby 1.9.1 and Rails Metal.</p>
<p>The code in Rails Metal endpoint:</p>
&#160; def call&#40;env&#41;
&#160; &#160; if env&#91;&#34;PATH_INFO&#34;&#93; =~ /^\/tags.txt/
&#160; &#160; &#160; request = Rack::Request.new&#40;env&#41;
&#160; &#160; &#160; params = request.params
&#160; &#160; &#160; query = params&#91;'q'&#93;
&#160; &#160; &#160; &#91;200, &#123; &#34;Content-Type&#34; =&#62; &#34;text/plain&#34; &#125;, words_from&#40;query&#41;.join&#40;&#34;\n&#34;&#41;&#93;
&#160; [...]]]></description>
			<content:encoded><![CDATA[<p>Just solved an interesting problem when using the latest Thin web server (1.2.5) with Ruby 1.9.1 and Rails Metal.</p>
<p>The code in Rails Metal endpoint:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> call<span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> env<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;PATH_INFO&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> =~ <span style="color:#006600; font-weight:bold;">/</span>^\<span style="color:#006600; font-weight:bold;">/</span>tags.<span style="color:#9900CC;">txt</span><span style="color:#006600; font-weight:bold;">/</span><br />
&nbsp; &nbsp; &nbsp; request = <span style="color:#6666ff; font-weight:bold;">Rack::Request</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; params = request.<span style="color:#9900CC;">params</span><br />
&nbsp; &nbsp; &nbsp; query = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'q'</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">200</span>, <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;Content-Type&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;text/plain&quot;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>, words_from<span style="color:#006600; font-weight:bold;">&#40;</span>query<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;<span style="color:#000099;">\n</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">else</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">404</span>, <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;Content-Type&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;text/html&quot;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>, <span style="color:#996600;">&quot;Not Found&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>Don&#8217;t worry about what words_from(query) actually does.  It just returns an array of words.  The deal is, I was trying to output a list of tags for use with a javascript autocompleter &#8212; one tag per line in a plain/text file for speed.  Sure, sure, I could use JSON or XML or whatever, but I didn&#8217;t, because it was easier to get the javascript thing working quickly this way and I&#8217;m lazy.</p>
<p>Under ruby 1.8.7 with thin or webrick, this works fine.  Under ruby 1.9.1 with Webrick (ugh!), this works fine.  Under ruby 1.9.1, with Thin, this bombs with:</p>
<blockquote><p>!! Unexpected error while processing request: undefined method `each&#8217; for #&lt;String:0&#215;000001037abd08&gt;</p></blockquote>
<p>After two hours of debugging, here&#8217;s the simple fix &#8212; pass an array with one string element to the return line instead of a pure string object:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">200</span>, <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;Content-Type&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;text/plain&quot;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>, <span style="color:#006600; font-weight:bold;">&#91;</span>words_from<span style="color:#006600; font-weight:bold;">&#40;</span>query<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;<span style="color:#000099;">\n</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#93;</span></div></div>
<p>Seriously?  Yes.  Seriously.</p>
<p>This makes Thin happy and prevents it from trying to enumerate a String, which doesn&#8217;t work in Ruby 1.9.</p>
<p>I haven&#8217;t gone back yet to see if this borks the other web servers, but I&#8217;m using Thin on this one anyway, so at the moment I don&#8217;t really care.  As always, your mileage may vary.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.digimonkey.com/2010/01/rails-metal-thin-no-each-for-string/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Sweet OS X aliases</title>
		<link>http://blog.digimonkey.com/2010/01/sweet-os-x-aliases/</link>
		<comments>http://blog.digimonkey.com/2010/01/sweet-os-x-aliases/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 21:47:01 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://digimonkey.com/mepblog/?p=18</guid>
		<description><![CDATA[<p>Put all this crap in your ~/.aliases file.  Do it!</p>
alias migrate=&#34;rake db:migrate db:test:prepare&#34;
alias remigrate=&#34;rake db:migrate &#38;&#38; rake db:migrate:redo &#38;&#38; rake db:schema:dump db:test:prepare&#34;
alias gadd=&#34;git add -u &#38;&#38; git add . &#38;&#38; git status&#34;
alias svnprecommit=&#34;git svn rebase &#38;&#38; rake features &#38;&#38; rake test&#34;
alias cuc=&#34;cucumber -r features&#34;
alias g=&#34;git&#34;
alias tu=&#34;ruby_test unit&#34;
alias tf=&#34;ruby_test functional&#34;
alias su=&#34;ruby_tu_rs unit&#34;
alias sf=&#34;ruby_tu_rs functional&#34;
alias ti=&#34;ruby_test [...]]]></description>
			<content:encoded><![CDATA[<p>Put all this crap in your ~/.aliases file.  Do it!</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:300px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">migrate</span>=<span style="color: #ff0000;">&quot;rake db:migrate db:test:prepare&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">remigrate</span>=<span style="color: #ff0000;">&quot;rake db:migrate &amp;&amp; rake db:migrate:redo &amp;&amp; rake db:schema:dump db:test:prepare&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gadd</span>=<span style="color: #ff0000;">&quot;git add -u &amp;&amp; git add . &amp;&amp; git status&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">svnprecommit</span>=<span style="color: #ff0000;">&quot;git svn rebase &amp;&amp; rake features &amp;&amp; rake test&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">cuc</span>=<span style="color: #ff0000;">&quot;cucumber -r features&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">g</span>=<span style="color: #ff0000;">&quot;git&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">tu</span>=<span style="color: #ff0000;">&quot;ruby_test unit&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">tf</span>=<span style="color: #ff0000;">&quot;ruby_test functional&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #c20cb9; font-weight: bold;">su</span>=<span style="color: #ff0000;">&quot;ruby_tu_rs unit&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">sf</span>=<span style="color: #ff0000;">&quot;ruby_tu_rs functional&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">ti</span>=<span style="color: #ff0000;">&quot;ruby_test integration&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gi</span>=<span style="color: #ff0000;">&quot;sudo gem install&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">giv</span>=<span style="color: #ff0000;">&quot;sudo gem install -v&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gci</span>=<span style="color: #ff0000;">&quot;git pull --rebase &amp;&amp; rake &amp;&amp; git push&quot;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># [misc]</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">l</span>=<span style="color: #ff0000;">&quot;ls -alh&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">finder</span>=<span style="color: #ff0000;">&quot;open .&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #c20cb9; font-weight: bold;">grep</span>=<span style="color: #ff0000;">'grep --color=auto'</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">safari</span>=<span style="color: #ff0000;">'open -a Safari'</span><br />
<br />
<span style="color: #666666; font-style: italic;"># [git]</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gsup</span>=<span style="color: #ff0000;">&quot;git submodule update --init&quot;</span><br />
<span style="color: #666666; font-style: italic;"># [rails]</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gen</span>=<span style="color: #ff0000;">'ruby script/generate'</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">con</span>=<span style="color: #ff0000;">&quot;ruby script/console&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">taildev</span>=<span style="color: #ff0000;">&quot;tail -f log/development.log&quot;</span></div></div>
<p>Hooray!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.digimonkey.com/2010/01/sweet-os-x-aliases/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing CRM114 on OS X Snow Leopard</title>
		<link>http://blog.digimonkey.com/2010/01/installing-crm114-on-os-x-snow-leopard/</link>
		<comments>http://blog.digimonkey.com/2010/01/installing-crm114-on-os-x-snow-leopard/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 19:38:33 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[crm114]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://digimonkey.com/mepblog/?p=4</guid>
		<description><![CDATA[<p>Here&#8217;s what I had to do to get it working:</p>
Install &#8216;tre&#8217;
<p>- but *don&#8217;t* use macports; tried that and it bombed, instead do:</p>
wget http://crm114.sourceforge.net/tarballs/tre-0.7.5.tar.gz
tar zxvf tre-0.7.5.tar.gz
cd tre-0.7.5
./configure
make &#38;amp;&#38;amp; sudo make install
Install &#8216;crm114&#8242;
&#160;wget -m -np http://crm114.sourceforge.net/src/
Follow Directions!
<p>now, follow these directions</p>
<p>Enjoy!</p>
]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s what I had to do to get it working:</p>
<h3>Install &#8216;tre&#8217;</h3>
<p>- but *don&#8217;t* use macports; tried that and it bombed, instead do:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>crm114.sourceforge.net<span style="color: #000000; font-weight: bold;">/</span>tarballs<span style="color: #000000; font-weight: bold;">/</span>tre-0.7.5.tar.gz<br />
<span style="color: #c20cb9; font-weight: bold;">tar</span> zxvf tre-0.7.5.tar.gz<br />
<span style="color: #7a0874; font-weight: bold;">cd</span> tre-0.7.5<br />
.<span style="color: #000000; font-weight: bold;">/</span>configure<br />
<span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000; font-weight: bold;">&amp;</span>amp; <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #c20cb9; font-weight: bold;">install</span></div></div>
<h3>Install &#8216;crm114&#8242;</h3>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp;<span style="color: #c20cb9; font-weight: bold;">wget</span> <span style="color: #660033;">-m</span> <span style="color: #660033;">-np</span> http:<span style="color: #000000; font-weight: bold;">//</span>crm114.sourceforge.net<span style="color: #000000; font-weight: bold;">/</span>src<span style="color: #000000; font-weight: bold;">/</span></div></div>
<h3>Follow Directions!</h3>
<p>now, follow <a href="http://www.huyng.com/archives/309">these directions</a></p>
<p><em>Enjoy!</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.digimonkey.com/2010/01/installing-crm114-on-os-x-snow-leopard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
