<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Starr Horne - Seattle Rails Developer</title>
 <link href="http://starrhorne.com/atom.xml" rel="self"/>
 <link href="http://starrhorne.com"/>
 <updated>2012-02-21T10:37:56-08:00</updated>
 <id>http://starrhorne.com</id>
 <author>
   <name>Starr Horne</name>
   <email>starr@chromahq.com</email>
 </author>

 
 <entry>
   <title>Frontend Code Doesn't Have to Suck: 5 Tips for Rails Developers</title>
   <link href="http://starrhorne.com/2012/02/16/building-front-ends-that-dont-suck-five-tips-for-rails-developers.html"/>
   <updated>2012-02-16T16:32:17-08:00</updated>
   <id>http://starrhorne.com/2012/02/16/building-front-ends-that-dont-suck-five-tips-for-rails-developers</id>
   <content type="html">&lt;p&gt;Most front end code sucks. You know the situation. You start out with the best intentions every time, but every time you wind up with something &quot;less than maintainable.&quot;&lt;/p&gt;

&lt;p&gt;I'm a rails developer and a lot of my work has to do with building out the UI. Over the past few years I've developed a number of best practices that have really helped me to build solid, maintainable front ends for fairly complicated web apps.&lt;/p&gt;

&lt;p&gt;I believe that most rails developers could improve the quality of their front and builds by adopting a few of these suggestions.&lt;/p&gt;

&lt;!--more--&gt;


&lt;h2&gt;Namespace the Hell Out of Your CSS&lt;/h2&gt;

&lt;p&gt;(Then namespace it some more)&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The worst part about CSS is that style conflicts are guaranteed to happen.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;When a project is still young you may think that all H1s are going to look a certain way (just like you thought you were always going to wear those acid wash jeans).&lt;/p&gt;

&lt;p&gt;But then you need an H1 with an underline, and then one in a different color. Soon, you first step when you style any H1 will be to undo half of the the original, global H1 style. It ain’t pretty.&lt;/p&gt;

&lt;p&gt;Your salvation lies in using a CSS reset, then namespacing the hell out of everything.&lt;/p&gt;

&lt;p&gt;Personally, I like a two-pronged approach, where I break a site up into “components” and “pages”. Component styles are namespaced to the component container. Page styles are namespaced to the body class.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;css&quot;&gt;&lt;span class=&quot;c&quot;&gt;/* Styles for the sidebar component */&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.component.sidebar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;300px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;/* Page specific styles */&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.checkout&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sidebar&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Global styles like “.error” are forbidden, with consequences of biblical proportion. (This is why I am morally opposed to things like the twitter bootstrap).&lt;/p&gt;

&lt;p&gt;If you follow this approach diligently, you can drop any CSS file into any page on your site with ZERO style conflicts.&lt;/p&gt;

&lt;h2&gt;Create a naming convention for files and classes&lt;/h2&gt;

&lt;p&gt;Most people just stick their CSS in a single file. At first things may be organized. But after 6 months, more often than not you'll have an ungodly mess of unmaintainable css.&lt;/p&gt;

&lt;p&gt;Naming conventions solve this problem.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;You should always know exactly where the style for an element belongs.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;A new developer on your team should be able to add a component to the page, and know exactly where to put the stylesheet. Then you should be able to come along later and know exactly where to find it.&lt;/p&gt;

&lt;p&gt;So in my projects, if you add a new component named “sidebar”, you will name the class “component.sidebar”, and the styles will go in /stylesheets/components/_sidebar.scss .&lt;/p&gt;

&lt;p&gt;Here are some examples:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;app/assets/stylesheets/components/_component_name.scss
app/assets/javascripts/components/component_name.js.coffee
app/assets/images/components/component_name/lolcat.jpg
app/views/components/_component_name.html.haml
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This system works quite well. It provides you with mechanism for defining general, reusable UI elements as well as for customizing them on a per-page basis.&lt;/p&gt;

&lt;h2&gt;Create a style guide&lt;/h2&gt;

&lt;p&gt;If you have the luxury of working with a really good designer, you might find yourself given a style guide containg specs for all of the color, text styles, buttons, gradients and other visual elements used in a project. Buy this person a sandwich. They've just saved you a ton of time.&lt;/p&gt;

&lt;p&gt;Even if your designer is to lazy to give you one of these, I suggest that you create one for yourself. You can do it based on mockups, or on the fly by continually refactoring your css.&lt;/p&gt;

