<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>dan.thoughts</title>
	<atom:link href="http://blog.sosedoff.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.sosedoff.com</link>
	<description>Web-development, PHP, Ruby, Sinatra, Merb, Rails, MySQL, SQLite, Web Services.</description>
	<lastBuildDate>Thu, 26 Apr 2012 21:46:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Emoji and Rails JSON output issue</title>
		<link>http://blog.sosedoff.com/2012/04/26/emoji-and-rails-json-output-issue/</link>
		<comments>http://blog.sosedoff.com/2012/04/26/emoji-and-rails-json-output-issue/#comments</comments>
		<pubDate>Thu, 26 Apr 2012 21:46:58 +0000</pubDate>
		<dc:creator>Dan Sosedoff</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[emoji]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[problem]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.sosedoff.com/?p=434</guid>
		<description><![CDATA[While working on API for the iOS-based device i noticed that text with emoji that comes from devices is being stored normally in database but when its being rendered as JSON format it gets broken.

>> JSON({:a => "\360\237\230\204"}.to_json)
=> {"a"=>"\357\230\204"}

The problem is related to the Rails internals and its JSON escaping process. After digging around internet [...]]]></description>
			<content:encoded><![CDATA[<p>While working on API for the iOS-based device i noticed that text with <a href="http://en.wikipedia.org/wiki/Emoji" target="_blank">emoji</a> that comes from devices is being stored normally in database but when its being rendered as JSON format it gets broken.</p>
<pre>
>> JSON({:a => "\360\237\230\204"}.to_json)
=> {"a"=>"\357\230\204"}
</pre>
<p>The problem is related to the Rails internals and its JSON escaping process. After digging around internet i&#8217;ve found that there&#8217;re few posts that explain the bug and also provide few solutions.</p>
<ul>
<li><a href="https://github.com/rails/rails/issues/3727">Github rails issue #3727</a></li>
<li><a href="http://stackoverflow.com/questions/7775597/bug-in-ruby-json-lib-when-handling-4-byte-unicode-emoji">Stackoverflow question</a></li>
</ul>
<h3>Solution</h3>
<p>The issue gets fixed by placing the following content into <i>config/initializers/active_support_encoding.rb</i> file:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> <span style="color:#6666ff; font-weight:bold;">ActiveSupport::JSON::Encoding</span>
  <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#0000FF; font-weight:bold;">self</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> escape<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">string</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#CC0066; font-weight:bold;">string</span>.<span style="color:#9900CC;">respond_to</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:force_encoding</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#CC0066; font-weight:bold;">string</span> = <span style="color:#CC0066; font-weight:bold;">string</span>.<span style="color:#9900CC;">encode</span><span style="color:#006600; font-weight:bold;">&#40;</span>::<span style="color:#6666ff; font-weight:bold;">Encoding::UTF_8</span>, <span style="color:#ff3333; font-weight:bold;">:undef</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:replace</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">force_encoding</span><span style="color:#006600; font-weight:bold;">&#40;</span>::<span style="color:#6666ff; font-weight:bold;">Encoding::BINARY</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
      json = <span style="color:#CC0066; font-weight:bold;">string</span>.<span style="color:#CC0066; font-weight:bold;">gsub</span><span style="color:#006600; font-weight:bold;">&#40;</span>escape_regex<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>s<span style="color:#006600; font-weight:bold;">|</span> ESCAPED_CHARS<span style="color:#006600; font-weight:bold;">&#91;</span>s<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
      json = <span style="color:#006600; font-weight:bold;">%</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{json}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      json.<span style="color:#9900CC;">force_encoding</span><span style="color:#006600; font-weight:bold;">&#40;</span>::<span style="color:#6666ff; font-weight:bold;">Encoding::UTF_8</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> json.<span style="color:#9900CC;">respond_to</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:force_encoding</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      json
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.sosedoff.com/2012/04/26/emoji-and-rails-json-output-issue/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding code revision header to your apps</title>
		<link>http://blog.sosedoff.com/2012/01/25/adding-code-revision-header-to-your-apps/</link>
		<comments>http://blog.sosedoff.com/2012/01/25/adding-code-revision-header-to-your-apps/#comments</comments>
		<pubDate>Wed, 25 Jan 2012 18:54:45 +0000</pubDate>
		<dc:creator>Dan Sosedoff</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[middleware]]></category>
		<category><![CDATA[rack]]></category>

		<guid isPermaLink="false">http://blog.sosedoff.com/?p=423</guid>
		<description><![CDATA[Sometimes its necessary to have a code revision tag somewhere on the website. Use cases are usually different and vary from just checking against the current revision, automatic upgrades and such. 
If you&#8217;re rolling deployments with capistrano, it will insert the REVISION file under the app&#8217;s root dir with git sha or svn revision or [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes its necessary to have a code revision tag somewhere on the website. Use cases are usually different and vary from just checking against the current revision, automatic upgrades and such. </p>
<p>If you&#8217;re rolling deployments with capistrano, it will insert the REVISION file under the app&#8217;s root dir with git sha or svn revision or whatever tag based on SCM of your choice.</p>
<p>Here is the simple rack middleware that injects that revision as a &#8216;X-REVISION&#8217; header in responses.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Rack
  <span style="color:#9966CC; font-weight:bold;">class</span> Revision
    @@revision = <span style="color:#0000FF; font-weight:bold;">nil</span>
    <span style="color:#CC00FF; font-weight:bold;">File</span> = ::<span style="color:#CC00FF; font-weight:bold;">File</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>app, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@app</span>   = app
      <span style="color:#0066ff; font-weight:bold;">@block</span> = block
      <span style="color:#0066ff; font-weight:bold;">@file</span>  = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">Dir</span>.<span style="color:#9900CC;">pwd</span>, <span style="color:#996600;">'REVISION'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> call<span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span>
      status, headers, body = <span style="color:#0066ff; font-weight:bold;">@app</span>.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span>
      headers<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'X-Revision'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = revision
      <span style="color:#006600; font-weight:bold;">&#91;</span>status, headers, body<span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    protected
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> revision
      @@revision <span style="color:#006600; font-weight:bold;">||</span>= read_revision
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> read_revision
      <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>@file<span style="color:#006600; font-weight:bold;">&#41;</span> ? <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>@file<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">strip</span> : <span style="color:#996600;">'UNDEFINED'</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>For instance, just put that file as lib/rack/revision.rb and change your config.ru file:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> ::<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">expand_path</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'../config/environment'</span>,  <span style="color:#0000FF; font-weight:bold;">__FILE__</span><span style="color:#006600; font-weight:bold;">&#41;</span>
use <span style="color:#6666ff; font-weight:bold;">Rack::Revision</span>
run <span style="color:#6666ff; font-weight:bold;">YOUR_APP::Application</span></pre></div></div>

<p>You&#8217;ll need to restart the app to apply the changes.</p>
<p>To test if it works just run:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">curl <span style="color: #660033;">-i</span> <span style="color: #660033;">-X</span> HEAD <span style="color: #ff0000;">&quot;http://YOUR_WEBSITE/&quot;</span></pre></div></div>

<p>Sample output would be:</p>
<pre>
ETag: "8d6228d86642025c31e3d54e9a67b14b"
Cache-Control: max-age=0, private, must-revalidate
X-Runtime: 0.001491
X-Rack-Cache: miss
X-Revision: f8c51630843898e88848261dd5ebac3fdebc5e48
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.sosedoff.com/2012/01/25/adding-code-revision-header-to-your-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using capistrano-unicorn with multistage environment</title>
		<link>http://blog.sosedoff.com/2012/01/21/using-capistrano-unicorn-with-multistage-environment/</link>
		<comments>http://blog.sosedoff.com/2012/01/21/using-capistrano-unicorn-with-multistage-environment/#comments</comments>
		<pubDate>Sun, 22 Jan 2012 03:52:57 +0000</pubDate>
		<dc:creator>Dan Sosedoff</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[unicorn]]></category>

		<guid isPermaLink="false">http://blog.sosedoff.com/?p=417</guid>
		<description><![CDATA[Awhile ago i create a capistrano-unicorn plugin for Capistrano that allows you to deploy your rails application using Unicorn. It works fine until you define multiple stages in your deployment configuration. 
The issue &#8211; capistrano loads default configuration and then executes your staging task and overrides previously defined variables. Default environment before executing stage task [...]]]></description>
			<content:encoded><![CDATA[<p>Awhile ago i create a <a href="https://github.com/sosedoff/capistrano-unicorn">capistrano-unicorn</a> plugin for <a href="https://github.com/capistrano/capistrano">Capistrano</a> that allows you to deploy your rails application using <a href="http://unicorn.bogomips.org/">Unicorn</a>. It works fine until you define multiple stages in your deployment configuration. </p>
<p>The issue &#8211; capistrano loads default configuration and then executes your staging task and overrides previously defined variables. Default environment before executing stage task is set to :production. So unless you define :rails_env, :unicorn_env, :app_env in your stage config it will use a wrong environment. </p>
<p>Lets take a look at sample deploy.rb file:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">set <span style="color:#ff3333; font-weight:bold;">:stages</span>, <span style="color:#006600; font-weight:bold;">%</span>w<span style="color:#006600; font-weight:bold;">&#40;</span>production staging<span style="color:#006600; font-weight:bold;">&#41;</span>
set <span style="color:#ff3333; font-weight:bold;">:default_stage</span>, <span style="color:#996600;">&quot;staging&quot;</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capistrano/ext/multistage'</span></pre></div></div>

<p>You&#8217;ll need to add config/deploy/staging.rb and production.rb files:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">set <span style="color:#ff3333; font-weight:bold;">:domain</span>,      <span style="color:#996600;">&quot;YOUR_HOST&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:rails_env</span>,   <span style="color:#996600;">&quot;staging&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:unicorn_env</span>, <span style="color:#996600;">&quot;staging&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:app_env</span>,     <span style="color:#996600;">&quot;staging&quot;</span>
&nbsp;
role <span style="color:#ff3333; font-weight:bold;">:web</span>, domain
role <span style="color:#ff3333; font-weight:bold;">:app</span>, domain
role <span style="color:#ff3333; font-weight:bold;">:db</span>,  domain, <span style="color:#ff3333; font-weight:bold;">:primary</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>
&nbsp;
set <span style="color:#ff3333; font-weight:bold;">:deploy_to</span>,   <span style="color:#996600;">&quot;/home/#{user}/#{application}/#{fetch :app_env}&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:current_path</span>, <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span>deploy_to, current_dir<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>This should fix the problem with wrong rails env being passed to unicorn server. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sosedoff.com/2012/01/21/using-capistrano-unicorn-with-multistage-environment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Homebrew upgrade failure fix</title>
		<link>http://blog.sosedoff.com/2012/01/19/homebrew-upgrade-failure-fix/</link>
		<comments>http://blog.sosedoff.com/2012/01/19/homebrew-upgrade-failure-fix/#comments</comments>
		<pubDate>Fri, 20 Jan 2012 01:19:57 +0000</pubDate>
		<dc:creator>Dan Sosedoff</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[homebrew]]></category>
		<category><![CDATA[osx]]></category>

		<guid isPermaLink="false">http://blog.sosedoff.com/?p=412</guid>
		<description><![CDATA[If you have an old homebrew installation, upgrade method for package will fail with something like this:

Error: undefined method `include?' for nil:NilClass
Please report this bug:
    https://github.com/mxcl/homebrew/wiki/checklist-before-filing-a-new-issue
/usr/local/Library/Homebrew/formula.rb:417:in `canonical_name'
/usr/local/Library/Homebrew/formula.rb:449:in `factory'
/usr/local/Library/Contributions/examples/brew-upgrade.rb:7
/usr/local/Library/Contributions/examples/brew-upgrade.rb:7:in `map'
/usr/local/Library/Contributions/examples/brew-upgrade.rb:7
/usr/local/bin/brew:47:in `require'
/usr/local/bin/brew:47:in `require?'
/usr/local/bin/brew:80

This happens because of old brew-update command. Pretty annoying, so to fix it just run the following script:

cd `brew --prefix`/Library/Contributions/examples
git clean -n
git [...]]]></description>
			<content:encoded><![CDATA[<p>If you have an old homebrew installation, upgrade method for package will fail with something like this:</p>
<pre>
Error: undefined method `include?' for nil:NilClass
Please report this bug:
    https://github.com/mxcl/homebrew/wiki/checklist-before-filing-a-new-issue
/usr/local/Library/Homebrew/formula.rb:417:in `canonical_name'
/usr/local/Library/Homebrew/formula.rb:449:in `factory'
/usr/local/Library/Contributions/examples/brew-upgrade.rb:7
/usr/local/Library/Contributions/examples/brew-upgrade.rb:7:in `map'
/usr/local/Library/Contributions/examples/brew-upgrade.rb:7
/usr/local/bin/brew:47:in `require'
/usr/local/bin/brew:47:in `require?'
/usr/local/bin/brew:80
</pre>
<p>This happens because of old <i>brew-update</i> command. Pretty annoying, so to fix it just run the following script:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">`</span>brew --prefix<span style="color: #000000; font-weight: bold;">`/</span>Library<span style="color: #000000; font-weight: bold;">/</span>Contributions<span style="color: #000000; font-weight: bold;">/</span>examples
git clean <span style="color: #660033;">-n</span>
git clean <span style="color: #660033;">-f</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.sosedoff.com/2012/01/19/homebrew-upgrade-failure-fix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Deploying Rails application with Capistrano and Unicorn</title>
		<link>http://blog.sosedoff.com/2011/10/23/deploying-rails-application-with-capistrano-and-unicorn/</link>
		<comments>http://blog.sosedoff.com/2011/10/23/deploying-rails-application-with-capistrano-and-unicorn/#comments</comments>
		<pubDate>Sun, 23 Oct 2011 22:15:13 +0000</pubDate>
		<dc:creator>Dan Sosedoff</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[unicorn]]></category>

		<guid isPermaLink="false">http://blog.sosedoff.com/?p=405</guid>
		<description><![CDATA[I&#8217;ve been switching all my new applications to Unicorn (nginx+unicorn) from Passenger (nginx+passenger). Passenger comes with an extension to nginx and needs to be compiled with nginx as a plugin. That requires additional maintenance on server and not a good idea in general when having more that just 1 ruby runtime on the server. 
I [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been switching all my new applications to <a href="http://unicorn.bogomips.org/">Unicorn</a> (nginx+unicorn) from <a href="http://www.modrails.com/">Passenger</a> (nginx+passenger). Passenger comes with an extension to nginx and needs to be compiled with nginx as a plugin. That requires additional maintenance on server and not a good idea in general when having more that just 1 ruby runtime on the server. </p>
<p>I use <a href="https://github.com/capistrano/capistrano">capistrano</a> for all my apps and find it very useful for quick and handy deployments. After switch to unicorn i&#8217;ve been copying-and-pasting the same code over and over again, so i decided to move it to a separate gem. </p>
<p>Check out code on github &#8211; <a href="https://github.com/sosedoff/capistrano-unicorn">capistrano-unicorn</a>.</p>
<h3>Usage</h3>
<p>Assuming that you already have your capistrano script ready, add gem to the Gemfile:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">group <span style="color:#ff3333; font-weight:bold;">:development</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  gem <span style="color:#996600;">'capistrano-unicorn'</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Then, add requirement to the deploy.rb file (after all hooks):</p>

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

<h3>Configuration</h3>
<p>All unicorn configs should be placed under APP_ROOT/config/unicorn/ENVIRONMENT.rb<br />
So, for each environment there should be a separate file.</p>
<p>Test if that worked:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">cap unicorn:start
cap unicorn:stop
cap unicorn:reload</pre></div></div>

<p>For more information check out github repository &#8211; <a href="https://github.com/sosedoff/capistrano-unicorn">capistrano-unicorn</a>.<br/><br />
It is still under development, but basic functionality works fine.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sosedoff.com/2011/10/23/deploying-rails-application-with-capistrano-and-unicorn/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Capistrano MySQL Backups for Rails</title>
		<link>http://blog.sosedoff.com/2011/08/10/capistrano-mysql-backups-for-rails/</link>
		<comments>http://blog.sosedoff.com/2011/08/10/capistrano-mysql-backups-for-rails/#comments</comments>
		<pubDate>Thu, 11 Aug 2011 00:34:50 +0000</pubDate>
		<dc:creator>Dan Sosedoff</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[backups]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://blog.sosedoff.com/?p=395</guid>
		<description><![CDATA[If you need to backup your application before each deployment, here is the small manual.
Capistrano versions: >= 2.5
Configuration
First, you need to define application environment:

# Define server-side rails environment
set :rails_env, &#34;production&#34;
&#160;
# Primary deployment location
set :deploy_to, &#34;/home/#{user}/#{application}&#34;
&#160;
# Place where all backups will be dumped
set :backup_to, &#34;/home/#{user}/#{application}/backups&#34;

Also, add this function. It allows capistrano to check if remote file [...]]]></description>
			<content:encoded><![CDATA[<p>If you need to backup your application before each deployment, here is the small manual.</p>
<p>Capistrano versions: >= 2.5</p>
<h2>Configuration</h2>
<p>First, you need to define application environment:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Define server-side rails environment</span>
set <span style="color:#ff3333; font-weight:bold;">:rails_env</span>, <span style="color:#996600;">&quot;production&quot;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Primary deployment location</span>
set <span style="color:#ff3333; font-weight:bold;">:deploy_to</span>, <span style="color:#996600;">&quot;/home/#{user}/#{application}&quot;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Place where all backups will be dumped</span>
set <span style="color:#ff3333; font-weight:bold;">:backup_to</span>, <span style="color:#996600;">&quot;/home/#{user}/#{application}/backups&quot;</span></pre></div></div>

<p>Also, add this function. It allows capistrano to check if remote file exists:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> remote_file_exists?<span style="color:#006600; font-weight:bold;">&#40;</span>full_path<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#996600;">'true'</span> ==  capture<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;if [ -e #{full_path} ]; then echo 'true'; fi&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">strip</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now, we need to add a backup task:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">namespace <span style="color:#ff3333; font-weight:bold;">:utils</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  desc <span style="color:#996600;">'Backup database before deploy'</span>
  task <span style="color:#ff3333; font-weight:bold;">:backup</span>, <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:db</span>, <span style="color:#ff3333; font-weight:bold;">:only</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>:primary <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    run <span style="color:#996600;">&quot;mkdir -p #{backup_to}&quot;</span> <span style="color:#008000; font-style:italic;"># Create a backup folder unless exists</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># Primary backup filename</span>
    filename = <span style="color:#996600;">&quot;#{backup_to}/#{application}_predeploy_#{Time.now.strftime(&quot;</span><span style="color:#006600; font-weight:bold;">%</span>m<span style="color:#006600; font-weight:bold;">%</span>d<span style="color:#006600; font-weight:bold;">%</span>Y<span style="color:#006600; font-weight:bold;">%</span>H<span style="color:#006600; font-weight:bold;">%</span>I<span style="color:#006600; font-weight:bold;">%</span>S<span style="color:#996600;">&quot;)}.sql.gz&quot;</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># Check if we've got database config</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> remote_file_exists?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{deploy_to}/current/config/database.yml&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>    
      text = capture<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;cat #{deploy_to}/current/config/database.yml&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      config = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span>text<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#91;</span>rails_env<span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
      on_rollback <span style="color:#006600; font-weight:bold;">&#123;</span> run <span style="color:#996600;">&quot;rm #{filename}&quot;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
      run <span style="color:#996600;">&quot;mysqldump -u #{config['username']} -p #{config['database']} | gzip --best &gt; #{filename}&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>ch, stream, out<span style="color:#006600; font-weight:bold;">|</span>
        ch.<span style="color:#9900CC;">send_data</span> <span style="color:#996600;">&quot;#{config['password']}<span style="color:#000099;">\n</span>&quot;</span> <span style="color:#9966CC; font-weight:bold;">if</span> out =~ <span style="color:#006600; font-weight:bold;">/</span>^Enter password:<span style="color:#006600; font-weight:bold;">/</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      logger.<span style="color:#9900CC;">debug</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;[Backup] No configuration file was found.&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>And finally, add the capistrano before hook:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">before <span style="color:#996600;">&quot;deploy&quot;</span>, <span style="color:#996600;">&quot;utils:backup&quot;</span></pre></div></div>

<h2>Testing</h2>
<p>To test if the task works, run:</p>
<pre>cap utils:backup</pre>
<p>On the server side you should see a backup file:</p>
<pre>/home/USER/APP/backups/APP_predeploy_MMDDYYHHMMSS.sql.gz.</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.sosedoff.com/2011/08/10/capistrano-mysql-backups-for-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Processing emails with Postfix and Rails</title>
		<link>http://blog.sosedoff.com/2011/08/10/processing-emails-with-postfix-and-rails/</link>
		<comments>http://blog.sosedoff.com/2011/08/10/processing-emails-with-postfix-and-rails/#comments</comments>
		<pubDate>Thu, 11 Aug 2011 00:28:44 +0000</pubDate>
		<dc:creator>Dan Sosedoff</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby Gems]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[mail processing]]></category>
		<category><![CDATA[postfix]]></category>

		<guid isPermaLink="false">http://blog.sosedoff.com/?p=391</guid>
		<description><![CDATA[This is a short manual on how to setup postfix and rails application to receive and process email messages.
Stack:

Debian / Ubuntu Server
Postix
Ruby 1.9
Rails 3.0

Overview
You have an application where users get email notifications. And you want to allow them to reply directly to the email.
In order to do so, each email should have an unique (depends [...]]]></description>
			<content:encoded><![CDATA[<p>This is a short manual on how to setup postfix and rails application to receive and process email messages.</p>
<p>Stack:</p>
<ul>
<li>Debian / Ubuntu Server</li>
<li>Postix</li>
<li>Ruby 1.9</li>
<li>Rails 3.0</li>
</ul>
<h2>Overview</h2>
<p>You have an application where users get email notifications. And you want to allow them to reply directly to the email.<br />
In order to do so, each email should have an unique (depends on situation) reply-to address. Usually its something like that:</p>
<pre><code>P946d272cf7da4dd6b0cb613605bced65@yourdomain.com
</code></pre>
<p>This means that the mailserver you use should support dynamic/virtual email addresses and forwarding.</p>
<h2>Postfix Configuration</h2>
<p>First, you&#8217;ll need to install postfix (in not installed):</p>
<pre><code>apt-get install postfix
</code></pre>
<p>Configuration should look like this:</p>
<pre><code># See /usr/share/postfix/main.cf.dist for a commented, more complete version

default_privs = apps

# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = ap

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=no
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = YOUR_APP_HOSTNAME
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydomain = YOUR_APP_DOMAIN
mydestination = YOUR_APP_DOMAIN, localhost
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
relay_domain = localhost
recipient_canonical_maps = regexp:/etc/postfix/recipient_canonical
</code></pre>
<p>Last option <strong>recipient_canonical_maps</strong> allows you to define a dynamic email addresses and forward them to the specific system mailbox for processing.</p>
<p>Create a file /etc/postfix/recipient_canonical:</p>
<pre><code>/^P[0-9abcdef]{1,}(M[0-9]{1,})?/ apps
</code></pre>
<p>This will add a virtual recipient addresses and forward messages to user apps.</p>
<p><strong>NOTE:</strong> <em>Regular expressions should be in POSIX format</em>. For test you can use <a href="http://www.regextester.com/">regextester.com</a></p>
<h2>Email Aliases</h2>
<p>After you added support for virtual addresses all mail will be delivered to the system user mailbox (apps). But, we need to drive all that traffic into our app. In order to do so we will have to setup mail piping directly into your application script.</p>
<p>Edit /etc/aliases:</p>
<pre><code>apps: "| /home/apps/APP_NAME/current/script/email_receiver_script"
</code></pre>
<p>And rebuild the aliases db by running:</p>
<pre><code>newaliases
</code></pre>
<p>Do not forget to restart postfix:</p>
<pre><code>/etc/init.d/postfix restart
</code></pre>
<p>You can test out the email delivery. For errors check /var/log/mail.info</p>
<h2>Mail Receiver Script</h2>
<p>Since all mail will be forwarded directly to our mail receiver script via piping there are few things to consider:</p>
<ul>
<li>Email receiver should consume as less memory as possible.</li>
<li>Email receiver should not load the whole application (because of item above).</li>
<li>Email receiver should only validate and preprocess incoming messages and leave actual processing to another subsystem via queue.</li>
</ul>
<h3>Configuration</h3>
<p>There are few ruby libraries that are well suited for this case:</p>
<ul>
<li><a href="https://github.com/mikel/mail">mail</a> &#8211; Email processing, ruby 1.9.2 compatible (comparing to tmail which is not)</li>
<li><a href="https://github.com/antirez/redis">redis</a> &#8211; Simple key-value in-memory database.</li>
<li><a href="https://github.com/defunkt/resque">resque</a> &#8211; Redis-backed library for creating background jobs, placing those jobs on multiple queues, and processing them.</li>
</ul>
<p>Install gems:</p>
<pre><code>gem install mail redis resque
</code></pre>
<p>Here is an example email receiver script:</p>
<div class="highlight">
<pre><span class="c1">#!/usr/bin/env ruby</span> 

<span class="nb">require</span> <span class="s1">&#39;rubygems&#39;</span>
<span class="nb">require</span> <span class="s1">&#39;mail&#39;</span>
<span class="nb">require</span> <span class="s1">&#39;redis&#39;</span>
<span class="nb">require</span> <span class="s1">&#39;resque&#39;</span> 

<span class="k">class</span> <span class="nc">EmailReply</span>
  <span class="vi">@queue</span> <span class="o">=</span> <span class="ss">:email_replies</span> 

  <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
    <span class="n">mail</span>    <span class="o">=</span> <span class="no">Mail</span><span class="o">.</span><span class="n">read_from_string</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
    <span class="n">from</span>    <span class="o">=</span> <span class="n">mail</span><span class="o">.</span><span class="n">from</span><span class="o">.</span><span class="n">first</span>
    <span class="n">to</span>      <span class="o">=</span> <span class="n">mail</span><span class="o">.</span><span class="n">to</span><span class="o">.</span><span class="n">first</span> 

    <span class="k">if</span> <span class="n">mail</span><span class="o">.</span><span class="n">multipart?</span>
      <span class="n">part</span> <span class="o">=</span> <span class="n">mail</span><span class="o">.</span><span class="n">parts</span><span class="o">.</span><span class="n">select</span> <span class="p">{</span> <span class="o">|</span><span class="nb">p</span><span class="o">|</span> <span class="nb">p</span><span class="o">.</span><span class="n">content_type</span> <span class="o">=~</span> <span class="sr">/text\/plain/</span> <span class="p">}</span><span class="o">.</span><span class="n">first</span> <span class="k">rescue</span> <span class="kp">nil</span>
      <span class="k">unless</span> <span class="n">part</span><span class="o">.</span><span class="n">nil?</span>
        <span class="n">message</span> <span class="o">=</span> <span class="n">part</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">decoded</span>
      <span class="k">end</span>
    <span class="k">else</span>
      <span class="n">message</span> <span class="o">=</span> <span class="n">part</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">decoded</span>
    <span class="k">end</span> 

    <span class="k">unless</span> <span class="n">message</span><span class="o">.</span><span class="n">nil?</span>
      <span class="no">Resque</span><span class="o">.</span><span class="n">enqueue</span><span class="p">(</span><span class="no">EmailReply</span><span class="p">,</span> <span class="n">from</span><span class="p">,</span> <span class="n">to</span><span class="p">,</span> <span class="n">message</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span> 

<span class="no">EmailReply</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="vg">$stdin</span><span class="o">.</span><span class="n">read</span><span class="p">)</span>
</pre>
</div>
<p>This script receives the mail message then tries to extract the plaintext body. If the email message is valid it adds it to the queue for future processing.</p>
<h2>Mail Queue processing</h2>
<p>After we put emails into the queue we&#8217;ll need to create a worker.</p>
<p>If you need to extract a reply from the body, use (mail_extract)[https://github.com/sosedoff/mail_extract]:</p>
<pre><code>gem install mail_extract
</code></pre>
<p>Simple worker (resque job worker), extracted from one of the projects. (RAILS_ROOT/lib/email_reply.rb):</p>
<div class="highlight">
<pre><span class="k">class</span> <span class="nc">InvalidReplyUUID</span>    <span class="o">&lt;</span> <span class="no">StandardError</span> <span class="p">;</span> <span class="k">end</span>
<span class="k">class</span> <span class="nc">InvalidReplyUser</span>    <span class="o">&lt;</span> <span class="no">StandardError</span> <span class="p">;</span> <span class="k">end</span>
<span class="k">class</span> <span class="nc">InvalidReplyProject</span> <span class="o">&lt;</span> <span class="no">StandardError</span> <span class="p">;</span> <span class="k">end</span>
<span class="k">class</span> <span class="nc">InvalidReplyMessage</span> <span class="o">&lt;</span> <span class="no">StandardError</span> <span class="p">;</span> <span class="k">end</span> 

<span class="k">class</span> <span class="nc">EmailReply</span>
  <span class="vi">@queue</span> <span class="o">=</span> <span class="ss">:email_replies</span> 

  <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">parse_email_uuid</span><span class="p">(</span><span class="n">str</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">str</span> <span class="o">=~</span> <span class="sr">/^P[0-9abcdef]+(M[\d]+)?@/i</span>
      <span class="n">parts</span> <span class="o">=</span> <span class="n">str</span><span class="o">.</span><span class="n">scan</span><span class="p">(</span><span class="sr">/^P([0-9abcdef]+)(M([\d]+))?/</span><span class="p">)</span><span class="o">.</span><span class="n">flatten</span>
      <span class="n">project_uuid</span> <span class="o">=</span> <span class="n">parts</span><span class="o">.</span><span class="n">first</span>
      <span class="n">message_id</span> <span class="o">=</span> <span class="n">parts</span><span class="o">.</span><span class="n">size</span> <span class="o">==</span> <span class="mi">3</span> <span class="o">?</span> <span class="n">parts</span><span class="o">.</span><span class="n">last</span> <span class="p">:</span> <span class="kp">nil</span> 

      <span class="n">result</span> <span class="o">=</span> <span class="p">{</span><span class="ss">:project_uuid</span> <span class="o">=&gt;</span> <span class="n">project_uuid</span><span class="p">}</span>
      <span class="n">result</span><span class="o">[</span><span class="ss">:message_id</span><span class="o">]</span> <span class="o">=</span> <span class="n">message_id</span> <span class="k">unless</span> <span class="n">message_id</span><span class="o">.</span><span class="n">nil?</span>
      <span class="n">result</span>
    <span class="k">else</span>
      <span class="k">raise</span> <span class="no">InvalidReplyUUID</span><span class="p">,</span> <span class="s2">&quot;Invalid UUID: </span><span class="si">#{</span><span class="n">str</span><span class="si">}</span><span class="s2">&quot;</span>
    <span class="k">end</span>
  <span class="k">end</span> 

  <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">perform</span><span class="p">(</span><span class="n">from</span><span class="p">,</span> <span class="n">to</span><span class="p">,</span> <span class="n">body</span><span class="p">)</span>
    <span class="n">user</span> <span class="o">=</span> <span class="no">User</span><span class="o">.</span><span class="n">find_by_email</span><span class="p">(</span><span class="n">from</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">user</span><span class="o">.</span><span class="n">nil?</span>
      <span class="k">raise</span> <span class="no">InvalidReplyUser</span><span class="p">,</span> <span class="s2">&quot;User with email = </span><span class="si">#{</span><span class="n">from</span><span class="si">}</span><span class="s2"> is not a member of the app.&quot;</span>
    <span class="k">end</span> 

    <span class="n">info</span> <span class="o">=</span> <span class="n">parse_email_uuid</span><span class="p">(</span><span class="n">to</span><span class="p">)</span> 

    <span class="n">project</span> <span class="o">=</span> <span class="no">Project</span><span class="o">.</span><span class="n">find_by_uuid</span><span class="p">(</span><span class="n">info</span><span class="o">[</span><span class="ss">:project_uuid</span><span class="o">]</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">project</span><span class="o">.</span><span class="n">nil?</span>
      <span class="k">raise</span> <span class="no">InvalidReplyProject</span><span class="p">,</span> <span class="s2">&quot;Project with UUID = </span><span class="si">#{</span><span class="n">info</span><span class="o">[</span><span class="ss">:project_uuid</span><span class="o">]</span><span class="si">}</span><span class="s2"> was not found.&quot;</span>
    <span class="k">end</span> 

    <span class="k">if</span> <span class="n">info</span><span class="o">.</span><span class="n">key?</span><span class="p">(</span><span class="ss">:message_id</span><span class="p">)</span>
      <span class="n">message</span> <span class="o">=</span> <span class="n">project</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">find_by_id</span><span class="p">(</span><span class="n">info</span><span class="o">[</span><span class="ss">:message_id</span><span class="o">]</span><span class="p">)</span>
      <span class="k">if</span> <span class="n">message</span><span class="o">.</span><span class="n">nil?</span>
        <span class="k">raise</span> <span class="no">InvalidReplyMessage</span><span class="p">,</span> <span class="s2">&quot;Message with ID = </span><span class="si">#{</span><span class="n">info</span><span class="o">[</span><span class="ss">:message_id</span><span class="o">]</span><span class="si">}</span><span class="s2"> was not found on project &#39;</span><span class="si">#{</span><span class="n">project</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">&#39;&quot;</span>
      <span class="k">end</span>
    <span class="k">end</span> 

    <span class="n">params</span> <span class="o">=</span> <span class="p">{</span>
      <span class="ss">:project</span>  <span class="o">=&gt;</span> <span class="n">project</span><span class="p">,</span>
      <span class="ss">:body</span>     <span class="o">=&gt;</span> <span class="no">MailExtract</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">body</span><span class="p">)</span><span class="o">.</span><span class="n">body</span><span class="p">,</span>
      <span class="ss">:markup</span>   <span class="o">=&gt;</span> <span class="s1">&#39;plain&#39;</span><span class="p">,</span>
      <span class="ss">:sent_via</span> <span class="o">=&gt;</span> <span class="s1">&#39;email&#39;</span>
    <span class="p">}</span>
    <span class="n">params</span><span class="o">[</span><span class="ss">:message</span><span class="o">]</span> <span class="o">=</span> <span class="n">message</span> <span class="k">unless</span> <span class="n">message</span><span class="o">.</span><span class="n">nil?</span> 

    <span class="n">message</span> <span class="o">=</span> <span class="n">user</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>
    <span class="k">unless</span> <span class="n">message</span><span class="o">.</span><span class="n">save</span>
      <span class="k">raise</span> <span class="no">RuntimeError</span><span class="p">,</span> <span class="s2">&quot;Unable to save message. Errors: </span><span class="si">#{</span><span class="n">message</span><span class="o">.</span><span class="n">errors</span><span class="o">.</span><span class="n">inspect</span><span class="si">}</span><span class="s2">&quot;</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</pre>
</div>
<p><strong>NOTE:</strong> <em>Its important that both mail receiver and worker are using the same queue.</em></p>
<p>Create a resque.rake in RAILS_ROOT/lib/tasks:</p>
<div class="highlight">
<pre><span class="nb">require</span> <span class="s1">&#39;resque/tasks&#39;</span>
<span class="n">task</span> <span class="s2">&quot;resque:setup&quot;</span> <span class="o">=&gt;</span> <span class="ss">:environment</span>
</pre>
</div>
<p>And fire it up:</p>
<pre><code>rake resque:work QUEUE=email_replies
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.sosedoff.com/2011/08/10/processing-emails-with-postfix-and-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Foreman + Capistrano for Rails 3 applications</title>
		<link>http://blog.sosedoff.com/2011/07/24/foreman-capistrano-for-rails-3-applications/</link>
		<comments>http://blog.sosedoff.com/2011/07/24/foreman-capistrano-for-rails-3-applications/#comments</comments>
		<pubDate>Mon, 25 Jul 2011 03:27:41 +0000</pubDate>
		<dc:creator>Dan Sosedoff</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[foreman]]></category>

		<guid isPermaLink="false">http://blog.sosedoff.com/?p=387</guid>
		<description><![CDATA[Foreman is a Procfile based process spawner.
Source: https://github.com/ddollar/foreman
Installation
gem install foreman

Configuration
Lets assume you have a resque worker, which you execute with rake:
bundle exec rake resque:work QUEUE=* RAILS_ENV=production

Now, you will need to create a Procfile inside your rails root folder (Procfile):
worker: bundle exec rake resque:work QUEUE=* RAILS_ENV=production

Start your workers with foreman:
foreman start


Foreman will start all of the [...]]]></description>
			<content:encoded><![CDATA[<p>Foreman is a Procfile based process spawner.</p>
<p>Source: <a href="https://github.com/ddollar/foreman">https://github.com/ddollar/foreman</a></p>
<h2>Installation</h2>
<pre><code>gem install foreman
</code></pre>
<h2>Configuration</h2>
<p>Lets assume you have a resque worker, which you execute with rake:</p>
<pre><code>bundle exec rake resque:work QUEUE=* RAILS_ENV=production
</code></pre>
<p>Now, you will need to create a Procfile inside your rails root folder (Procfile):</p>
<pre><code>worker: bundle exec rake resque:work QUEUE=* RAILS_ENV=production
</code></pre>
<p>Start your workers with foreman:</p>
<pre><code>foreman start

</code></pre>
<p>Foreman will start all of the processes associated with your app and display stdout and stderr of each process. Processes are color-coded by type to make them easy to read. $PORT will be automatically assigned by foreman and made available to each underlying process.</p>
<h2>Export to system</h2>
<p>While foreman is great for running your application in development, there are some great existing tools for managing processes in production. Foreman can export to either upstart or standard unix init.</p>
<p>Exporting to upstart:</p>
<div class="highlight">
<pre><span class="nv">$ </span>foreman <span class="nb">export </span>upstart /etc/init

<span class="o">[</span>foreman <span class="nb">export</span><span class="o">]</span> writing: /etc/init/testapp.conf
<span class="o">[</span>foreman <span class="nb">export</span><span class="o">]</span> writing: /etc/init/testapp-web.conf
<span class="o">[</span>foreman <span class="nb">export</span><span class="o">]</span> writing: /etc/init/testapp-web-1.conf

<span class="o">[</span>foreman <span class="nb">export</span><span class="o">]</span> writing: /etc/init/testapp-worker.conf
<span class="o">[</span>foreman <span class="nb">export</span><span class="o">]</span> writing: /etc/init/testapp-worker-1.conf
<span class="o">[</span>foreman <span class="nb">export</span><span class="o">]</span> writing: /etc/init/testapp-clock.conf

<span class="o">[</span>foreman <span class="nb">export</span><span class="o">]</span> writing: /etc/init/testapp-clock-1.conf
</pre>
</div>
<h2>Capistrano integration</h2>
<p>Assuming you got your capistrano recipe working, here is a set of foreman tasks:</p>
<div class="highlight">
<pre><span class="c1"># Foreman tasks</span>

<span class="n">namespace</span> <span class="ss">:foreman</span> <span class="k">do</span>
  <span class="n">desc</span> <span class="s1">&#39;Export the Procfile to Ubuntu upstart scripts&#39;</span>
  <span class="n">task</span> <span class="ss">:export</span><span class="p">,</span> <span class="ss">:roles</span> <span class="o">=&gt;</span> <span class="ss">:app</span> <span class="k">do</span>

    <span class="n">run</span> <span class="s2">&quot;cd </span><span class="si">#{</span><span class="n">release_path</span><span class="si">}</span><span class="s2"> &amp;&amp; sudo bundle exec foreman export upstart /etc/init -a </span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2"> -u </span><span class="si">#{</span><span class="n">user</span><span class="si">}</span><span class="s2"> -l </span><span class="si">#{</span><span class="n">release_path</span><span class="si">}</span><span class="s2">/log/foreman&quot;</span>

  <span class="k">end</span>

  <span class="n">desc</span> <span class="s2">&quot;Start the application services&quot;</span>
  <span class="n">task</span> <span class="ss">:start</span><span class="p">,</span> <span class="ss">:roles</span> <span class="o">=&gt;</span> <span class="ss">:app</span> <span class="k">do</span>

    <span class="n">sudo</span> <span class="s2">&quot;start </span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2">&quot;</span>
  <span class="k">end</span>

  <span class="n">desc</span> <span class="s2">&quot;Stop the application services&quot;</span>

  <span class="n">task</span> <span class="ss">:stop</span><span class="p">,</span> <span class="ss">:roles</span> <span class="o">=&gt;</span> <span class="ss">:app</span> <span class="k">do</span>
    <span class="n">sudo</span> <span class="s2">&quot;stop </span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2">&quot;</span>

  <span class="k">end</span>

  <span class="n">desc</span> <span class="s2">&quot;Restart the application services&quot;</span>
  <span class="n">task</span> <span class="ss">:restart</span><span class="p">,</span> <span class="ss">:roles</span> <span class="o">=&gt;</span> <span class="ss">:app</span> <span class="k">do</span>

    <span class="n">run</span> <span class="s2">&quot;sudo start </span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2"> || sudo restart </span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2">&quot;</span>
  <span class="k">end</span>
<span class="k">end</span>
</pre>
</div>
<p>Just add deploy hooks and its ready to go:</p>
<div class="highlight">
<pre><span class="n">after</span> <span class="s2">&quot;deploy:update&quot;</span><span class="p">,</span> <span class="s2">&quot;foreman:export&quot;</span>    <span class="c1"># Export foreman scripts</span>
<span class="n">after</span> <span class="s2">&quot;deploy:update&quot;</span><span class="p">,</span> <span class="s2">&quot;foreman:restart&quot;</span>   <span class="c1"># Restart application scripts</span>
</pre>
</div>
<h2>Documentation</h2>
<ul>
<li>Github repo &#8211; <a href="https://github.com/ddollar/foreman">https://github.com/ddollar/foreman</a></li>
<li>Blog post &#8211; <a href="http://blog.daviddollar.org/2011/05/06/introducing-foreman.html">http://blog.daviddollar.org/2011/05/06/introducing-foreman.html</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.sosedoff.com/2011/07/24/foreman-capistrano-for-rails-3-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Serving maintenance page with Rack Middleware</title>
		<link>http://blog.sosedoff.com/2011/04/09/serving-maintenance-page-with-rack-middleware/</link>
		<comments>http://blog.sosedoff.com/2011/04/09/serving-maintenance-page-with-rack-middleware/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 02:14:17 +0000</pubDate>
		<dc:creator>Dan Sosedoff</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[middleware]]></category>
		<category><![CDATA[rack]]></category>

		<guid isPermaLink="false">http://blog.sosedoff.com/?p=377</guid>
		<description><![CDATA[Its not that important to show message while doing a regular app update, which takes seconds to complete, but when you need to perform some maintenance tasks (tuning, configuration, installation) its better to give users information when its going to be finished. All big websites have their own fancy maintenance page, but for small projects [...]]]></description>
			<content:encoded><![CDATA[<p>Its not that important to show message while doing a regular app update, which takes seconds to complete, but when you need to perform some maintenance tasks (tuning, configuration, installation) its better to give users information when its going to be finished. All big websites have their own fancy maintenance page, but for small projects it does not matter. </p>
<p>Here is a Rack::Maintenance module that provides such functionality:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Rack
  <span style="color:#9966CC; font-weight:bold;">class</span> Maintenance
    <span style="color:#CC00FF; font-weight:bold;">File</span> = ::<span style="color:#CC00FF; font-weight:bold;">File</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>app, dir=<span style="color:#0000FF; font-weight:bold;">nil</span>, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@app</span> = app
      <span style="color:#0066ff; font-weight:bold;">@block</span> = block
      <span style="color:#0066ff; font-weight:bold;">@dir</span> = dir <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#CC00FF; font-weight:bold;">Dir</span>.<span style="color:#9900CC;">pwd</span>
      <span style="color:#0066ff; font-weight:bold;">@file</span> = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">expand_path</span><span style="color:#006600; font-weight:bold;">&#40;</span>@dir<span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#996600;">'.maintenance'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> call<span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>@file<span style="color:#006600; font-weight:bold;">&#41;</span>
        body = <span style="color:#0066ff; font-weight:bold;">@block</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>? ? default_prompt<span style="color:#006600; font-weight:bold;">&#40;</span>time_info<span style="color:#006600; font-weight:bold;">&#41;</span> : <span style="color:#0066ff; font-weight:bold;">@block</span>.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span>time_info<span style="color:#006600; font-weight:bold;">&#41;</span>
        res = Response.<span style="color:#9900CC;">new</span>
        res.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span>body<span style="color:#006600; font-weight:bold;">&#41;</span>
        res.<span style="color:#9900CC;">finish</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        <span style="color:#0066ff; font-weight:bold;">@app</span>.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    private
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> time_info
      t_since, t_until = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF; font-weight:bold;">nil</span>, <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>@file<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span>
        t_since = f.<span style="color:#9900CC;">mtime</span>
        t_until = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>f.<span style="color:#CC0066; font-weight:bold;">gets</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#0000FF; font-weight:bold;">nil</span>
        t_until = <span style="color:#0000FF; font-weight:bold;">nil</span> <span style="color:#9966CC; font-weight:bold;">if</span> t_until.<span style="color:#9900CC;">kind_of</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">Time</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> t_until <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#006600; font-weight:bold;">&#123;</span>:since <span style="color:#006600; font-weight:bold;">=&gt;</span> t_since, <span style="color:#ff3333; font-weight:bold;">:until</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> t_until<span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> default_prompt<span style="color:#006600; font-weight:bold;">&#40;</span>t<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> t<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:until</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>? <span style="color:#008000; font-style:italic;"># no idea when do we end</span>
        msg = <span style="color:#996600;">&quot;We're doing stuff on our servers and will be back shortly.&lt;br/&gt;&lt;br/&gt;&quot;</span>
        msg <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#996600;">&quot;&lt;small&gt;started: #{t[:since]}&lt;/small&gt;&quot;</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        msg = <span style="color:#996600;">&quot;We'll be back online on &lt;b&gt;#{t[:until]}&lt;/b&gt;&quot;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#996600;">&quot;&lt;center&gt;&lt;br/&gt;&lt;br/&gt;&lt;h1&gt;Maintenance.&lt;/h1&gt;&lt;p&gt;#{msg}&lt;/p&gt;&lt;/center&gt;&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3>Usage</h3>
<p>By default middleware will look into current working directory for file with filename &#8220;.maintenance&#8221;.<br />
Request will be passed next if no file found.</p>
<p>Simpliest example:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">use <span style="color:#6666ff; font-weight:bold;">Rack::Maintenance</span></pre></div></div>

<p>Set custom directory:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">use <span style="color:#6666ff; font-weight:bold;">Rack::Maintenance</span>, <span style="color:#996600;">'/path/to/dir'</span></pre></div></div>

<p>Customize default maintenance prompt:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">use <span style="color:#6666ff; font-weight:bold;">Rack::Maintenance</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  <span style="color:#996600;">&quot;We're doing some stuff. Come back later.&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>If you want to use timestamps in your prompt just put a valid time string<br />
into your .maintenance file:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'.maintenance'</span>, <span style="color:#996600;">'w'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">3600</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>and then use it in your prompt:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">use <span style="color:#6666ff; font-weight:bold;">Rack::Maintenance</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#996600;">&quot;We're doing some stuff since #{t[:since} will be done at #{t[:until]}.&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3>Results</h3>
<p><img src="http://blog.sosedoff.com/wp-content/uploads/2011/04/Screen-shot-2011-04-09-at-8.57.40-PM.png" alt="Screen shot 2011-04-09 at 8.57.40 PM" title="Screen shot 2011-04-09 at 8.57.40 PM" width="471" height="188" class="alignnone size-full wp-image-380" /><br />
<br/><br />
<img src="http://blog.sosedoff.com/wp-content/uploads/2011/04/Screen-shot-2011-04-09-at-9.09.46-PM.png" alt="Screen shot 2011-04-09 at 9.09.46 PM" title="Screen shot 2011-04-09 at 9.09.46 PM" width="423" height="118" class="alignnone size-full wp-image-381" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sosedoff.com/2011/04/09/serving-maintenance-page-with-rack-middleware/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Restrict access to all mobile and bot clients with Rack Middleware</title>
		<link>http://blog.sosedoff.com/2011/04/09/restrict-access-to-all-mobile-and-bot-clients-with-rack-middleware/</link>
		<comments>http://blog.sosedoff.com/2011/04/09/restrict-access-to-all-mobile-and-bot-clients-with-rack-middleware/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 01:54:37 +0000</pubDate>
		<dc:creator>Dan Sosedoff</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[middleware]]></category>
		<category><![CDATA[rack]]></category>

		<guid isPermaLink="false">http://blog.sosedoff.com/?p=371</guid>
		<description><![CDATA[Rack middleware is a convenient way to process request before it gets to the application level. Of course, a lot of tasks might be performed within the app, but its not even necessary to do so. Since every ruby web framework is based on rack it makes sense to handle it with middleware. 
Here is [...]]]></description>
			<content:encoded><![CDATA[<p>Rack middleware is a convenient way to process request before it gets to the application level. Of course, a lot of tasks might be performed within the app, but its not even necessary to do so. Since every ruby web framework is based on rack it makes sense to handle it with middleware. </p>
<p>Here is a small module to bounce off all non-desktop clients (mobile devices, crawlers):</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Rack
  <span style="color:#9966CC; font-weight:bold;">class</span> Restrict
    REGEX_MOBILE = <span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#40;</span>blackberry<span style="color:#006600; font-weight:bold;">|</span>motorokr<span style="color:#006600; font-weight:bold;">|</span>motorola<span style="color:#006600; font-weight:bold;">|</span>sony<span style="color:#006600; font-weight:bold;">|</span>windows ce<span style="color:#006600; font-weight:bold;">|</span>240x320<span style="color:#006600; font-weight:bold;">|</span>176x220<span style="color:#006600; font-weight:bold;">|</span>palm<span style="color:#006600; font-weight:bold;">|</span>mobile<span style="color:#006600; font-weight:bold;">|</span>iphone<span style="color:#006600; font-weight:bold;">|</span>ipod<span style="color:#006600; font-weight:bold;">|</span>symbian<span style="color:#006600; font-weight:bold;">|</span>nokia<span style="color:#006600; font-weight:bold;">|</span>samsung<span style="color:#006600; font-weight:bold;">|</span>midp<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">/</span>i
    REGEX_BOTS = <span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#40;</span>google<span style="color:#006600; font-weight:bold;">|</span>yahoo<span style="color:#006600; font-weight:bold;">|</span>baidu<span style="color:#006600; font-weight:bold;">|</span>bot<span style="color:#006600; font-weight:bold;">|</span>webalta<span style="color:#006600; font-weight:bold;">|</span>ia_archiver<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">/</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>app<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@app</span> = app
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> call<span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span>
      str = env<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'HTTP_USER_AGENT'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      restrict = !str.<span style="color:#9900CC;">match</span><span style="color:#006600; font-weight:bold;">&#40;</span>REGEX_MOBILE<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>? <span style="color:#006600; font-weight:bold;">||</span> !str.<span style="color:#9900CC;">match</span><span style="color:#006600; font-weight:bold;">&#40;</span>REGEX_BOTS<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>?
      restrict ? forbidden! : <span style="color:#0066ff; font-weight:bold;">@app</span>.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> forbidden!
      <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">403</span>, <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">'Content-Type'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'text/html'</span>, <span style="color:#996600;">'Content-Length'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'0'</span> <span style="color:#006600; font-weight:bold;">&#125;</span>, <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Usage: (sample config.ru):</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rack'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rack/contrib'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'app.rb'</span>
&nbsp;
use <span style="color:#6666ff; font-weight:bold;">Rack::Restrict</span>
run <span style="color:#6666ff; font-weight:bold;">Sinatra::Application</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.sosedoff.com/2011/04/09/restrict-access-to-all-mobile-and-bot-clients-with-rack-middleware/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

