<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>The Remarkable Labs Blog</title>
    <link>http://blog.remarkablelabs.com</link>
    <description>The Remarkable Labs Blog</description>
    <lastBuildDate>2013-06-19 09:14:40 +0000</lastBuildDate>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/remarkablelabs" /><feedburner:info uri="remarkablelabs" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
      <title>The Rails 4 Way (beta) now available</title>
      <link>http://feedproxy.google.com/~r/remarkablelabs/~3/7-e0ZW5yONk/the-rails-4-way-beta-now-available</link>
      <pubDate>Tue, 07 May 2013 10:51:09 -0400</pubDate>
      <author>Kevin Faustino</author>
      <guid isPermaLink="false">http://blog.remarkablelabs.com/2013/05/the-rails-4-way-beta-now-available</guid>
      <description>&lt;p&gt;I&amp;#39;m excited to announce that I am a co-author of &lt;a href="https://leanpub.com/tr4w"&gt;The Rails 4 Way&lt;/a&gt;. I&amp;#39;m joined with Obie Fernandez himself, and fellow co-authors Vitaly Kushner and Ari Lerner.&lt;/p&gt;

&lt;p&gt;The original &amp;quot;The Rails Way&amp;quot; holds a special place in my heart as it was my ultimate reference when I started developing with Ruby on Rails. With each new edition of the book, it has become better and better, providing no fluff content and containing great advice from various Rails developers from around the world. What sets The Rails Way apart from other Rails books in the market, is that it covers topics and technologies that practitioners consider to be ideal. This means it covers things such Haml, RSpec, and FactoryGirl over Erb, TestUnit, and fixtures respectively. While this may not be everyone&amp;#39;s preferred stack, the book still has something for everyone. The coverage of Active Record alone could be its own book and is a must read for any Rails developer.&lt;/p&gt;

&lt;p&gt;Thanks to the cooperation of Addison-Wesley, you can &lt;a href="https://leanpub.com/tr4w"&gt;purchase&lt;/a&gt; a DRM-free copy of The Rails 4 Way today on the great Leanpub service. For those who like physical books over digital copies, the published Addison-Wesley edition is expected to be released sometime late in the year.&lt;/p&gt;

&lt;p&gt;Since the book is still in beta, its not 100% complete yet. Expect updates every couple of weeks, updating the second half of the book to Rails 4 and including many tips and gems that are relevant to Rails development today. Some things to look forward to is coverage of Sidekiq, Sorcery, Draper, Active Model Serializers, and more. We have also taken into consideration feedback from previous editions, and we are going to include a Haml, Sass, and CoffeeScript reference to make The Rails 4 Way an even better resource. You submit any suggestions or errors to our &lt;a href="https://awprorubyseries.lighthouseapp.com/projects/108333-the-rails-4-way/overview"&gt;lighthouse issue tracking page&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/remarkablelabs/~4/7-e0ZW5yONk" height="1" width="1"/&gt;</description>
    <feedburner:origLink>http://blog.remarkablelabs.com/2013/05/the-rails-4-way-beta-now-available</feedburner:origLink></item>
    <item>
      <title>Using Sidekiq to send emails asynchronously</title>
      <link>http://feedproxy.google.com/~r/remarkablelabs/~3/bc1OIDHVaJc/using-sidekiq-to-send-emails-asynchronously</link>
      <pubDate>Tue, 22 Jan 2013 11:36:34 -0500</pubDate>
      <author>Kevin Faustino</author>
      <guid isPermaLink="false">http://blog.remarkablelabs.com/2013/01/using-sidekiq-to-send-emails-asynchronously</guid>
      <description>&lt;p&gt;If your web application needs to send out emails, the best practice is to send them asynchronously in a background task. This usage is so common that Rails 4 added an &lt;a href="http://blog.remarkablelabs.com/2012/12/asynchronous-action-mailer-rails-4-countdown-to-2013"&gt;asynchronous Action Mailer&lt;/a&gt;, but the feature will no longer be making the original 4.0 release. In spite of that, the asynchronous Action Mailer would have been a temporary solution for developers until they were ready to run their own dedicated queue.&lt;/p&gt;

&lt;p&gt;A lot of Ruby developers are familiar with queues, such as DelayedJob and Resque. While these queues have been predominant the last couple of years, my tool of choice is &lt;a href="http://mperham.github.com/sidekiq/"&gt;Sidekiq&lt;/a&gt;, a Redis backed queue by Mike Perham. Sidekiq advertises that a single process can do the work of 20 Resque or DelayedJob processes. Another benefit of Sidekiq is the inclusion of extensions, which allows for testing and delayed mailers. &lt;/p&gt;

&lt;h2&gt;Getting Started&lt;/h2&gt;

&lt;p&gt;Add Sidekiq to your Rails project by including it to your &lt;code&gt;Gemfile&lt;/code&gt; and run the &lt;code&gt;bundle&lt;/code&gt; command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# Gemfile&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sidekiq&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To run Sidekiq, run the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;sidekiq
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Sending Delayed Emails&lt;/h2&gt;

&lt;p&gt;Sidekiq supports sending emails asynchronously with Action Mailer out of the box. It does this by including three methods to the &lt;code&gt;ActionMailer&lt;/code&gt; module.&lt;/p&gt;

&lt;h3&gt;&lt;code&gt;.delay&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The method that you will likely use the most is &lt;code&gt;.delay&lt;/code&gt;. Calling &lt;code&gt;.delay&lt;/code&gt; from an Action Mailer will result in the email being added to the &lt;code&gt;DelayedMailer&lt;/code&gt; queue for processing.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="no"&gt;SubscriptionMailer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note the absence of &lt;code&gt;.deliver&lt;/code&gt; in the above code snippet, as that execution is performed by the &lt;code&gt;DelayedMailer&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;&lt;code&gt;.delay_for(interval)&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Sidekiq also supports the delayed delivery of emails by providing a specified interval to the &lt;code&gt;.delay_for&lt;/code&gt; method. &lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="no"&gt;UserMailer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delay_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;&lt;code&gt;.delay_until(timestamp)&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The last Action Mailer method added by Sidekiq is &lt;code&gt;.delay_until&lt;/code&gt;. Sidekiq will wait until the provided time to send the email.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="no"&gt;UserMailer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delay_until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;How about Devise emails?&lt;/h2&gt;

&lt;p&gt;Devise has its own mailer for authentication emails. You can enable asynchronous emails for Devise by using the &lt;a href="https://github.com/mhfs/devise-async"&gt;&lt;code&gt;devise-async&lt;/code&gt; gem&lt;/a&gt;. Note that emails queued via &lt;code&gt;devise-async&lt;/code&gt; are added the &lt;em&gt;mailer&lt;/em&gt; queue by default. &lt;/p&gt;

&lt;p&gt;To setup &lt;code&gt;devise-async&lt;/code&gt;, add it to your &lt;code&gt;Gemfile&lt;/code&gt; and run the &lt;code&gt;bundle&lt;/code&gt; command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# Gemfile&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;devise-async&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Add the &lt;code&gt;:async&lt;/code&gt; option to the &lt;code&gt;devise&lt;/code&gt; call in your authentication model:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;devise&lt;/span&gt; &lt;span class="ss"&gt;:database_authenticatable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:async&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:confirmable&lt;/span&gt; &lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, create an initializer to set &lt;code&gt;Devise::Async.backend&lt;/code&gt; to use Sidekiq:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# config/initializers/devise_async.rb&lt;/span&gt;
&lt;span class="no"&gt;Devise&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Async&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:sidekiq&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Testing&lt;/h2&gt;