&lt;p&gt;You can use the styleguide to build a set of sass mixins which you can use throughout the project. This is how you can have DRY stylesheets without defining global classes. If you haven't done things this way, it's awesome. It saves so much time.&lt;/p&gt;

&lt;h2&gt;Make your JavaScript independent of Dom structure&lt;/h2&gt;

&lt;p&gt;Once you've built enough projects you find yourself running into the same bugs over and over again. For example, I had one project where every few months the JS would just stop working, even though it hadn’t been touched.&lt;/p&gt;

&lt;p&gt;Inevitably, the problem turned out to be that someone had tweaked the HTML, caused the JS dependent on some DOM structure to explode.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Your project’s HTML will be changed all the time.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Your project’s HTML will be changed all the time. It is a fact of life. Every time you write JS that depends on a DOM structure, you’re linking the stability of your code to something that's inherently unstable.&lt;/p&gt;

&lt;p&gt;An easy way around this is to use HTML 5 data attributes.  For example, if I have a link that causes a box to slide open, I might set &lt;code&gt;data-expand=”#the-thing-to-expand”&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;Here's the html:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-toggle-trigger=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;token&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Toggle that thing!&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-toggle=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;token&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And coffeescript:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;[data-toggle-trigger]&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;click&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(e) -&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;[data-toggle=#{ $(this).attr(&amp;quot;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toggle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;) }]&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toggle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Modularize your JavaScript&lt;/h2&gt;

&lt;p&gt;With Rails 3.1 and the asset pipeline, every piece of JS you add runs on every page of your site. So it’s time to namespace the hell out of your JS.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;With Rails 3.1 and the asset pipeline, every piece of JS runs on every page of your site.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;One neat approach is to create JavaScript classes which only operate on one particular component. If the component is present, they go to work. If not, they don’t do anything. These JS components only operate on children of the component container, and they don’t know anything about any other components on the page. But they can communicate via custom DOM events.&lt;/p&gt;

&lt;p&gt;This method is simple, but can be really powerful. For example, in my work at OfficeSpace.com, we have a search form which update a Google map, a data display, and several other elements. All of these are separate components which communicate via custom DOM events.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;coffeescript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Simplified search form. Somewhat Nonsensical.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SearchForm&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(@el) -&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;form&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;submit&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;location:search&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;@searchParams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;searchParams: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Just an example&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Attach the component to dom elements&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;.component.search-form&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attachComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SearchForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I hope these few tips will help you build awesome, maintainable UIs for your rails applications. They’ve definitely helped me.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fuzzy Text Search in Postgresql</title>
   <link href="http://starrhorne.com/2012/02/15/fuzzy-text-search-in-postgresql.html"/>
   <updated>2012-02-15T15:31:53-08:00</updated>
   <id>http://starrhorne.com/2012/02/15/fuzzy-text-search-in-postgresql</id>
   <content type="html">&lt;p&gt;On my latest project, one of our guiding principles was to keep then
number of moving parts to a minimum. (That sphinx/solr server your running is
just one more server that can go down)&lt;/p&gt;

