<?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>M. E. Patterson - Author, Geek &#187; Coding</title>
	<atom:link href="http://mepatterson.net/category/coding/feed/" rel="self" type="application/rss+xml" />
	<link>http://mepatterson.net</link>
	<description>bestselling author of Devil&#039;s Hand, a supernatural thriller; writer of fictions and web software</description>
	<lastBuildDate>Sun, 18 Dec 2011 23:19:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
	<!-- google_ad_section_end --><!-- google_ad_section_start -->	<item>
		<title>Devil&#8217;s Hand is on Blog Tour!</title>
		<link>http://mepatterson.net/2011/10/devils-hand-is-on-blog-tour/</link>
		<comments>http://mepatterson.net/2011/10/devils-hand-is-on-blog-tour/#comments</comments>
		<pubDate>Sat, 22 Oct 2011 15:24:26 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>

		<guid isPermaLink="false">http://mepatterson.net/?p=289</guid>
		<description><![CDATA[Just a reminder to all my fans and interested folks that my supernatural thriller, Devil&#8217;s Hand, is currently on blog tour through November. What the heck does that mean, you ask? Well, it means that various reading/writing blogs, book review blogs, and blogs supporting the world of literature will be hosting reviews, interviews, and a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://mepatterson.net/wp-content/uploads/2011/10/small_tall_book3d.jpg"><img class="alignleft size-full wp-image-292" title="small_tall_book3d" src="http://mepatterson.net/wp-content/uploads/2011/10/small_tall_book3d.jpg" alt="" width="100" height="160" /></a>Just a reminder to all my fans and interested folks that my <a title="Devil's Hand: a supernatural thriller" href="http://bit.ly/dhx1">supernatural thriller, Devil&#8217;s Hand</a>, is currently on blog tour through November. What the heck does that mean, you ask? Well, it means that various reading/writing blogs, book review blogs, and blogs supporting the world of literature will be hosting reviews, interviews, and a couple giveaways!</p>
<p>Check out my tour schedule <a href="http://www.pumpupyourbook.com/2011/09/23/devils-hand-virtual-book-publicity-tour-octobernovember-2011/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mepatterson.net/2011/10/devils-hand-is-on-blog-tour/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing, Marketing, Programming, Designing</title>
		<link>http://mepatterson.net/2011/08/writing-marketing-programming-designing/</link>
		<comments>http://mepatterson.net/2011/08/writing-marketing-programming-designing/#comments</comments>
		<pubDate>Mon, 22 Aug 2011 15:09:05 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Writing]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[marketing]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[publishing]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=203</guid>
		<description><![CDATA[So I have a confession to make: I do more than just write software. I know! Gasp, right? I&#8217;ll bet no one was expecting that! Yeah, well it&#8217;s true. Per my previous post, I&#8217;m also a (now published) author, a marketer-of-sorts, and in addition to programming, I&#8217;m also reasonably well-versed in design. I&#8217;ve designed more [...]]]></description>
			<content:encoded><![CDATA[<p>So I have a confession to make: I do more than just write software. I know! Gasp, right? I&#8217;ll bet no one was expecting that! Yeah, well it&#8217;s true. Per my previous post, I&#8217;m also a (<a title="Buy a copy of Devil's Hand!" href="http://amzn.to/dhkindle">now published</a>) author, a marketer-of-sorts, and in addition to programming, I&#8217;m also reasonably well-versed in design. I&#8217;ve designed more websites than I can count, I did all the cover art for my book, did the PDF layout for the actual printed book cover, did the interior book typography and layout, all the way down to deciding how to format the chapter headings and whether or not to put italics on the page numbers at the top right/left of each page. Ta da!</p>
<p>Lest this turn into a self-promoting, self-congratulating garbage post, I should probably get to the point why I&#8217;m listing all this: <strong>To succeed in today&#8217;s digital world, I believe you need to learn to do more than one thing. </strong>Hit the jump for more&#8230;</p>
<p><span id="more-203"></span>When I was a kid, I was going to be a scientist someday. Then a writer. Then a movie director. Then a computer programmer. Given my proclivity for pushing plastic keys and messing with calculators, the latter came pretty naturally. But then college: the computer engineering program I entered was focused on compilers and shrink-wrapped software; this whole &#8216;internet&#8217; and &#8216;hypertext&#8217; thing seemed a bit faddish. But that&#8217;s what <em>I</em> was interested in. So I switched to English where, not only did I get to read books and write, but the profs there were actually psyched about HTML &#8212; they saw it as a new future where everyone in the world would read their manifesto on &#8220;British colonial attitudes between the years of 1862 and 1864.&#8221;</p>
<p>Yeah, so, fast-forward to today.</p>
<p>Film industry is changing.</p>
<p>Music is changing.</p>
<p>And now publishing is changing.</p>
<p>Not to mention newspapers, magazines, and everything else related to the printed word. So the question you have to ask yourself, as a programmer, or a writer, or a graphic designer is: <strong>am I learning new things that will help me leverage my top skills in other verticals (to use some biz-speak)?</strong></p>
<p>To come at it another way &#8212; you can do one of the aforementioned things, and that&#8217;s great, and you can probably get people to pay you to do it. But if you&#8217;re a programmer, why not learn to write and kick out a self-pubbed book on programming related to your particular specialty? Or polish up some design skills: at the least, learn some color theory and basic front-end HTML 5. If you&#8217;re a graphic designer, you damn well better be learning HTML and CSS or you&#8217;re sunk as the ad agencies all start going digital/interactive. If you&#8217;re a writer and you&#8217;re still poking your typewriter and ignoring the world of social media, internet publishing, and design, then you&#8217;re going to end up spending a lot of money paying guys like me to do stuff for you when you either (A) self-publish or (B) your Big Publishing publisher tells you &#8220;do the marketing your damn self because we&#8217;re cutting budgets.&#8221;</p>
<p>And I&#8217;m not saying that this secondary or tertiary skill you pick up needs to be polished to diamond clarity. You don&#8217;t need to become <a href="http://nobelprize.org/nobel_prizes/literature/laureates/2010/">Mario Llosa</a> to add some oomph to your programming skills. You don&#8217;t need to become Van Gogh to learn to make website designs that are better than <a href="http://www.angelfire.com/super/badwebs/">this</a>. And you don&#8217;t need to know the ins-and-outs of Ruby&#8217;s eigenclass if you want to improve your ability to do internet marketing for your book.</p>
<p>But you do owe it to yourself to push the boundaries of your comfort zone and go beyond your expertise. It will pay off in dividends.</p>
]]></content:encoded>
			<wfw:commentRss>http://mepatterson.net/2011/08/writing-marketing-programming-designing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Check out my supernatural thriller!</title>
		<link>http://mepatterson.net/2011/07/buy-my-supernatural-thriller/</link>
		<comments>http://mepatterson.net/2011/07/buy-my-supernatural-thriller/#comments</comments>
		<pubDate>Thu, 28 Jul 2011 16:24:14 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[devils hand]]></category>
		<category><![CDATA[novel]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=198</guid>
		<description><![CDATA[It&#8217;s a bit of a departure from my normal subjects on this blog, but I wrote a book and would love if it readers gave it a try (and passed the word along!) It&#8217;s a supernatural thriller about demons, angels, poker, and armageddon, set in Las Vegas. If you like Tim Powers or Dean Koontz, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://amzn.to/dhkindle"><img class="alignleft size-medium wp-image-200" title="Devil's Hand : a supernatural thriller" src="http://blog.digimonkey.com/wp-content/uploads/2011/07/book_cover_web-197x300.jpg" alt="Devil's Hand : a supernatural thriller" width="197" height="300" /></a>It&#8217;s a bit of a departure from my normal subjects on this blog, but <strong>I wrote a book</strong> and would love if it readers gave it a try (and passed the word along!)</p>
<p>It&#8217;s a supernatural thriller about demons, angels, poker, and armageddon, set in Las Vegas. If you like Tim Powers or Dean Koontz, you&#8217;ll probably dig this.</p>
<p>It&#8217;s only $2.99 for e-readers. $11.95 if you want a for-reals paperback.</p>
<p>ebook for Kindle/Kindle App: <a href="http://amzn.to/dhkindle" rel="nofollow" target="_blank">http://amzn.to/dhkindle</a><br />
ebook for Nook: <a href="http://bit.ly/dhnook" rel="nofollow" target="_blank">http://bit.ly/dhnook</a><br />
paperback: <a title="Devil's Hand - paperback" href="http://amzn.to/qxQEgw">http://amzn.to/qxQEgw</a></p>
<p>And if you buy it, read it, and like it, please drop by Amazon and give it a quick review. Every review helps get it more exposure to readers that might not otherwise ever hear about the novel. Thanks!</p>
]]></content:encoded>
			<wfw:commentRss>http://mepatterson.net/2011/07/buy-my-supernatural-thriller/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>SQL/NoSQL Debate? Why?</title>
		<link>http://mepatterson.net/2011/05/sqlnosql-debate-why/</link>
		<comments>http://mepatterson.net/2011/05/sqlnosql-debate-why/#comments</comments>
		<pubDate>Fri, 27 May 2011 14:03:37 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[databases]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=194</guid>
		<description><![CDATA[Short post here. I&#8217;m tired of hearing about the SQL/NoSQL &#8220;debate.&#8221; Seriously. I don&#8217;t really understand why there&#8217;s a need to stake out territory and then start a war over techno-ideologies. In my opinion, this debate is like having a debate about cars vs. pickup trucks. There are valid pros/cons to buying cars and valid [...]]]></description>
			<content:encoded><![CDATA[<p>Short post here. I&#8217;m tired of hearing about the SQL/NoSQL &#8220;debate.&#8221; Seriously. I don&#8217;t really understand why there&#8217;s a need to stake out territory and then start a war over techno-ideologies.</p>
<p>In my opinion, this debate is like having a debate about cars vs. pickup trucks. There are valid pros/cons to buying cars and valid pros/cons to buying pickup trucks. In fact, it&#8217;s totally valid for one person to own both a car and a pickup truck! Gasp! I know, it&#8217;s mind-blowing!</p>
<p>I&#8217;ll add that, as a proponent of <a href="http://www.mongodb.org/">MongoDB</a>, I definitely think the right NoSQL database is a better solution in many ways for much of the web-app databasing that was previously handled by relational DBs. But my saying that in no way indicates that I think SQL is dead, relational is dead, or anything of that sort. This is a classic &#8216;right tools for the job&#8217; discussion.</p>
<p>If there&#8217;s any debate at all, maybe it&#8217;s around what, specifically, the best use cases are for each type of database, but I&#8217;d prefer that we stop referring to that as a debate and instead just see it as an ongoing evolution and discussion. Creating conflict where there doesn&#8217;t need to be any solves nothing and makes us all look bad.</p>
]]></content:encoded>
			<wfw:commentRss>http://mepatterson.net/2011/05/sqlnosql-debate-why/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Basic Linux Server Hardening</title>
		<link>http://mepatterson.net/2011/02/basic-linux-server-hardening/</link>
		<comments>http://mepatterson.net/2011/02/basic-linux-server-hardening/#comments</comments>
		<pubDate>Fri, 18 Feb 2011 15:46:27 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[clamav]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[servers]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=184</guid>
		<description><![CDATA[Some excellent tools and tricks to consider when hardening the security on your Linux server, mostly listed here for my own benefit later: Linux Malware Detector on a daily scan mod_security for Apache moving /tmp to a non-executable partition daily scan with ClamAV&#8217;s clamscan utility moving SSH to a nonstandard port removing the ability for [...]]]></description>
			<content:encoded><![CDATA[<p>Some excellent tools and tricks to consider when hardening the security on your Linux server, mostly listed here for my own benefit later:</p>
<ul>
<li>Linux Malware Detector on a daily scan</li>
<li>mod_security for Apache</li>
<li>moving /tmp to a non-executable partition</li>
<li>daily scan with ClamAV&#8217;s clamscan utility</li>
<li>moving SSH to a nonstandard port</li>
<li>removing the ability for root to login through SSH</li>
<li>(even better) making SSH auth-key-based only, so no user/password logins at all!</li>
</ul>
<p>This setup will at the very least harden your server against the bulk of irritating script-based assaults.  There&#8217;s lots more that can (and should) be done, but I&#8217;m starting to think that most of the things I&#8217;ve just listed are required nowadays (certainly the SSH ones are).</p>
]]></content:encoded>
			<wfw:commentRss>http://mepatterson.net/2011/02/basic-linux-server-hardening/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mongoid + Carrierwave + Virus scanning!</title>
		<link>http://mepatterson.net/2010/12/mongoid-carrierwave-virus-scanning/</link>
		<comments>http://mepatterson.net/2010/12/mongoid-carrierwave-virus-scanning/#comments</comments>
		<pubDate>Thu, 30 Dec 2010 17:00:32 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[clamav]]></category>
		<category><![CDATA[inherited_resources]]></category>
		<category><![CDATA[mongoid]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[virus]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=174</guid>
		<description><![CDATA[Ever wanted to have your app virus-scan uploads BEFORE you attach them to a model?  My BigAuthor app for writers and agents needed to do exactly that &#8212; I didn&#8217;t want some bozo uploading a virus-laden Word doc and then distributing to all the agents that log in to the site.  So I set to [...]]]></description>
			<content:encoded><![CDATA[<p>Ever wanted to have your app virus-scan uploads BEFORE you attach them to a model?  My <a href="http://bigauthor.com">BigAuthor app for writers and agents</a> needed to do exactly that &#8212; I didn&#8217;t want some bozo uploading a virus-laden Word doc and then distributing to all the agents that log in to the site.  So I set to work&#8230; I thought this was a fun little implementation that I pulled off with relatively little code.</p>
<p><span id="more-174"></span>First, you gotta setup Mongoid with Carrierwave and all that junk.  I&#8217;m not going to explain how all that works.  It&#8217;s not terribly difficult.  <a href="https://github.com/jnicklas/carrierwave">Figure it out</a>.  The salient point is that you should go ahead and get your model and controller all wired up so that Carrierwave processes the file upload and attaches it to your Mongoid model correctly.  For now, ignore the virus-scanning bit and just get that working.  Once you&#8217;re there, read on&#8230;</p>
<p>THE CONTROLLER</p>
<p>The first trick is that you don&#8217;t want to just attach the file to the model anymore, since you want to verify it&#8217;s cleanliness <em>first</em>.  So we need to shunt it to the file system in a temp directory where we can scan it.  </p>
<p>Your &#8216;create&#8217; method on the controller might look something like this (using InheritedResources here for simplicity):</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> create<br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@project</span> = current_user.<span style="color:#9900CC;">projects</span>.<span style="color:#9900CC;">build</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;">:project</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; shunt_manuscript_through_viruscan<br />
&nbsp; &nbsp; create!<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>So what we&#8217;re saying is that we shunt the manuscript off before we create the project and save the object to mongo.  Obviously.</p>
<p>Here&#8217;s that method (I&#8217;ve removed some extra code that&#8217;s not relevant to the discussion):</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> shunt_manuscript_through_viruscan<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:project</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:manuscript</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; manu = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:project</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:manuscript</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; filename = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:project</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:manuscript</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">original_filename</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># we delete this param now, so it doesn't pass thru to the model immediately</span><br />
&nbsp; &nbsp; &nbsp; params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:project</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:manuscript</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@project</span>.<span style="color:#9900CC;">manuscript_upload_pending</span> = <span style="color:#0000FF; font-weight:bold;">true</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># write it to filesystem immediately, in user-specific tmp dir</span><br />
&nbsp; &nbsp; &nbsp; save_location = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>Rails.<span style="color:#9900CC;">root</span>, <span style="color:#6666ff; font-weight:bold;">Project::MANUSCRIPT_TEMP_DIRECTORY</span>, current_user.<span style="color:#9900CC;">id</span>.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">FileUtils</span>.<span style="color:#9900CC;">mkdir_p</span> save_location<br />
&nbsp; &nbsp; &nbsp; doctext = manu.<span style="color:#9900CC;">read</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># this next line is necessary since we're using Ruby 1.9 and it's encoding stuff is picky</span><br />
&nbsp; &nbsp; &nbsp; doctext.<span style="color:#9900CC;">force_encoding</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;BINARY&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>save_location, filename<span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#996600;">&quot;w:BINARY&quot;</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:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span>doctext<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@project</span>.<span style="color:#9900CC;">process_manuscript_upload</span><span style="color:#006600; font-weight:bold;">&#40;</span>filename<span style="color:#006600; font-weight:bold;">&#41;</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>Okay, so that last line takes us to the next awesome.  We&#8217;ve got a project.  It has a manuscript.  We&#8217;ve shunted it off and written to the filesystem, then deleted the param so it doesn&#8217;t get attached via Carrierwave (yet).  Now we call process_manuscript_upload for that project against that file.  (NOTE: obviously we call this same shunt method in the update action on the controller too)</p>
<p>CLAM AV</p>
<p>Before we can go about willy-nilly virus-scanning things, we ought to have a virus scan solution.  Enter <a href="http://www.clamav.net/lang/en/">ClamAV</a> for Linux.  Suppose you could use any virus scanner you want here, as long as it can be called via command-line and returns reasonable exit codes that differentiate between success (clean) and failure (has virus).</p>
<p>I&#8217;ll leave it up to you to figure out how to install ClamAV on your system. </p>
<p>THE MODEL</p>
<p>So in our Project model, we&#8217;ve added an instance method that gets called after someone has attempted to upload a file through our projects controller.  It does our dirty work using the virus scanner we just installed.</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> process_manuscript_upload<span style="color:#006600; font-weight:bold;">&#40;</span>filename<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; path = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>Rails.<span style="color:#9900CC;">root</span>, <span style="color:#6666ff; font-weight:bold;">Project::MANUSCRIPT_TEMP_DIRECTORY</span>, <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">user</span>.<span style="color:#9900CC;">id</span>.<span style="color:#9900CC;">to_s</span>, filename<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; scan_is_clean = <span style="color:#CC0066; font-weight:bold;">system</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;clamscan #{path}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> scan_is_clean<br />
&nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">manuscript</span> = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">manuscript_upload_pending</span> = <span style="color:#0000FF; font-weight:bold;">false</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">save</span>!<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">else</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">update_attributes</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:manuscript_upload_pending</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">false</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; Rails.<span style="color:#9900CC;">logger</span>.<span style="color:#9900CC;">warn</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">&quot;[VIRUS DETECTED!] Manuscript uploaded by #{self.user.id.to_s} for project #{self.id.to_s} had a virus!&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># notify the user via email</span><br />
&nbsp; &nbsp; &nbsp; UserMailer.<span style="color:#9900CC;">manuscript_had_virus</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:#9900CC;">deliver</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># clean file from filesystem</span><br />
&nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; handle_asynchronously <span style="color:#ff3333; font-weight:bold;">:process_manuscript_upload</span></div></div>
<p>Seriously, this is not really complicated at all.  I&#8217;ll break it down:</p>
<ol>
<li>figure out the path to file we want to scan.  scan it using system() shelling out to the &#8216;clamscan&#8217; executable and giving it the tmp path of our file.</li>
<li>if it&#8217;s clean, assign it to manuscript by just opening up the file (carrierwave takes over here &#8212; in my case, I have it write the file to cloud storage, but you could write it locally, or to the database, or whatever), change the Project object so it doesn&#8217;t think it has a pending manuscript anymore, and save</li>
<li>if it&#8217;s got a virus, similarly update the pending attribute, but instead of attaching, we log a big warning, send the user a nasty email, and delete the filthy thing from our filesystem.</li>
</ol>
<p>Easy, right?  And if you don&#8217;t know what that very last line is all about, it&#8217;s DelayedJob.  I like the <a href="https://github.com/collectiveidea/delayed_job">fork from collectiveidea</a>.  Really, you want to background this somehow.  Generally ClamAV is fast as hell, but you don&#8217;t want that process blocking the saving of the user&#8217;s Project.  And that&#8217;s what the &#8216;pending&#8217; attribute is all about.  On my Project new form, I only show the manuscript upload file field if pending is false.  If it&#8217;s true, I instead show a message with a little spinner saying &#8220;Your manuscript is being scanned for viruses&#8221; or something like that.</p>
<p>So hopefully that wasn&#8217;t too tough to follow.  I was delighted at how straightforward it ended up being.  And I&#8217;m sure there&#8217;s some variations on the theme you could use, or wrap all this up in a nice include that just gets stuck on the model (i.e. include VirusScanner or something).  But this is my quick-and-dirty implementation.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://mepatterson.net/2010/12/mongoid-carrierwave-virus-scanning/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cheating on Haml with Slim</title>
		<link>http://mepatterson.net/2010/11/cheating-on-haml-with-slim/</link>
		<comments>http://mepatterson.net/2010/11/cheating-on-haml-with-slim/#comments</comments>
		<pubDate>Tue, 30 Nov 2010 04:16:27 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=158</guid>
		<description><![CDATA[I feel bad. I really didn&#8217;t mean for you to find out this way, Haml. I mean, Slim is really a lot like you. Really. It&#8217;s just&#8230; slimmer. And it does all the same stuff, plus some stuff you would never do for me. It fulfills me. It makes me feel like all is right [...]]]></description>
			<content:encoded><![CDATA[<p>I feel bad.  I really didn&#8217;t mean for you to find out this way, <a href="http://haml-lang.com/">Haml</a>.  I mean, <a href="http://slim-lang.com/">Slim</a> is really a lot like you.  Really.  It&#8217;s just&#8230; slimmer.  And it does all the same stuff, plus some stuff you would never do for me.  It fulfills me.  It makes me feel like all is right with the world.  </p>
<p>I still love you Haml, but you&#8217;ve grown a bit slow.  I like <a href="http://slim-lang.com/">Slim</a>&#8216;s <a href="https://gist.github.com/626215">sexier benchmarks</a>.  And it turns me on not to need to type % anymore.  I mean, look at this:</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">&nbsp; h4 class=klass title=title</div></div>
<p>Anyway, I know and love you, Haml.  I won&#8217;t stop using you for all sorts of stuff.  And I can tell you&#8217;ve had a lot of influence on <a href="http://slim-lang.com/">Slim</a>.  But Slim&#8217;s the templating language for me.  At least for right now.</p>
<p>It&#8217;s not you, it&#8217;s me&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://mepatterson.net/2010/11/cheating-on-haml-with-slim/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HOW TO: get fuzzy and plural matches from Sunspot / Solr</title>
		<link>http://mepatterson.net/2010/10/how-to-get-fuzzy-and-plural-matches-from-sunspot-solr/</link>
		<comments>http://mepatterson.net/2010/10/how-to-get-fuzzy-and-plural-matches-from-sunspot-solr/#comments</comments>
		<pubDate>Tue, 05 Oct 2010 05:14:23 +0000</pubDate>
		<dc:creator>M. E. Patterson</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[solr]]></category>
		<category><![CDATA[sunspot]]></category>

		<guid isPermaLink="false">http://blog.digimonkey.com/?p=141</guid>
		<description><![CDATA[Looked all over the place for a simple way to get Sunspot to give me back some basic &#8216;fuzzy&#8217; search results, including ye olde &#8220;things that sound kinda like what I typed, even if I misspelled it&#8221; and &#8220;plural versions of the keywords I typed in.&#8221;  It&#8217;s not that this is a super-hard problem that [...]]]></description>
			<content:encoded><![CDATA[<p>Looked all over the place for a simple way to get <a href="http://github.com/outoftime/sunspot">Sunspot</a> to give me back some basic &#8216;fuzzy&#8217; search results, including ye olde &#8220;things that sound kinda like what I typed, even if I misspelled it&#8221; and &#8220;plural versions of the keywords I typed in.&#8221;  It&#8217;s not that this is a super-hard problem that nobody&#8217;s solved.  It&#8217;s more that doing it really, really well involves some knowledge of how Solr works and monkeying with its configuration to get it to give up the goods the way you want for your use of the thing.</p>
<p>But that&#8217;s okay, <a title="go see Winnebago Man!" href="http://winnebagoman.com/index.php">I&#8217;m going to do you a kindness, Tony</a>, and give you the config setup I used that&#8217;s giving me a good set of results per the above requirements:</p>
<p>Make sure this is what your &lt;analyzer&gt; section looks like in the <strong>/solr/conf/schema.xml</strong> file:</p>
<div class="codecolorer-container xml blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;analyzer<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tokenizer</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.StandardTokenizerFactory&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.StandardFilterFactory&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.LowerCaseFilterFactory&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.PorterStemFilterFactory&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.PhoneticFilterFactory&quot;</span> <span style="color: #000066;">encoder</span>=<span style="color: #ff0000;">&quot;DoubleMetaphone&quot;</span> <span style="color: #000066;">inject</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/analyzer<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>Now, let the commenting commence!  I&#8217;m sure some folks out there would be happy to explain why the above is non-performant at large scales or that there&#8217;s a much better way to achieve my above requirements with some other method.  I&#8217;d love to hear it!  Lay it on me!</p>
<p>But for now, this is totally satisfying my requirements, and I ain&#8217;t gonna change it until I need to.  And I hope the tip helps someone else get on the right path faster than I did.</p>
]]></content:encoded>
			<wfw:commentRss>http://mepatterson.net/2010/10/how-to-get-fuzzy-and-plural-matches-from-sunspot-solr/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Nested forms, hashes, checkboxes and MongoMapper</title>
		<link>http://mepatterson.net/2010/02/nested-forms-hashes-checkboxes-and-mongomapper/</link>
		<comments>http://mepatterson.net/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[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 [...]]]></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><span style="color:#CC0066; font-weight:bold;">sub</span><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://mepatterson.net/2010/02/nested-forms-hashes-checkboxes-and-mongomapper/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Starting a new Rails app?  Here&#8217;s my skeleton&#8230;</title>
		<link>http://mepatterson.net/2010/02/starting-a-new-rails-app-heres-my-skeleton/</link>
		<comments>http://mepatterson.net/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[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; Take it for what it is: a point of discussion. Of course, the skeleton of any Rails app will vary from project to project, [...]]]></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&#8242;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://mepatterson.net/2010/02/starting-a-new-rails-app-heres-my-skeleton/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	<!-- google_ad_section_end --></channel>
</rss>