&lt;p&gt;Sidekiq comes with some great test/spec helpers to make testing against it easy.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;spec/spec_helper.rb&lt;/code&gt;, requiring &lt;code&gt;sidekiq/testing&lt;/code&gt; forces Sidekiq to not push jobs to Redis, but an array named &lt;code&gt;jobs&lt;/code&gt; for testing purposes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# spec/spec_helper.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sidekiq/testing&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To ensure emails are correctly enqueued in Sidekiq, you can test  against the jobs size of the &lt;code&gt;Sidekiq::Extensions::DelayedMailer&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;SubscriptionMailer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Extensions&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;DelayedMailer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mperham.github.com/sidekiq/"&gt;Sidekiq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mperham/sidekiq"&gt;Sidekiq on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://railscasts.com/episodes/366-sidekiq"&gt;Railscast on Sidekiq&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/remarkablelabs/~4/bc1OIDHVaJc" height="1" width="1"/&gt;</description>
    <feedburner:origLink>http://blog.remarkablelabs.com/2013/01/using-sidekiq-to-send-emails-asynchronously</feedburner:origLink></item>
    <item>
      <title>Creating Retina Images with CarrierWave</title>
      <link>http://feedproxy.google.com/~r/remarkablelabs/~3/-btI8CaY-Tg/creating-retina-images-with-carrierwave</link>
      <pubDate>Fri, 18 Jan 2013 11:11:05 -0500</pubDate>
      <author>Kevin Faustino</author>
      <guid isPermaLink="false">http://blog.remarkablelabs.com/2013/01/creating-retina-images-with-carrierwave</guid>
      <description>&lt;p&gt;In yesterday&amp;#39;s post &lt;a href="http://blog.remarkablelabs.com/2013/01/retina-web-design"&gt;Retina Web Design&lt;/a&gt;, we covered multiple techniques to be &amp;quot;retina-ready&amp;quot; for the upcoming wave of double density screens. One of the techniques mentioned was to use &lt;a href="http://retinajs.com/"&gt;retina.js&lt;/a&gt;, a JavaScript library that attempts to serve higher resolution images for visitors of your web application. To ensure even your uploaded image assets will work with retina.js, we can utilize &lt;a href="https://github.com/jnicklas/carrierwave"&gt;CarrierWave&lt;/a&gt; to upload both standard and high resolution image versions.&lt;/p&gt;

&lt;p&gt;One constraint we must conform to is naming our &amp;quot;retina&amp;quot; image versions to use the Apple &lt;a href="http://developer.apple.com/library/ios/#documentation/2DDrawing/Conceptual/DrawingPrintingiOS/SupportingHiResScreensInViews/SupportingHiResScreensInViews.html#//apple_ref/doc/uid/TP40010156-CH15-SW1"&gt;@2x naming style&lt;/a&gt;. CarrierWave allows us to set a specific file name for each version of an uploaded file. To do this, we must override the &lt;code&gt;#full_filename&lt;/code&gt; method defined in the &lt;code&gt;CarrierWave::Uploader::Versions&lt;/code&gt; module. &lt;/p&gt;

&lt;h2&gt;Example&lt;/h2&gt;

&lt;p&gt;The key to using this technique is to not resize the original version of the image smaller than the &amp;quot;retina&amp;quot; version. In the example below, we do not process the original image and instead create a thumb and retina_thumb version. Also note that when creating a &amp;quot;retina&amp;quot; image, the dimensions must be double the size of the standard definition version.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AvatarUploader&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;CarrierWave&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Uploader&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;CarrierWave&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MiniMagick&lt;/span&gt;

  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="ss"&gt;:thumb&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="n"&gt;resize_to_fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="ss"&gt;:retina_thumb&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="ss"&gt;:resize_to_fill&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;full_filename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;for_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;avatar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tap&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;@2x.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;retina_&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Processing a png image to the &lt;code&gt;AvatarUploader&lt;/code&gt; above, would result in three versions uploaded to your asset store:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The original file&lt;/li&gt;
&lt;li&gt;A thumbnail named &lt;code&gt;thumb.png&lt;/code&gt; with dimensions 100x100&lt;/li&gt;
&lt;li&gt;A retina thumbnail named &lt;code&gt;thumb@2x.png&lt;/code&gt; with dimensions 200x200&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;APIs&lt;/h2&gt;

&lt;p&gt;This technique is also useful for APIs designed specifically for iOS applications. If an API endpoint returns images, you can return both standard and high resolution version paths of the image and leave the decision of which version to use to the API consumer.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/remarkablelabs/~4/-btI8CaY-Tg" height="1" width="1"/&gt;</description>
    <feedburner:origLink>http://blog.remarkablelabs.com/2013/01/creating-retina-images-with-carrierwave</feedburner:origLink></item>
    <item>
      <title>Retina Web Design</title>
      <link>http://feedproxy.google.com/~r/remarkablelabs/~3/6uB6T6OzO4Q/retina-web-design</link>
      <pubDate>Thu, 17 Jan 2013 15:26:02 -0500</pubDate>
      <author>Kevin Faustino</author>
      <guid isPermaLink="false">http://blog.remarkablelabs.com/2013/01/retina-web-design</guid>
      <description>&lt;p&gt;Devices with retina displays are changing the way we design web applications. When Apple introduced the iPhone 4, we got a glimpse into how images on our sites look on retina enabled screens. Last year, the retina enabled iPad and Macbook Pro came to market, highlighting the fact that most web sites are not retina-ready.&lt;/p&gt;

&lt;p&gt;One day retina displays will no longer be the exception, but the standard. However until that time, we need to take steps to ensure all the people visiting our web applications are getting the same polished experience.&lt;/p&gt;

&lt;h2&gt;What is retina?&lt;/h2&gt;

&lt;p&gt;Retina is a term used by Apple to describe their double density pixel screens. A device pixel is not the same as the pixels we define within our CSS declarations. A CSS pixel is an abstract unit used by web browsers to draw content. On non-retina displays a CSS pixel maps directly to a device pixel. On retina displays, this is quadrupled as one CSS pixel can equal 4 device pixels.&lt;/p&gt;

&lt;p&gt;Image sizes on the web are also defined in CSS pixels. If a height/width is defined in either markup or CSS, the browsers will either stretch or squeeze the image when rendering the web page.&lt;/p&gt;

&lt;p&gt;To demonstrate a non-retina image on a double density screen, let&amp;#39;s take a look at the how the Remarkable Labs logo renders:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://lab-report.s3.amazonaws.com/images/posts/retina_web_design/non-retina.png" alt="Non-retina logo"&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the image becomes blurry as it is stretched to fit within a defined area of CSS pixels.&lt;/p&gt;

&lt;h2&gt;How to move forward?&lt;/h2&gt;

&lt;p&gt;There are a variety of strategies you can use to optimize your graphics to work with retina enabled devices. Let&amp;#39;s take a look at some of the ones we use here at Remarkable Labs.&lt;/p&gt;