&lt;p&gt;Fortunately, postgres provides some nice fuzzy text search features out
of the box. And they're super easy to use.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;To enable the trigram and fuzzy string match extensions, just do this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EXTENSION&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pg_trgm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now you can play around. Searching for &quot;wiliam&quot; will return people named &quot;william&quot;.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;people&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;wiliam&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;similarity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;wiliam&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DESC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;It's important to use the % operator as the condition for the select,
because it uses available indices. (The similarity function doesn't.)
BTW, similarity is a float between 0 and 1, where 1 means &quot;identical&quot;.&lt;/p&gt;

&lt;p&gt;Once you're ready to create an index, just do this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INDEX&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;people_name_trigram_index&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;people&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;USING&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gist&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gist_trgm_ops&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Easy peasy.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;&lt;span class=&quot;k&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;similarity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;bob ross&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;ross bob&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;One thing to watch out for is that the % operator and the similarity
function don't take position into account. For example, in the above
query they show &quot;bob ross&quot; and &quot;ross bob&quot; as being identical.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using Sunspot / Solr to Dramatically Simplify Tagging &amp; Other Stuff in Rails</title>
   <link href="http://starrhorne.com/2012/01/18/using-sunspot-slash-solr-to-dramatically-simplify-tagging-and-other-stuff-in-rails.html"/>
   <updated>2012-01-18T18:20:00-08:00</updated>
   <id>http://starrhorne.com/2012/01/18/using-sunspot-slash-solr-to-dramatically-simplify-tagging-and-other-stuff-in-rails</id>
   <content type="html">&lt;p&gt;Ok...If you really love SQL, this is not the article for you. I'm going to share
a little trick I've learned that will let you do really complex queries without
writing a lick of SQL.&lt;/p&gt;

&lt;!--more--&gt;


&lt;h2&gt;Here's the setup&lt;/h2&gt;

&lt;p&gt;I've been working on a niche job site for a client. It's pretty straightforward,
but it involves some monster queries.&lt;/p&gt;

&lt;p&gt;A typical requirement might be to query all JobCandidates who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have any location, job_type or specialization matching those of any job belonging to a specific employer.

&lt;ul&gt;
&lt;li&gt;JobSeekers and Jobs both have multiple, arbitry values for location, job_type, etc...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Have not replied to any of the employer's previous job postings&lt;/li&gt;
&lt;li&gt;Have been active in the last month&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;... and we need to to fulltext search on top of this.&lt;/p&gt;

&lt;h2&gt;That sounds like a lot of work&lt;/h2&gt;

&lt;p&gt;Why yes, it does.&lt;/p&gt;

&lt;p&gt;Sure, you can implement all of that using AR/Mysql. But it sounds like a heck of a lot
of work. And not very fun work.&lt;/p&gt;

&lt;h2&gt;The Solution&lt;/h2&gt;

&lt;p&gt;On a lark, I decided to see if this could be implemented any more easily using Solr,
and the excellent Sunspot gem.&lt;/p&gt;

&lt;p&gt;The basic trick is this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use AR's serialization to store an array of tags in the model&lt;/li&gt;
&lt;li&gt;Tell Solr to index each tag.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;An Example Model&lt;/h2&gt;

&lt;script src=&quot;https://gist.github.com/1637340.js&quot;&gt; &lt;/script&gt;


&lt;h2&gt;How to search&lt;/h2&gt;

&lt;script src=&quot;https://gist.github.com/1637342.js&quot;&gt; &lt;/script&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;This will return all jobs where job.specializations includes one of
'rails', 'python' or 'perl'.&lt;/p&gt;

&lt;h2&gt;Bonus!&lt;/h2&gt;

&lt;p&gt;You don't have to do anything different in your controllers/views
to take advantage of this approach.&lt;/p&gt;

&lt;p&gt;Rails' views and controllers are set up to handle arrays like this
just fine. In the example below, when the user submits the form,
the job's specializations are set, and will be indexed by Solr on
save.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1637346.js&quot;&gt; &lt;/script&gt;


&lt;h2&gt;Wash, Rinse and Repeat&lt;/h2&gt;

&lt;p&gt;If you can add one solr-indexed tag attribute to your model, you can
add two.&lt;/p&gt;

&lt;p&gt;Also, since solr can index integers, there's no reason you can't define
associations between models in terms of arrays of integers.&lt;/p&gt;

&lt;p&gt;Here's a bit of production code, slightly cleaned up:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1637348.js&quot;&gt; &lt;/script&gt;


&lt;h2&gt;Caveats&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I'm pretty sure this won't scale well at all, since it requires you to
update the solr index whenever a new record is created or updated.
But this particular project is not going to be very high-traffic, so
it's no big deal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Solr only promises 'eventual consistency', which could be an issure for
some apps, but isn't here.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>Track Pageviews Using MongoDB</title>
   <link href="http://starrhorne.com/2012/01/18/track-pageviews.html"/>
   <updated>2012-01-18T18:20:00-08:00</updated>
   <id>http://starrhorne.com/2012/01/18/track-pageviews</id>
   <content type="html">&lt;p&gt;Now, mongo isn't the solution to every problem. But for some things, like action
tracking, it is close to perfect.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;Mongodb is pretty sweet, and mongo mapper makes it really easy to integrate with
your rails app.&lt;/p&gt;

&lt;p&gt;For example, the following track method will create a Metric record with a
certain action if it doesn't exist. Then it will push the current time to the
timestamps array.&lt;/p&gt;

&lt;p&gt;https://gist.github.com/1637337&lt;/p&gt;

&lt;p&gt;The only caveat with this approach is that mongo documents have a max size of 5 megabytes.
So if you were tracking pageviews on a site that received 1000s of hits a day, you'd
exceed that limit pretty quickly.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to extract font names from TTF files using Python and our old friend 'the command line'</title>
   <link href="http://starrhorne.com/2012/01/18/how-to-extract-font-names-from-ttf-files-using-python-and-our-old-friend-the-command-line.html"/>
   <updated>2012-01-18T18:19:00-08:00</updated>
   <id>http://starrhorne.com/2012/01/18/how-to-extract-font-names-from-ttf-files-using-python-and-our-old-friend-the-command-line</id>
   <content type="html">&lt;p&gt;So you're given an archive containing 10,000,000 .ttf files, most
of which are named things like &quot;bs019dfk.ttf&quot;. How do you extract human
readable names from these things?&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;If you're like me you think, &quot;No problem! There has to be a command line
utility for that!&quot;&lt;/p&gt;

&lt;p&gt;...then about an hour later you think, &quot;I hope to god there's a command line
utility for this&quot;.&lt;/p&gt;

&lt;p&gt;...then you open a .ttf file in a text editor just in case the name will
somehow magically be there.&lt;/p&gt;

&lt;p&gt;...then you start drinking.&lt;/p&gt;

&lt;p&gt;Well, good news for your liver. While I couldn't find a stock utility to
extract the name from the .ttf file, I was able to find a little code to do
so.&lt;/p&gt;

&lt;p&gt;It's in python, and you'll need the FontTools library installed. And you should
know that this code is blatently copied from the &lt;a href=&quot;http://pypi.python.org/pypi/TTFQuery/1.0.2&quot;&gt;TTFQuery project&lt;/a&gt;.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1637310.js&quot;&gt; &lt;/script&gt;


&lt;p&gt;To use it, just do this:&lt;/p&gt;

&lt;p&gt; ttf_name somefont.ttf&lt;/p&gt;

&lt;p&gt;Or to get all of the font names in a directory tree:&lt;/p&gt;

&lt;p&gt;$ find . -iname &quot;*.ttf&quot; -exec ttf_name {} \;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Customize the Google Voice Call Widget With Rails &amp; jQuery</title>
   <link href="http://starrhorne.com/2012/01/18/customize-the-google-voice-call-widget-with-rails-and-jquery.html"/>
   <updated>2012-01-18T18:19:00-08:00</updated>
   <id>http://starrhorne.com/2012/01/18/customize-the-google-voice-call-widget-with-rails-and-jquery</id>
   <content type="html">&lt;p&gt;So I have a client who needed a google voice widget embedded in their site.&lt;br/&gt;
If you're not familiar with it, it's a little widget that your site's visitors
can use to call you.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;It's really simple to set up...unless you want to customize the widget's graphics.
But there is a way. Here's how you can do it:&lt;/p&gt;

&lt;h1&gt;A simple form post&lt;/h1&gt;

&lt;p&gt;The Google Voice widget does a simple form post. You can see it &lt;a href=&quot;http://www.stephenjc.com/2009/05/google-voice-call-widget-post-commands.html&quot;&gt;Here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When there are no errors, google returns &quot;ok=true&quot;. When there are problems, it returns &quot;ok=false&quot;.&lt;/p&gt;

&lt;p&gt;Easy&lt;/p&gt;

&lt;h1&gt;A Proxy&lt;/h1&gt;

&lt;p&gt;The only kink here is that we can't AJAX post to a 3rd party domain like
google. So we need to implement a little proxy. You can do this by creating a
controller named &quot;phone_calls&quot;.&lt;/p&gt;

&lt;p&gt;It's pretty simple. It just takes params[:phone_call] and does a https post to
the google server.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1637301.js&quot;&gt; &lt;/script&gt;


&lt;h1&gt;The HTML&lt;/h1&gt;

&lt;p&gt;Now we just need to make a little form and add some javascript to submit it.
You'll need to get your api key from the google voice widget's embed code.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1637295.js&quot;&gt; &lt;/script&gt;


&lt;p&gt;... and here's the javascript&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1637297.js&quot;&gt; &lt;/script&gt;


&lt;p&gt;You can make it a little fancier by showing &quot;success&quot; and &quot;failure&quot;.
That's left as an exercise for the reader.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Making a million little color swatches with imagemagick and rake</title>
   <link href="http://starrhorne.com/2012/01/18/making-a-million-little-color-swatches-with-imagemagick-and-rake.html"/>
   <updated>2012-01-18T18:18:00-08:00</updated>
   <id>http://starrhorne.com/2012/01/18/making-a-million-little-color-swatches-with-imagemagick-and-rake</id>
   <content type="html">&lt;p&gt;Yesterday I was working on a project, and found myself needing to
create a bunch of color swatches. CSS wasn't an option. No. They had to
be little 16x16 images.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;In such situations, I often resort to a more-or-less socratic dialog:&lt;/p&gt;

&lt;p&gt;&quot;Is it not so that you are building this for a client&quot;&lt;/p&gt;

&lt;p&gt;&quot;Yes.&quot;&lt;/p&gt;

&lt;p&gt;&quot;And do clients not inevitably change their minds&quot;&lt;/p&gt;

&lt;p&gt;&quot;Very true, they usually do&quot;&lt;/p&gt;

&lt;p&gt;&quot;Then would it not make sense to generate these swatches programmatically?&quot;&lt;/p&gt;

&lt;h1&gt;The Rake Task&lt;/h1&gt;

&lt;p&gt;Heartily agreeing with myself, I devised the following rake task for creating
color swatches, based on input from a YAML file. BTW, You'll need to have imagemagick
installed.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1637322.js&quot;&gt; &lt;/script&gt;


&lt;h1&gt;The YAML File&lt;/h1&gt;

&lt;p&gt;Now create a &quot;swatches.yml&quot; file like so:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1637325.js&quot;&gt; &lt;/script&gt;


&lt;h1&gt;W00t!&lt;/h1&gt;

&lt;p&gt;Now you can just type in &quot;rake swatches&quot; and feel the magick.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1637328.js&quot;&gt; &lt;/script&gt;



</content>
 </entry>
 
 <entry>
   <title>How to use rjs templates with uploadify: a rails multiple file upload extravaganza!</title>
   <link href="http://starrhorne.com/2012/01/18/how-to-use-rjs-templates-with-uploadify-a-rails-multiple-file-upload-extravaganza.html"/>
   <updated>2012-01-18T18:18:00-08:00</updated>
   <id>http://starrhorne.com/2012/01/18/how-to-use-rjs-templates-with-uploadify-a-rails-multiple-file-upload-extravaganza</id>
   <content type="html">&lt;p&gt;John Nunemaker posted a great &lt;a href=&quot;http://railstips.org/2009/7/21/uploadify-and-rails23&quot;&gt;article&lt;/a&gt;
on using uploadify with rails.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.uploadify.com/&quot;&gt;Uploadify&lt;/a&gt; is a sweet jquery plugin that lets you do multiple file upload with progress indicators and everything,
using the magic of flash.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;But you know that magic always comes with a price. Specifically: flash sucks. It sucks in part because it doesn't
let you send cookies back with your request. John's post showed you a way around that.&lt;/p&gt;

&lt;p&gt;But it also sucks because it doesn't send HTTP request headers either. Which means no RJS, kiddies. Unless you
use a workaround like so.&lt;/p&gt;

&lt;p&gt;In your middleware:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1637315.js&quot;&gt; &lt;/script&gt;


&lt;p&gt;And in your javascript, you'll need to add a bit of code to eval the response:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1637317.js&quot;&gt; &lt;/script&gt;


&lt;p&gt;Now, bingo! You can just use responds_to like normal.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Warping Vector Text With Ruby &amp; Cairo</title>
   <link href="http://starrhorne.com/2012/01/18/warping-vector-text-with-ruby-and-cairo.html"/>
   <updated>2012-01-18T18:16:00-08:00</updated>
   <id>http://starrhorne.com/2012/01/18/warping-vector-text-with-ruby-and-cairo</id>
   <content type="html">&lt;p&gt;I recently needed to create arched text in an application that uses Cairo. Unfortunately, Cairo doesn't support warping text out of the box.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;Luckily, the pycairo guys were cool enough to include an example of warped text in their distribution.&lt;/p&gt;

&lt;p&gt;Here it is, ported to ruby:&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/466898.js?file=gistfile1.rb&quot;&gt;&lt;/script&gt;



</content>
 </entry>
 
 
</feed>