&lt;h3&gt;Use CSS3 and HTML5 over graphics&lt;/h3&gt;

&lt;p&gt;The days of using images for rounded corners, gradients, and text are long behind us. Using CSS3 properties, we are now able to create beautiful web pages natively within the browser with minimal graphics.&lt;/p&gt;

&lt;p&gt;While I am not going to go into detail about CSS3, here are a couple of resources to look into if your interested:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.abookapart.com/products/css3-for-web-designers"&gt;CSS3 for Web Designers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://bourbon.io/"&gt;bourbon.io Sass library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://compass-style.org/"&gt;Compass CSS Authoring Framework&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Icon Fonts&lt;/h3&gt;

&lt;p&gt;I&amp;#39;m a big fan of using icon fonts wherever you can. They allow you to have &amp;quot;graphics&amp;quot; which are rendered as text. This means you can apply any CSS property you can use for text, such as &lt;code&gt;font-size&lt;/code&gt; and &lt;code&gt;color&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I highly recommend using Zurb&amp;#39;s &lt;a href="http://www.zurb.com/playground/foundation-icons"&gt;Foundation Icon Fonts 2&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://lab-report.s3.amazonaws.com/images/posts/retina_web_design/icon_fonts.jpg" alt="Zurb Foundation Icon Fonts"&gt;&lt;/p&gt;

&lt;p&gt;You can even build your own with &lt;a href="http://fontello.com/"&gt;Fontello&lt;/a&gt;, an icon font generator that includes free icon fonts available on the web.&lt;/p&gt;

&lt;h3&gt;Media Query Targeting&lt;/h3&gt;

&lt;p&gt;Using media queries, we are able to target retina devices and minimum resolutions. When targeting with media queries, ensure you include all &lt;code&gt;device-pixel-ratio&lt;/code&gt; browser specific properties. Also, setting &lt;code&gt;min-device-pixel-ratio&lt;/code&gt; to 1.3 and &lt;code&gt;min-resolution&lt;/code&gt; to 1.3dppx allows us to support new Android devices, such as the Google Nexus 7. The &lt;code&gt;background-size&lt;/code&gt; property defines the width and height of image contained within the container.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nc"&gt;.logo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;background&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url(path/to/image.png)&lt;/span&gt; &lt;span class="k"&gt;no-repeat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;moz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pixel&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ratio&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pixel&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ratio&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;webkit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pixel&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ratio&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pixel&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ratio&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="n"&gt;dppx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;background-image&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url(path/to/image@2x.png)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;background&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you are using Sass for authoring your CSS, please use the great mixin shared in the 37Signals post &lt;a href="http://37signals.com/svn/posts/3271-easy-retina-ready-images-using-scss"&gt;Easy retina-ready images using SCSS&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;SVG&lt;/h3&gt;

&lt;p&gt;SVG(Scalable Vector Graphics) support is now available on all major browsers, even Internet Explorer! The benefits of using vector graphics over images are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: Scalable Vector Graphics do not have the limitation of regular images, as they can scale to any size without distortion.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tiny Footprint&lt;/strong&gt;: File sizes tend to be smaller and thus use less bandwidth.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To find out more about SVG, read the excellent article &lt;a href="http://coding.smashingmagazine.com/2012/01/16/resolution-independence-with-svg/"&gt;&amp;quot;Resolution Independence With SVG&amp;quot;&lt;/a&gt; on Smashing Magazine.&lt;/p&gt;

&lt;h3&gt;Using JavaScript with retina.js&lt;/h3&gt;

&lt;p&gt;&lt;img src="http://lab-report.s3.amazonaws.com/images/posts/retina_web_design/retina_js.jpg" alt="retina.js"&gt;&lt;/p&gt;

&lt;p&gt;With the JavaScript library &lt;a href="http://retinajs.com/"&gt;retina.js&lt;/a&gt;, you can integrate retina graphics very easily just by including the library in your web pages. On the loading of a web page, retina.js will determine if the user is using a double density screen. If they are, retina.js will go through each image on the page and check the server to see if a high resolution version is available. The high resolution images are expected to follow the &lt;a href="http://developer.apple.com/library/ios/#documentation/2DDrawing/Conceptual/DrawingPrintingiOS/SupportingHiResScreensInViews/SupportingHiResScreensInViews.html#//apple_ref/doc/uid/TP40010156-CH15-SW1"&gt;Apple naming standard&lt;/a&gt; &lt;code&gt;&amp;lt;ImageName&amp;gt;@2x.&amp;lt;filename_extension&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;While this technique is very easy to implement, the main disadvantage is all retina enabled devices download &lt;strong&gt;both&lt;/strong&gt; high resolution and standard images. In his post &lt;a href="http://mir.aculo.us/2012/09/22/dont-use-javascript-for-retinafying/"&gt;&amp;quot;Don&amp;#39;t Use JavaScript for Retinafying&amp;quot;&lt;/a&gt;, Thomas Fuchs advocates designing &amp;quot;retina-first&amp;quot; over using JavaScript libraries.&lt;/p&gt;

&lt;p&gt;Designing &amp;quot;retina-first&amp;quot; does have disadvantages as well. Retina displays are not common place yet, thus by using higher resolution images only, we are serving larger assets to all our visitors. This can in turn slow down your sites as response payloads become much larger. My advice is look at your site metrics, and determine how many users are using &amp;quot;retina&amp;quot; displays to gauge which technique to pursue.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/remarkablelabs/~4/6uB6T6OzO4Q" height="1" width="1"/&gt;</description>
    <feedburner:origLink>http://blog.remarkablelabs.com/2013/01/retina-web-design</feedburner:origLink></item>
    <item>
      <title>How to decrease coupling in your controllers &amp; views with decent_exposure for better maintainability</title>
      <link>http://feedproxy.google.com/~r/remarkablelabs/~3/fdh13GDKj4Y/how-to-decrease-coupling-in-your-controllers-views-with-decent_exposure-for-better-maintainability</link>
      <pubDate>Fri, 11 Jan 2013 14:26:36 -0500</pubDate>
      <author>Kevin Faustino</author>
      <guid isPermaLink="false">http://blog.remarkablelabs.com/2013/01/how-to-decrease-coupling-in-your-controllers-views-with-decent_exposure-for-better-maintainability</guid>
      <description>&lt;p&gt;If you&amp;#39;re a Rails developer, you&amp;#39;re familiar with with the standard way of sharing data from the controller layer to the view layer. By convention, Rails copies all instance variables defined in the execution of a controller action to the view context. This standard usage will result in strong coupling between your controllers and views, as they are sharing state via instance variables.&lt;/p&gt;

&lt;p&gt;To solve this problem, Stephen Caudill created the &lt;a href="https://github.com/voxdolo/decent_exposure"&gt;&lt;code&gt;decent_exposure&lt;/code&gt;&lt;/a&gt; gem. Decent Exposure works by &amp;quot;exposing&amp;quot; methods over instance variables. This results in the ability to program views to an interface over a controller implementation.&lt;/p&gt;

&lt;h2&gt;Converting a standard controller to use decent_exposure&lt;/h2&gt;

&lt;p&gt;To demonstrate how to use &lt;code&gt;decent_exposure&lt;/code&gt;, let&amp;#39;s convert the follow controller:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ComicsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="vi"&gt;@comics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
    &lt;span class="vi"&gt;@comic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="vi"&gt;@comic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;edit&lt;/span&gt;
    &lt;span class="vi"&gt;@comic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="vi"&gt;@comic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:comic&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@comic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;notice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Comic was successfully created.&amp;#39;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;new&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;
    &lt;span class="vi"&gt;@comic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_attributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:comic&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@comic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;notice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Comic was successfully updated.&amp;#39;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;edit&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt;
    &lt;span class="vi"&gt;@comic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;destroy&lt;/span&gt;

    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;comics_url&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To begin, we need to use the &lt;code&gt;expose&lt;/code&gt; macro style method provided by &lt;code&gt;decent_exposure&lt;/code&gt; to define the methods we want to make available to our controller. The &lt;code&gt;expose&lt;/code&gt; macro will also declare the method as a helper method for your views to access:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ComicsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="ss"&gt;:html&lt;/span&gt;

  &lt;span class="n"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:comics&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:comic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;
    &lt;span class="n"&gt;respond_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;
    &lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;
    &lt;span class="n"&gt;respond_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt;
    &lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;destroy&lt;/span&gt;
    &lt;span class="n"&gt;respond_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At first glance, you will notice the removal of the &lt;code&gt;index&lt;/code&gt;, &lt;code&gt;show&lt;/code&gt;, &lt;code&gt;new&lt;/code&gt;, and &lt;code&gt;edit&lt;/code&gt; controller action definitions. This is a result of using another Rails convention. If a route is defined for the controller action, and a method is empty or not defined, Rails will by default render the standard template for the requested action. For example, if the &lt;code&gt;index&lt;/code&gt; action was requested, Rails would render the view &lt;code&gt;app/views/comics/index.html.erb&lt;/code&gt; by default. To clean up things further, we also take advantage of responders.&lt;/p&gt;

&lt;p&gt;Also gone are the previously defined instance variables. The &lt;code&gt;expose&lt;/code&gt; macro will initialize or query for resources based on some criteria. Here is a breakdown of how &lt;code&gt;decent_exposure&lt;/code&gt; sets  each resource in the above example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The collection of comics used by the &lt;code&gt;index&lt;/code&gt; action will be queried by default using &lt;code&gt;Comic.scoped&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If no &lt;code&gt;:id&lt;/code&gt; parameter is available in the controller &lt;code&gt;params&lt;/code&gt; hash, &lt;code&gt;decent_exposure&lt;/code&gt; returns &lt;code&gt;Comic.new(params[:comic])&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If an &lt;code&gt;:id&lt;/code&gt; parameter is present, &lt;code&gt;decent_exposure&lt;/code&gt; will query for   the resource by executing &lt;code&gt;Comic.find(params[:id]&lt;/code&gt;. If a plural exposed resource  is available, &lt;code&gt;decent_exposure&lt;/code&gt; will scope the singular version to it. Thus, &lt;code&gt;comic&lt;/code&gt; is set to &lt;code&gt;Comic.scoped.find(params[:id])&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, all calls to previously defined instance variables must be changed to their method counterpart. For example, all calls to &lt;code&gt;@comics&lt;/code&gt;, must now send a message to &lt;code&gt;comics&lt;/code&gt; instead.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="x"&gt;&amp;lt;!-- app/views/comics/index.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;&amp;lt;h1&amp;gt;Listing comics&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="x"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;  &amp;lt;tr&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    &amp;lt;th&amp;gt;Title&amp;lt;/th&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    &amp;lt;th&amp;gt;Volume&amp;lt;/th&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;  &amp;lt;/tr&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="n"&gt;comics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;span class="x"&gt;  &amp;lt;tr&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    &amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    &amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    &amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Show&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comic&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    &amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Edit&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;edit_comic_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    &amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Destroy&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:delete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;confirm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Are you sure?&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;  &amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;span class="x"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;

&lt;span class="x"&gt;&amp;lt;br /&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;New Comic&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_comic_path&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Nested Resources&lt;/h2&gt;

&lt;p&gt;Another benefit to using the &lt;code&gt;decent_exposure&lt;/code&gt; gem is its ability to work with nested resources out of the box. As an example, say comics were nested under a publisher, &lt;code&gt;decent_exposure&lt;/code&gt; will be able to instantiates/queries for resources based on Rails conventions:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:publisher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:comics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ancestor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:publisher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:comic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the above code, the exposed &lt;code&gt;publisher&lt;/code&gt; method will be set by &lt;code&gt;Publisher.find(params[:publisher_id])&lt;/code&gt;. Next, a nested relationship is defined via the exposed &lt;code&gt;comics&lt;/code&gt; method. The &lt;code&gt;comic&lt;/code&gt; exposed method will then use the pluaral exposed method to ininitialize/query resources. In the above example, quering for a &lt;code&gt;Comic&lt;/code&gt; resource would call &lt;code&gt;Publisher.find(params[:publisher_id]).comics.find(params[:id])&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Scopes&lt;/h2&gt;

&lt;p&gt;In instances where you would like to use a scope with a exposed method, pass a block to the &lt;code&gt;expose&lt;/code&gt; macro:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:comics&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Non-Conventional&lt;/h2&gt;

&lt;p&gt;Your application will likely contain instances where you do not want to query by an id. In those cases, &lt;code&gt;decent_exposure&lt;/code&gt; provides some options to make your life a little easier.&lt;/p&gt;

&lt;h3&gt;finder_parameter&lt;/h3&gt;

&lt;p&gt;Maybe you don&amp;#39;t query all the time using an &lt;code&gt;:id&lt;/code&gt; parameter. In these cases, you can define what you want &lt;code&gt;decent_exposure&lt;/code&gt; to use via the &lt;code&gt;:finder_parameter&lt;/code&gt; option:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:issue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;finder_parameter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:slug&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;model&lt;/h3&gt;

&lt;p&gt;If the name of your exposed method does not match to an existing model, use the &lt;code&gt;:model&lt;/code&gt; option:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:issue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:comic_issue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;params&lt;/h3&gt;

&lt;p&gt;Sometimes if you are using a custom form, you will pass different parameters to your controller. To handle this situation, use the &lt;code&gt;:params&lt;/code&gt; option:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:comic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:comic_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Playing friendly with Strong Parameters&lt;/h2&gt;

&lt;p&gt;By default, &lt;code&gt;decent_exposure&lt;/code&gt; does not support the &lt;a href="https://github.com/rails/strong_parameters"&gt;Strong Parameters&lt;/a&gt; gem. With strong parameters being the standard for sanitizing your parameters moving forward in Rails 4, it is recommended you use the &lt;code&gt;decent_exposure&lt;/code&gt; strategy available on the &lt;a href="https://github.com/voxdolo/decent_exposure/wiki/Strategies:-Use-with-strong_parameters"&gt;project&amp;#39;s wiki&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To enable support, create a file &lt;code&gt;strong_parameters_strategy.rb&lt;/code&gt; in your &lt;code&gt;lib&lt;/code&gt; directory with the following code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# https://github.com/voxdolo/decent_exposure/wiki/Strategies:-Use-with-strong_parameters&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StrongParametersStrategy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;DecentExposure&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ActiveRecordWithEagerAttributesStrategy&lt;/span&gt;
  &lt;span class="n"&gt;delegate&lt;/span&gt; &lt;span class="ss"&gt;:delete?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:to&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:request&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;attributes&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get?&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;delete?&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;singularize&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;_params&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, create an initializer to ensure the strategy will be available to &lt;code&gt;decent_exposure&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# config/initializers/decent_exposure.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;strong_parameters_strategy&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, in any exposed methods where you want to utilize strong parameters, set &lt;code&gt;StrongParametersStrategy&lt;/code&gt; to the &lt;code&gt;:strategy&lt;/code&gt; option:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:comic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;StrongParametersStrategy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When saving/updating a resource, &lt;code&gt;decent_exposure&lt;/code&gt; will now look for the associated &lt;code&gt;resource_name_params&lt;/code&gt; method within your controller. In the above example, we would define a private controller method named &lt;code&gt;comic_params&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;comic_params&lt;/span&gt;
  &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:comic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:volume&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Install&lt;/h2&gt;

&lt;p&gt;To use &lt;code&gt;decent_exposure&lt;/code&gt; in your Rails project, add it to your &lt;code&gt;Gemfile&lt;/code&gt; and run the &lt;code&gt;bundle&lt;/code&gt; command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;decent_exposure&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/remarkablelabs/~4/fdh13GDKj4Y" height="1" width="1"/&gt;</description>
    <feedburner:origLink>http://blog.remarkablelabs.com/2013/01/how-to-decrease-coupling-in-your-controllers-views-with-decent_exposure-for-better-maintainability</feedburner:origLink></item>
    <item>
      <title>MailCatcher: Making working with email in development mode a pleasure </title>
      <link>http://feedproxy.google.com/~r/remarkablelabs/~3/sQ2f0PyoXuY/mailcatcher-making-working-with-email-in-development-mode-a-pleasure</link>
      <pubDate>Wed, 09 Jan 2013 10:15:28 -0500</pubDate>
      <author>Kevin Faustino</author>
      <guid isPermaLink="false">http://blog.remarkablelabs.com/2013/01/mailcatcher-making-working-with-email-in-development-mode-a-pleasure</guid>
      <description>&lt;p&gt;When developing web applications, working with email has always been a pain. By default in Ruby on Rails, all email messages sent in development via Action Mailer are delivered in test mode. This means if you send an email from your application, the output of that message would display in your development log. While this can show you if the output is correct, it does not indicate if the HTML of the email message is rendered correctly. A way around this would be to connect your development environment to an actual SMTP server. Even though this would allow you to view the email in your mail client of choice, it is a very bad idea, as you could potentially email real people.&lt;/p&gt;

&lt;p&gt;Originally to solve this problem, the ruby gem &lt;a href="https://github.com/ryanb/letter_opener"&gt;&lt;code&gt;letter_opener&lt;/code&gt;&lt;/a&gt; was our tool of choice.  When an email was sent from the web application, &lt;code&gt;letter_opener&lt;/code&gt; would open up the email in a new browser tab. However, in use cases where multiple emails were fired off, multiple browser tabs being opened at once was very obtrusive.&lt;/p&gt;

&lt;h2&gt;Enter MailCatcher&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://mailcatcher.me/"&gt;MailCatcher&lt;/a&gt; is a ruby gem that runs a local SMTP server on your machine. Any email message sent to this SMTP server will be captured and not sent out. Also, all messages will be viewable in a web interface available at http://localhost:1080.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://lab-report.s3.amazonaws.com/images/posts/mailcatcher/mailcatcher.jpg" alt="MailCatcher"&gt;&lt;/p&gt;

&lt;p&gt;MailCatcher utilizes WebSockets to display email messages immediately after they are sent without a refresh to the browser. If your browser does not support WebSockets, a simple refresh will update the email listing.&lt;/p&gt;

&lt;p&gt;Another great feature of MailCatcher is the ability to view both the HTML and plain text versions of emails. This feature alone has saved us some time during testing of our email views.&lt;/p&gt;

&lt;p&gt;MailCatcher also lists any attachments within the email for easy downloading.&lt;/p&gt;

&lt;h2&gt;Getting Started&lt;/h2&gt;

&lt;p&gt;To get up and running, install the mailcatcher gem:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gem install mailcatcher
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, in your development configuration file &lt;code&gt;config/development.rb&lt;/code&gt;, set the following Action Mailer settings:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action_mailer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delivery_method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:smtp&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action_mailer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;smtp_settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                         &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1025&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, start the mailcatcher daemon in your terminal:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mailcatcher
Starting &lt;span class="nv"&gt;MailCatcher&lt;/span&gt;
&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; smtp://127.0.0.1:1025
&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; http://127.0.0.1:1080
*** MailCatcher runs as a daemon by default. Go to the web interface to quit.
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mailcatcher.me/"&gt;MailCatcher project page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sj26/mailcatcher"&gt;GitHub page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/remarkablelabs/~4/sQ2f0PyoXuY" height="1" width="1"/&gt;</description>
    <feedburner:origLink>http://blog.remarkablelabs.com/2013/01/mailcatcher-making-working-with-email-in-development-mode-a-pleasure</feedburner:origLink></item>
    <item>
      <title>Quarterly Goals and Habits over Resolutions</title>
      <link>http://feedproxy.google.com/~r/remarkablelabs/~3/MHAo1-zDa-Y/quarterly-goals-and-habits-over-resolutions</link>
      <pubDate>Mon, 07 Jan 2013 14:15:49 -0500</pubDate>
      <author>Kevin Faustino</author>
      <guid isPermaLink="false">http://blog.remarkablelabs.com/2013/01/quarterly-goals-and-habits-over-resolutions</guid>
      <description>&lt;p&gt;The beginning of the New Year is the time when businesses and individuals set resolutions for the year. While it&amp;#39;s important to set high-level goals for the upcoming year, I tend to focus not on resolutions, but creation of habits and quarterly goals instead.&lt;/p&gt;

&lt;p&gt;Setting a yearly goal/resolution is like developing a software product using the &lt;a href="http://en.wikipedia.org/wiki/Waterfall_model"&gt;Waterfall model&lt;/a&gt;, it doesn&amp;#39;t account for change. Things happen that can alter the course of our lives and businesses. By planning quarterly over yearly, it allows us to embrace change and shift our focus to goals that will have the most impact on our businesses and lives.&lt;/p&gt;

&lt;h2&gt;Achieve Yearly Objectives with Quarterly Goals&lt;/h2&gt;

&lt;p&gt;Planning quarterly all the time is nice, but sometimes there are high-level goals which your business does want to achieve. This can be something like reaching X amount of revenue in 2013. To plan for these types of goals, break them down into manageable parts.&lt;/p&gt;

&lt;p&gt;For example, if a software product wanted to gain 1000 new customers in 2013, they could set a quarterly goal of 250 new customers instead. After the first quarter, based on the amount of new customers obtained, you can pivot the goal for the next quarter, or proceed with trying to obtain 250 more new customers.&lt;/p&gt;

&lt;h2&gt;How I Plan&lt;/h2&gt;

&lt;p&gt;I&amp;#39;ve developed a system using a combination of techniques found in &lt;a href="http://www.accidentalcreative.com/book"&gt;The Accidental Creative&lt;/a&gt;, &lt;a href="http://www.amazon.com/Getting-Things-Done-Stress-Free-Productivity/dp/0142000280"&gt;Getting Things Done&lt;/a&gt;, and &lt;a href="http://www.amazon.com/Eat-That-Frog-Great-Procrastinating/dp/1576754227"&gt;Eat That Frog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Accidental Creative discusses the concept of &lt;em&gt;&amp;quot;Checkpoints&amp;quot;&lt;/em&gt;, which focuses on having weekly, monthly and quarterly reviews. Within each of these checkpoints, you evaluate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your areas of focus&lt;/li&gt;
&lt;li&gt;Relationships&lt;/li&gt;
&lt;li&gt;Energy (Are there projects that need to be pruned?)&lt;/li&gt;
&lt;li&gt;Stimuli (What will help you with upcoming projects and grow?)&lt;/li&gt;
&lt;li&gt;Hours (What will require the most of your time)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of these areas, I apply the &lt;em&gt;&amp;quot;Law of Three&amp;quot;&lt;/em&gt; defined in Eat That Frog. In each following category, I define the three most important goals for the quarter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business/Career&lt;/li&gt;
&lt;li&gt;Family/Relationship&lt;/li&gt;
&lt;li&gt;Financial&lt;/li&gt;
&lt;li&gt;Health&lt;/li&gt;
&lt;li&gt;Professional Development&lt;/li&gt;
&lt;li&gt;Social/Community&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once all quarterly goals have been set, I create projects for each goal in my GTD system. I recommend &lt;a href="http://culturedcode.com/things/"&gt;Things&lt;/a&gt; as it works perfectly with GTD and syncs over the internet. The next step is to set challenges/tasks for each goal/project. Set deadlines for each action step, as a goal without one has no urgency.&lt;/p&gt;

&lt;h2&gt;Habits&lt;/h2&gt;

&lt;p&gt;Some lifestyle goals such as losing X amount of weight/inches, and being more productive are fundamentally tied to developing habits. Charles Duhigg&amp;#39;s book &lt;a href="http://charlesduhigg.com/the-power-of-habit/"&gt;&amp;quot;The Power of Habit&amp;quot;&lt;/a&gt; goes into how certain habits are triggered via a &lt;em&gt;habit loop&lt;/em&gt;. This loop consists of a trigger(&amp;quot;cue&amp;quot;), a routine, and finally a reward.&lt;/p&gt;

&lt;p&gt;Once you are aware of how habits are triggers and created, it makes it much easier to develop new ones. I cue habits everyday using the iPhone application &lt;a href="https://itunes.apple.com/us/app/commit/id473527073?mt=8"&gt;Commit&lt;/a&gt;. At a specified time, Commit will send me a reminder(&amp;quot;cue&amp;quot;) asking if I&amp;#39;ve committed to a specified goal. By executing the commitment once I am reminded, it triggers a &amp;quot;routine&amp;quot;, which ultimately allows me to reach my goal(&amp;quot;reward&amp;quot;).&lt;/p&gt;

&lt;h2&gt;Current Goals&lt;/h2&gt;

&lt;p&gt;Listed below is a sample of some goals/challenges I want to achieve in the next quarter.&lt;/p&gt;

&lt;h3&gt;Write 1000 words a day&lt;/h3&gt;

&lt;p&gt;One of my high-level goals is to become a better writer. The key to becoming better at anything is practice, practice, practice. Thus for the next quarter, and most likely the year, I want to write 1000 words a day. The writing can be done towards anything from this blog, a book, or a journal. I will be using the site &lt;a href="http://750words.com/"&gt;750words.com&lt;/a&gt; to keep track of my progress.&lt;/p&gt;

&lt;h3&gt;Complete the &amp;quot;Rails 4 Upgrading Guide&amp;quot; eBook&lt;/h3&gt;

&lt;p&gt;With the completion of the &lt;a href="http://blog.remarkablelabs.com/2012/11/rails-4-countdown-to-2013"&gt;Rails 4 Countdown series&lt;/a&gt;, the next step is to expand on what I have wrote, and make an ebook which can be used as a reference for those developers upgrading from Rails 3. Over the next three months, I want to have this completed and sent to all the Remarkable Labs newsletter subscribers.&lt;/p&gt;

&lt;h3&gt;Launch a Web Application&lt;/h3&gt;

&lt;p&gt;Nathan Barry in his blog wrote about a &lt;a href="http://nathanbarry.com/starting-web-app-challenge/"&gt;Web App Challenge&lt;/a&gt;. Essentially to complete the challenge, you must build a web application within six months to have $5,000 in recurring revenue each month. Over the next quarter, I want to take the steps necessary to launch my own product to coincide with this challenge.&lt;/p&gt;

&lt;h3&gt;Get back to the gym and lose 18 pounds&lt;/h3&gt;

&lt;p&gt;While this goal is cliché, going to the gym in the morning was something that allowed my day to get off to a great start. I had more energy, felt better, and enjoyed setting fitness goals for myself. Over 8 months ago, I stopped going to the gym due to an injury and never got into the habit of going again. Hopefully, I can rectify that.&lt;/p&gt;

&lt;h2&gt;Feedback&lt;/h2&gt;

&lt;p&gt;I&amp;#39;d love to hear your thoughts on this system and any goals you have personally set. Feel free to &lt;a href="mailto:kevin@remarkablelabs.com"&gt;email me&lt;/a&gt; or leave a comment.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/remarkablelabs/~4/MHAo1-zDa-Y" height="1" width="1"/&gt;</description>
    <feedburner:origLink>http://blog.remarkablelabs.com/2013/01/quarterly-goals-and-habits-over-resolutions</feedburner:origLink></item>
    <item>
      <title>Rails 4 Upgrading Guide [Rails 4 Countdown to 2013]</title>
      <link>http://feedproxy.google.com/~r/remarkablelabs/~3/Y0jRlIHkEl0/rails-4-upgrading-guide-rails-4-countdown-to-2013</link>
      <pubDate>Mon, 31 Dec 2012 09:27:27 -0500</pubDate>
      <author>Kevin Faustino</author>
      <guid isPermaLink="false">http://blog.remarkablelabs.com/2012/12/rails-4-upgrading-guide-rails-4-countdown-to-2013</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This post is part of a series of &lt;a href="http://blog.remarkablelabs.com/2012/11/rails-4-countdown-to-2013"&gt;31 Rails 4 articles being released each day in December 2012&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As 2012 comes to a close, we can look forward to 2013 as Ruby on Rails 4.0 will be released sometime in the coming year. Over the month of December, we have covered what we feel are some of the biggest changes coming to Rails 4. &lt;/p&gt;

&lt;p&gt;We at Remarkable Labs really hope you&amp;#39;ve enjoyed the series, and to finish it off, I wanted to announce that I will be writing an ebook, titled &amp;quot;The Rails 4 Upgrading Guide&amp;quot;. While not yet complete, here is a list of some of the content to look forward to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In-depth coverage of what&amp;#39;s new to Rails 4&lt;/li&gt;
&lt;li&gt;A step-by-step guide for upgrading your Rails 3 application&lt;/li&gt;
&lt;li&gt;Tips and use cases on using Rails 4&amp;#39;s new features&lt;/li&gt;
&lt;li&gt;Upgrading checklist&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The ebook will be available in PDF, ePub(iBooks, Nook), and Mobi(Kindle) formats. We are also making it absolutely free for all our mailing list subscribers. Be sure to &lt;a href="http://eepurl.com/rJa35"&gt;sign up for the mailing list&lt;/a&gt; to receive your copy of &amp;quot;The Rails 4 Upgrading Guide&amp;quot; when it&amp;#39;s finished.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/remarkablelabs/~4/Y0jRlIHkEl0" height="1" width="1"/&gt;</description>
    <feedburner:origLink>http://blog.remarkablelabs.com/2012/12/rails-4-upgrading-guide-rails-4-countdown-to-2013</feedburner:origLink></item>
    <item>
      <title>Live Streaming [Rails 4 Countdown to 2013]</title>
      <link>http://feedproxy.google.com/~r/remarkablelabs/~3/Cxh3h013hEg/live-streaming-rails-4-countdown-to-2013</link>
      <pubDate>Sun, 30 Dec 2012 16:38:35 -0500</pubDate>
      <author>Kevin Faustino</author>
      <guid isPermaLink="false">http://blog.remarkablelabs.com/2012/12/live-streaming-rails-4-countdown-to-2013</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This post is part of a series of &lt;a href="http://blog.remarkablelabs.com/2012/11/rails-4-countdown-to-2013"&gt;31 Rails 4 articles being released each day in December 2012&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One major feature being added to Rails 4 is the ability to stream data to the client. While the streaming of templates is currently available in Rails 3, thanks to Aaron Patterson&amp;#39;s efforts, we can now stream other types of data such as JSON.&lt;/p&gt;

&lt;p&gt;To enable live streaming in a controller, you must mixin the module &lt;code&gt;ActionController::Live&lt;/code&gt;. This provides an I/O like interface to the response, allowing you to continuously write to the client until the stream is explicitly closed.&lt;/p&gt;

&lt;p&gt;Here is an example of a live streaming controller from the Rails docs:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Live&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stream&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;text/event-stream&amp;#39;&lt;/span&gt;
    &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;hello world&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="nb"&gt;sleep&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Requirements&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;All actions executed from &lt;code&gt;ActionController::Live&lt;/code&gt; enabled controllers are run in a separate thread, thus controller action code must be thread safe.&lt;/li&gt;
&lt;li&gt;A concurrent Ruby Web Server is required to take advantage of live streaming. Be sure to take a look at &lt;a href="http://puma.io/"&gt;puma&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Headers must be written before anything is written to the client.&lt;/li&gt;
&lt;li&gt;Streams must be closed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Why is this important?&lt;/h2&gt;

&lt;p&gt;This feature alone allows Rails to do more than just serve HTTP web pages and JSON. It can now handle a variety of other use cases, that were not possible in the past. For example, using &lt;a href="http://en.wikipedia.org/wiki/Server-sent_events"&gt;Server-sent events&lt;/a&gt;, the ability to create chat clients, push notifications, and real-time feeds are achievable from Rails itself. &lt;/p&gt;

&lt;h2&gt;Further Reading&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://edgeapi.rubyonrails.org/classes/ActionController/Live.html"&gt;&lt;code&gt;ActionController::Live&lt;/code&gt; documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tenderlovemaking.com/2012/07/30/is-it-live.html"&gt;Is It Live?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/"&gt;Why Rails 4 Live Streaming is a big deal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/remarkablelabs/~4/Cxh3h013hEg" height="1" width="1"/&gt;</description>
    <feedburner:origLink>http://blog.remarkablelabs.com/2012/12/live-streaming-rails-4-countdown-to-2013</feedburner:origLink></item>
    <item>
      <title>A love affair with PostgreSQL [Rails 4 Countdown to 2013]</title>
      <link>http://feedproxy.google.com/~r/remarkablelabs/~3/PDvvg636--U/a-love-affair-with-postgresql-rails-4-countdown-to-2013</link>
      <pubDate>Sat, 29 Dec 2012 16:04:05 -0500</pubDate>
      <author>Kevin Faustino</author>
      <guid isPermaLink="false">http://blog.remarkablelabs.com/2012/12/a-love-affair-with-postgresql-rails-4-countdown-to-2013</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This post is part of a series of &lt;a href="http://blog.remarkablelabs.com/2012/11/rails-4-countdown-to-2013"&gt;31 Rails 4 articles being released each day in December 2012&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Out of all the supported databases available in Active Record, PostgreSQL received the most amount of attention during the development of Rails 4. In today&amp;#39;s countdown post, we are going to look at the various additions made to the PostgreSQL database adapter.&lt;/p&gt;

&lt;h2&gt;hstore support&lt;/h2&gt;

&lt;p&gt;Rails 4 comes with &lt;a href="http://www.postgresql.org/docs/9.1/static/hstore.html"&gt;&lt;code&gt;hstore&lt;/code&gt;&lt;/a&gt; support out of the box. &lt;code&gt;hstore&lt;/code&gt; allows you to store a set of key/value pairs within a single PostgreSQL value. In other words, it allows you to have NoSQL schema-less data support in PostgreSQL.&lt;/p&gt;

&lt;p&gt;To get started, first setup your database to use the hstore extension:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddHstoreExtension&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;up&lt;/span&gt;
    &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;CREATE EXTENSION hstore&amp;#39;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;down&lt;/span&gt;
    &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;DROP EXTENSION hstore&amp;#39;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, add the &lt;code&gt;hstore&lt;/code&gt; column type to a model:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddPropertiesToComics&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;up&lt;/span&gt;
    &lt;span class="n"&gt;add_column&lt;/span&gt; &lt;span class="ss"&gt;:comics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:hstore&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;down&lt;/span&gt;
    &lt;span class="n"&gt;remove_column&lt;/span&gt; &lt;span class="ss"&gt;:comics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:properties&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using the &lt;code&gt;store_accessor&lt;/code&gt; macro style method in Active Record models, we can add read/write accessors to key/value hstore properties:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Comic&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;store_accessor&lt;/span&gt; &lt;span class="ss"&gt;:properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:story_arc&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;comic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;
&lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;properties&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;story_arc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Throne of Atlantis&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; UPDATE &amp;quot;comics&amp;quot; SET &amp;quot;properties&amp;quot; = &amp;#39;&amp;quot;story_arc&amp;quot;=&amp;gt;&amp;quot;Throne of Atlantis&amp;quot;&amp;#39;, &amp;quot;updated_at&amp;quot; = &amp;#39;2012-12-29 19:31:45.234882&amp;#39; WHERE &amp;quot;comics&amp;quot;.&amp;quot;id&amp;quot; = 1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using the store accessors, you can include the dynamic attributes in forms and also have the ability to add Active Model validations to them.&lt;/p&gt;

&lt;p&gt;To query against &lt;code&gt;hstore&lt;/code&gt; data in Active Record, use SQL string conditions with the &lt;code&gt;where&lt;/code&gt; query method:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt; &lt;span class="no"&gt;Comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;properties -&amp;gt; &amp;#39;story_arc&amp;#39; = &amp;#39;Throne of Atlantis&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;#  SELECT &amp;quot;comics&amp;quot;.* FROM &amp;quot;comics&amp;quot; WHERE (properties -&amp;gt; &amp;#39;story_arc&amp;#39; = &amp;#39;Throne of Atlantis&amp;#39;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; When an &lt;code&gt;hstore&lt;/code&gt; attribute is returned from PostgreSQL, all key/values are going to be strings.&lt;/p&gt;

&lt;h3&gt;Indexes&lt;/h3&gt;

&lt;p&gt;If you are doing any queries on an &lt;code&gt;hstore&lt;/code&gt; property, be sure to add the appropriate index. When adding an index, you will have to decide to use either GIN or GiST index types. The distinguishing factor between the two index types is that GIN index lookups are three times faster than GiST indexes, however they also take three times longer to build. Checkout the &lt;a href="http://www.postgresql.org/docs/9.1/static/textsearch-indexes.html"&gt;documentation&lt;/a&gt;, which goes into detail about the differences.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;column&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;gist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;column&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddIndexToComicsProperties&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;up&lt;/span&gt;
    &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;CREATE INDEX comics_properties ON comics USING gin(properties)&amp;#39;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;down&lt;/span&gt;
    &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;DROP INDEX comics_properties&amp;#39;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Indexes can only be used for queries with &lt;code&gt;@&amp;gt;&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, &lt;code&gt;?&amp;amp;&lt;/code&gt; and &lt;code&gt;?|&lt;/code&gt; operators. Thus the ActiveRecord example in the previous section using the &lt;code&gt;-&amp;gt;&lt;/code&gt; operator would not use any indexes. (Thanks to Philip Hofstetter for pointing this out)&lt;/p&gt;

&lt;h3&gt;Upgrade Path&lt;/h3&gt;

&lt;p&gt;If this is something you would like to use in your Rails 3 applications today, you can use the &lt;a href="https://github.com/engageis/activerecord-postgres-hstore"&gt;activerecord-postgres-hstore gem&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;hstore resources&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://railscasts.com/episodes/345-hstore"&gt;hstore Railscast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.postgresql.org/docs/9.1/static/hstore.html"&gt;PostgreSQL Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.postgresql.org/docs/9.1/static/textsearch-indexes.html"&gt;GiST and GIN Index Types&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Array support&lt;/h2&gt;

&lt;p&gt;Another native type being supported by Active Record for PostgreSQL databases is Array.&lt;/p&gt;

&lt;p&gt;When creating a column in a migration, you must pass &lt;code&gt;true&lt;/code&gt; to the &lt;code&gt;array&lt;/code&gt; option to set the attribute as an Array.&lt;/p&gt;

&lt;p&gt;Here is an example of creating a string
 array of tags:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddTagsToArticles&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;change_table&lt;/span&gt; &lt;span class="ss"&gt;:articles&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# ALTER TABLE &amp;quot;articles&amp;quot; ADD COLUMN &amp;quot;tags&amp;quot; character varying(255)[]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, add an item to the array attribute:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;
&lt;span class="c1"&gt;# UPDATE &amp;quot;articles&amp;quot; SET &amp;quot;tags&amp;quot; = &amp;#39;{&amp;quot;rails&amp;quot;}&amp;#39;, &amp;quot;updated_at&amp;quot; = &amp;#39;2012-12-29 20:12:49.825980&amp;#39; WHERE &amp;quot;articles&amp;quot;.&amp;quot;id&amp;quot; = 1&lt;/span&gt;
&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reload&lt;/span&gt;
&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; [&amp;quot;rails&amp;quot;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the &lt;a href="https://github.com/dockyard/pg_array_parser"&gt;&lt;code&gt;pg_array_parser gem&lt;/code&gt;&lt;/a&gt; is included in the application &lt;code&gt;Gemfile&lt;/code&gt;, Rails will use it when parsing PostgreSQL&amp;#39;s array representation. The gem includes a native C extention and JRuby support.&lt;/p&gt;

&lt;h3&gt;Resources&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.postgresql.org/docs/9.1/static/arrays.html"&gt;PostgreSQL documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dockyard/pg_array_parser"&gt;pg_array_parser gem&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;uuid type&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://www.postgresql.org/docs/9.1/static/datatype-uuid.html"&gt;Universally unique identifier (UUID) column type&lt;/a&gt; support has been added to Rails 4.&lt;/p&gt;

&lt;p&gt;To set a column as UUID, use &lt;code&gt;add_column&lt;/code&gt; in your migration and set the data type to &lt;code&gt;:uuid&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;add_column&lt;/span&gt; &lt;span class="ss"&gt;:table_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:unique_identifier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:uuid&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When reading/writing to a UUID attribute, you will always be dealing with a string:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unique_identifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Network Address data types&lt;/h2&gt;

&lt;p&gt;PostgreSQL has data types exclusively for IPv4, IPv6, and MAC addresses. Data types &lt;code&gt;inet&lt;/code&gt; and &lt;code&gt;cidr&lt;/code&gt; are used for IPv4 or IPv6 host address. The difference between &lt;code&gt;inet&lt;/code&gt; and &lt;code&gt;cidr&lt;/code&gt; is that the former accepts values with nonzero bits to the right of the netmask. MAC addresses are represented with the &lt;code&gt;macaddr&lt;/code&gt; data type.&lt;/p&gt;

&lt;p&gt;When reading &lt;code&gt;inet&lt;/code&gt;/&lt;code&gt;cidr&lt;/code&gt; data types from the database, Active Record will convert the values to &lt;code&gt;IPAddr&lt;/code&gt; objects. Reading and writing to &lt;code&gt;macaddr&lt;/code&gt; attributes on the other hand uses strings.&lt;/p&gt;

&lt;p&gt;To set a column as a network address, use &lt;code&gt;add_column&lt;/code&gt; in your migration and set the data type to &lt;code&gt;inet&lt;/code&gt;, &lt;code&gt;cidr&lt;/code&gt;, or &lt;code&gt;macaddr&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddNetworkAddresses&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;add_column&lt;/span&gt; &lt;span class="ss"&gt;:table_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:inet_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:inet&lt;/span&gt;
    &lt;span class="n"&gt;add_column&lt;/span&gt; &lt;span class="ss"&gt;:table_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:cidr_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:cidr&lt;/span&gt;
    &lt;span class="n"&gt;add_column&lt;/span&gt; &lt;span class="ss"&gt;:table_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:mac_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:macaddr&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inet_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IPAddr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;127.0.0.1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;
&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reload&lt;/span&gt;
&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inet_address&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; &amp;lt;IPAddr: IPv4:127.0.0.1/255.255.255.255&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Other data types&lt;/h2&gt;

&lt;p&gt;The following datatypes can be created in PostgreSQL and be correctly converted to and from the database:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;int4range&lt;/li&gt;
&lt;li&gt;int8range&lt;/li&gt;
&lt;li&gt;json&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/remarkablelabs/~4/PDvvg636--U" height="1" width="1"/&gt;</description>
    <feedburner:origLink>http://blog.remarkablelabs.com/2012/12/a-love-affair-with-postgresql-rails-4-countdown-to-2013</feedburner:origLink></item>
  </channel>
</rss>
