<?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>Darth Sid &#187; Ruby on Rails</title>
	<atom:link href="http://darthsid.com/blog/tag/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://darthsid.com/blog</link>
	<description>&#34;Powered by The Dark Side&#34;</description>
	<lastBuildDate>Tue, 06 Apr 2010 08:48:28 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SSL checklist for Rails Applications</title>
		<link>http://darthsid.com/blog/2010/03/29/ssl-checklist-for-rails-applications/</link>
		<comments>http://darthsid.com/blog/2010/03/29/ssl-checklist-for-rails-applications/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 13:34:39 +0000</pubDate>
		<dc:creator>Sid</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[SSL]]></category>

		<guid isPermaLink="false">http://darthsid.com/blog/?p=126</guid>
		<description><![CDATA[The purpose of SSL is to provide a reasonable level of protection against eavesdropping and man-in-the-middle attacks. Although SSL provides a greater level of security, it introduces a lot of overheads and hence should be used sparingly.  Two of the most common places to use SSL is for payment transactions and user registration/login.
This post [...]]]></description>
			<content:encoded><![CDATA[<p>The purpose of SSL is to provide a reasonable level of protection against eavesdropping and man-in-the-middle attacks. Although SSL provides a greater level of security, it introduces a lot of overheads and hence should be used sparingly.  Two of the most common places to use SSL is for payment transactions and user registration/login.<br />
This post intentionally focuses only on the Rails application as there are numerous post on the net for SSL setup on the server. Enabling SSL in a Rails application is really trivial and there are just a few points that need your attention..<br />
<span id="more-126"></span><br />
<big><big><strong>1. Enabling SSL</strong></big></big><br />
<big>a. Install the <i>ssl_requirment</i> plugin:</big></p>
<pre class="brush: bash;">
./script/plugin install git://github.com/rails/ssl_requirement.git
</pre>
<p><big>b. Include it in your <i>application_controller.rb</i>:</big></p>
<pre class="brush: ruby;">
include SslRequirement
</pre>
<p><big>c. Specify actions that require SSL in their respective controllers. For eg. my session controller has the following line:</big></p>
<pre class="brush: ruby;">
ssl_required  :new, :create
</pre>
<p><big>d. Add the following line in <i>development.rb</i> to bypass SSL in development mode:</big></p>
<pre class="brush: ruby;">
SslRequirement.disable_ssl_check = true
</pre>
<p><big><big><strong>2. Gotcha&#8217;s</strong></big></big><br />
<big>a. Include all submit actions in requirement</big><br />
Any action that processes form data from a SSL page should also be added to the requirement. In the above example, the form on the login page(<i>new</i> action) is processed by the <i>create</i> action and hence it is also included in the requirement.<br />
<big>b. Ajax actions</big><br />
Ajax actions on a SSL page should also use SSL and must be included in the requirement. At times you do not have a body for the Ajax action and it is rendered using it&#8217;s respective RJS template. In such cases create an empty action and include it in the <i>ssl_requirement</i>.<br />
<big>c. Mixed content</big><br />
A lot of browsers show you a &#8220;Mixed Content Warning&#8221; if your SSL page references non-SSL assets. IE displays a scary looking confirmation dialog while Firefox and Chrome show a exclamation in the url bar. Any relative paths(eg. using _path helpers) on the page will automatically use the https protocol but any absolute paths(eg. using _url helper or by manually specifying as a string in link_to) will need to be changed to use https.<br />
<big>d. Asset host issue</big><br />
If you are using Rails asset hosts and do not have a SSL certificate that supports wildcard(for subdomains), then you need to disable them for the SSL pages. Just add the following code to your <i>production.rb</i>:</p>
<pre class="brush: ruby;">
ActionController::Base.asset_host = Proc.new { |source, request|
  if request.ssl?
    "#{request.protocol}#{request.host_with_port}"
  else
    "#{request.protocol}assets%d.yourdomain.com" % (source.hash % 4)
  end
}
</pre>
<p>Replace <i>&#8220;yourdomain&#8221;</i> with your apps domain and <i>&#8220;4&#8243;</i> with the number of asset hosts required.</p>
<p>The above should ensure that you have a proper SSL setup without displaying warnings to the user.</p>
]]></content:encoded>
			<wfw:commentRss>http://darthsid.com/blog/2010/03/29/ssl-checklist-for-rails-applications/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rails Caching And JavaScript Techniques</title>
		<link>http://darthsid.com/blog/2009/08/27/rails-caching-and-javascript-techniques/</link>
		<comments>http://darthsid.com/blog/2009/08/27/rails-caching-and-javascript-techniques/#comments</comments>
		<pubDate>Thu, 27 Aug 2009 10:46:04 +0000</pubDate>
		<dc:creator>Sid</dc:creator>
				<category><![CDATA[Jquery]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Caching]]></category>

		<guid isPermaLink="false">http://darthsid.com/blog/?p=68</guid>
		<description><![CDATA[While implementing caching in a recent rails project I came across some typical caching issues. In a lot of pages the content is same for all users but certain components in them have user specific actions. As an example, I have a page listing all public messages that users have posted(similar to the public timeline [...]]]></description>
			<content:encoded><![CDATA[<p>While implementing caching in a recent rails project I came across some typical caching issues. In a lot of pages the content is same for all users but certain components in them have user specific actions. As an example, I have a page listing all public messages that users have posted(similar to the <a href="http://twitter.com/public_timeline">public timeline</a> in <a href="http://twitter.com">twitter</a>) but actions on those messages are user specific(eg: only owner or admin can delete a message). Also, most of these actions use ajax and the rails <a href="http://ryandaigle.com/articles/2007/9/24/what-s-new-in-edge-rails-better-cross-site-request-forging-prevention">authenticity token</a> in them also gets cached resulting in subsequent failures if the session changes. Another issue was that the timestamps in most pages is fuzzy and they become irrelevant if a page gets cached for too long. I could have created separate caches for each user but if the user base really grows managing the caches would become a nightmare and that would still not solve the authenticity token and the timestamp problem. The simplest solution was to use JavaScript, more specifically <a href="http://jquery.com">jQuery</a>.<br />
<span id="more-68"></span><br />
I have been a big fan of jQuery since I started using it about a year and a half ago and try to use it in all my projects. There is an excellent Rails plugin called <a href="http://ennerchi.com/projects/jrails">jRails</a> that replaces Prototype with jQuery and provides all the default Rails helpers for JavaScript making jQuery even more tempting to use. The examples I use below all use jQuery.</p>
<p><big><big><strong>1. Handling User Specific Components</strong></big></big></p>
<p>Taking the delete action as explained in the example above, the code in the cached view looks something like this:</p>
<pre class="brush: ruby;">
<% if logged_in? %>
<li class="delete <%= 'only_' + (message.owner.login) + '_delete_allowed' %>">
  <%= link_to_remote "Delete",
    :url => user_message_path(current_user, message)
    :method => :delete,
    :confirm => "Are you sure you wish to delete this message?",
    :html => { :title => "Delete Post" } %>
</li>

<% end %>
</pre>
<p>This will create an li element with class &#8220;delete&#8221; and &#8220;only_kratos_delete_allowed&#8221; if the username of the message owner is &#8220;kratos&#8221;</p>
<p>In the non-cached part of the view I have the following code:</p>
<pre class="brush: ruby;">
<% if logged_in? %>
  <% if current_user.is_admin? %>
    <%= javascript_tag "$(document).ready(function() { MessageView.removeInvalidDeteteButtons('only_#{current_user.login}_delete_allowed', 'true'); });" %>
  <% else %>
    <%= javascript_tag "$(document).ready(function() { MessageView.removeInvalidDeteteButtons('only_#{current_user.login}_delete_allowed'); });" %>
  <% end %>
<% end %>
</pre>
<p>If the current user is an admin I pass the JavaScript function an additional parameter.</p>
<p>In the application.js file I have the following code:</p>
<pre class="brush: javascript;">
var MessageView = {
  removeInvalidDeteteButtons: function(element_class, admin) {
    if (admin == undefined)
    {
      $('.delete').each(function() { if (!$(this).hasClass(element_class)) { $(this).remove(); } });
    }
  }
}
</pre>
<p>If the second parameter is passed(in the case of an admin) the function does nothing, else it iterates over all li elements with class &#8220;delete&#8221; and removes all elements that do not also have, in this case, the &#8220;only_kratos_delete_allowed&#8221; class.</p>
<p><big><big><strong>2. Handling Rails Authenticity Token</strong></big></big></p>
<p>This part describes how to take care of the authenticity token problem:</p>
<p>I added the following code to the layout:</p>
<pre class="brush: ruby;">
<%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>
</pre>
<p>This code creates a JavaScript variable named &#8220;AUTH_TOKEN&#8221; that contains the current authentication token. Since this section is not cached it always get the correct token.</p>
<p>Next I added the following code to application.js:</p>
<pre class="brush: javascript;">
$(document).ajaxSend(function(event, request, settings) {
  if (settings.type == 'get' || settings.type == 'GET' || typeof(AUTH_TOKEN) == "undefined") return;
  var authTokenRegExp = /authenticity_token=\w{40}/
  settings.data = settings.data || "";
  if (authTokenRegExp.test(settings.data))
  {
    settings.data=settings.data.replace(authTokenRegExp, "authenticity_token=" + encodeURIComponent(AUTH_TOKEN));
  }
  else
  {
    settings.data += (settings.data ? "&#038;" : "") + "authenticity_token=" + encodeURIComponent(AUTH_TOKEN);
  }
})
</pre>
<p>This code is a slight modification of the code posted <a href="http://henrik.nyh.se/2008/05/rails-authenticity-token-with-jquery">here</a>. <a href="http://docs.jquery.com/Ajax/ajaxSend">ajaxSend</a> is jQuery function that is executed before every ajax request is sent and I use it here to replace or append the authenticity token to the request, unless the request is GET or the AUTH_TOKEN variable is not defined.</p>
<p><big><big><strong>3. Handling Fuzzy Timestamps</strong></big></big></p>
<p>The code for timestamps in the cached view looks like this:</p>
<pre class="brush: ruby;">
<span>
  <%= process_message_body_timestamp(message) %>
</span>
</pre>
<p>And the helper code is:</p>
<pre class="brush: ruby;">
def process_message_body_timestamp(message)
  link_to "#{message.created_at}", show_message_url(message), :class => "timestamps"
end
</pre>
<p>I put the following code in the layout(non-cached):</p>
<pre class="brush: ruby;">
<%= javascript_tag "$(document).ready(function() { CustomDate.datify(#{get_custom_date_arguments}) });" %>
</pre>
<p>The get_custom_date_arguments helper is defined in application helper and returns a string containing the current time arguments needed for the JavaScript function:</p>
<pre class="brush: ruby;">
def get_custom_date_arguments
  current_time = Time.zone.now
  "#{current_time.year},#{current_time.month-1},#{current_time.day},#{current_time.hour},#{current_time.min},#{current_time.sec}"
end
</pre>
<p>I put the following code in application.js:</p>
<pre class="brush: javascript;">
var CustomDate = {
  datify: function(current_utc_year,
                      current_utc_month,
                      current_utc_day,
                      current_utc_hour,
                      current_utc_minute,
                      current_utc_second) {
    $('.timestamps').each(function() {
      $(this).html(CustomDate.humane_date($(this).html(),
                                                current_utc_year,
                                                current_utc_month,
                                                current_utc_day,
                                                current_utc_hour,
                                                current_utc_minute,
                                                current_utc_second)).removeClass('timestamps')
    })
  },

  humane_date: function(date_str, current_utc_year, current_utc_month, current_utc_day, current_utc_hour, current_utc_minute, current_utc_second) {
    var time_formats = [
                        [60, 'less than a minute ago'],
                        [90, '1 minute'], // 60*1.5
                        [3600, 'minutes', 60], // 60*60, 60
                        [5400, '1 hour'], // 60*60*1.5
                        [86400, 'hours', 3600], // 60*60*24, 60*60
                        [129600, '1 day'], // 60*60*24*1.5
                        [604800, 'days', 86400], // 60*60*24*7, 60*60*24
                        [907200, '1 week'], // 60*60*24*7*1.5
                        [2628000, 'weeks', 604800], // 60*60*24*(365/12), 60*60*24*7
                        [3942000, '1 month'], // 60*60*24*(365/12)*1.5
                        [31536000, 'months', 2628000], // 60*60*24*365, 60*60*24*(365/12)
                        [47304000, '1 year'], // 60*60*24*365*1.5
                        [3153600000, 'years', 31536000], // 60*60*24*365*100, 60*60*24*365
                        [4730400000, '1 century'], // 60*60*24*365*100*1.5
                      ];

    var time = ('' + date_str).replace(/-/g,"/").replace(/[TUTC]/g," "),
        dt = new Date

    dt.setUTCFullYear(current_utc_year, current_utc_month, current_utc_day)
    dt.setUTCHours(current_utc_hour, current_utc_minute, current_utc_second)

    var seconds = ((dt - new Date(time) + (dt.getTimezoneOffset() * 60000)) / 1000),
        token = ' ago',
        prepend = '',
        i = 0,
        format;

    if (seconds < 0) {
      seconds = Math.abs(seconds);
      token = '';
      prepend = 'in ';
    }

    while (format = time_formats[i++]) {
      if (seconds < format[0]) {
        if (format.length == 2) {
          return (i>1?prepend:'') + format[1] + (i > 1 ? token : ''); // Conditional so we don't return Just Now Ago
        }
        else {
            return prepend + Math.round(seconds / format[2]) + ' ' + format[1] + (i > 1 ? token : '');
        }
      }
    }

    // overflow for centuries
    if(seconds > 4730400000) {
      return Math.round(seconds / 4730400000) + ' Centuries' + token;
    }

    return date_str;
  }
}
</pre>
<p>The datify function iterates over all timestamps(elements with class &#8220;timestamps&#8221;) and replaces them with fuzzy timestamps. The humane_date function(yanked from <a href="http://stackoverflow.com/questions/168924/how-to-render-contextual-difference-between-two-timestamps-in-javascript">here</a>) generates the actual fuzzy timestamps.</p>
]]></content:encoded>
			<wfw:commentRss>http://darthsid.com/blog/2009/08/27/rails-caching-and-javascript-techniques/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Git Work Flow For Rails Developers</title>
		<link>http://darthsid.com/blog/2009/07/21/git-work-flow-for-rails-developers/</link>
		<comments>http://darthsid.com/blog/2009/07/21/git-work-flow-for-rails-developers/#comments</comments>
		<pubDate>Tue, 21 Jul 2009 12:07:00 +0000</pubDate>
		<dc:creator>Sid</dc:creator>
				<category><![CDATA[Git]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://darthsid.com/blog/?p=29</guid>
		<description><![CDATA[This is my very first blog post and so I though it should be about a tool that is indispensable for me &#8211; Git. I started using git about 10 months ago and looking back I can&#8217;t imagine how I managed to get work done without it. The purpose of this post however is not [...]]]></description>
			<content:encoded><![CDATA[<p>This is my very first blog post and so I though it should be about a tool that is indispensable for me &#8211; Git. I started using git about 10 months ago and looking back I can&#8217;t imagine how I managed to get work done without it. The purpose of this post however is not to sing git&#8217;s praises, there are lots of good articles on the web that do so much better than I ever could. Instead, I wish to share the work-flow I use on my projects. I developed this work-flow by trial and error over the months and is currently the most efficient and productive approach I can think of. If any experienced git users happen to stumble upon this post, please do provide suggestions/alternatives to help me improve my process.</p>
<p>The project I am currently working on requires me to maintain two parallel deployment branches. One is a &#8220;production branch&#8221; which is deployed on the live server and the other is a &#8220;development branch&#8221; which is deployed on a staging server. All enhancements and feature additions are done in the &#8220;development branch&#8221; and the only changes made in the &#8220;production branch&#8221; are production bug fixes that need urgent attention. Once the &#8220;development branch&#8221; is deemed stable it is merged into &#8220;production branch&#8221; and deployed.<br />
<span id="more-29"></span><br />
I&#8217;ve divided my work-flow into two parts. The first part is a generic approach which I follow in all projects, the second part is specific to the case mentioned above and discusses how I manage the two branches using git. Although I mention &#8220;Rails&#8221; in the title of this post, the work-flow I define below is not &#8220;Rails&#8221; specific and can be applied to any project where multiple deployment branches need to be maintained. I assume the reader has a basic understanding of git and is comfortable with git branches. There are lots of configuration settings in git which help you setup things like you git author name, email and colors for git commands etc. There are two I would like to mention here though:</p>
<pre class="brush: bash; gutter: false;">git config --global push.default "tracking"</pre>
<p>This command tells git to perform a push only to the tracked remote branch in which you are currently working.</p>
<pre class="brush: bash; gutter: false;">git config --global pack.threads "0"</pre>
<p>This command tells git to auto-detect the number of threads to use for packing repositories and is useful when working on a machine with more than one core.</p>
<p><big><big><strong>1. Generic Workflow</strong></big></big></p>
<p><strong>a. Start with a clean master branch.</strong></p>
<pre class="brush: bash; gutter: false;">git checkout master
git pull</pre>
<p>You now have a clean master branch. Never work directly in the master branch, instead make all changes to a local branch.</p>
<p><strong>b. Create a local branch.</strong></p>
<pre class="brush: bash; gutter: false;">git branch my_local_branch
git checkout my_local_branch</pre>
<p>or do both in one command:</p>
<pre class="brush: bash; gutter: false;">git checkout -b my_local_branch</pre>
<p>This creates a new local branch named &#8220;my_local_branch&#8221; and switches to it. You can now perform all changes in this branch. One good practice to follow when using git is to commit often and in small chunks. This gives you finer control on the work done and allows you to fix mistakes without losing other work. Once you are satisfied, all those smaller commits can be consolidated in a single meaningful commit.</p>
<p><strong>c. Merge with master branch.</strong></p>
<pre class="brush: bash; gutter: false;">git checkout master
git pull</pre>
<p>if new changes were pulled do the following:</p>
<pre class="brush: bash; gutter: false;">git checkout my_local_branch
git rebase master</pre>
<p>A rebase will apply the newly pulled changes in the master branch to your local branch and then apply local branch changes on top of that. This will ensure a clean merge with master. Conflicts are very common during a rebase and will need to be resolved before you can have a successful rebase. You can also pass the &#8220;-i&#8221; option to rebase to perform an interactive rebase which will alllow you to squash multiple commits into one if you so require. Once you are finished with the rebase do the following:</p>
<pre class="brush: bash; gutter: false;">git checkout master
git merge my_local_branch
git push</pre>
<p>Once you are satisfied with the push you can delete the local branch:</p>
<pre class="brush: bash; gutter: false;">git branch -d my_local_branch</pre>
<p><big><big><strong><br />
2. Managing Multiple Deployment Branches</strong></big></big></p>
<p>The master branch is set as the branch for production deployment and a new remote branch is created for development phase. Since I use capistrano for project deployment I set it up to have three separate tasks: &#8220;production&#8221;, &#8220;production_staging&#8221; and &#8220;development_staging&#8221;. The &#8220;production&#8221; and &#8220;production_staging&#8221; tasks use the master branch and the &#8220;development_staging&#8221; task uses the newly created remote branch. For both the remote branches you must follow the above work-flow i.e: never work directly in the branches themselves, instead create local branches to work in.</p>
<p><strong>a. Create a new remote branch.</strong></p>
<p>First create a new remote branch from our master branch:</p>
<pre class="brush: bash; gutter: false;">git push origin master:refs/heads/development_phase_1</pre>
<p><strong>b. Track the remote branch.</strong></p>
<p>Track the newly created remote branch:</p>
<pre class="brush: bash; gutter: false;">git checkout --track -b development_phase_1 origin/development_phase_1</pre>
<p>This will create a new local branch named &#8220;development_phase_1&#8243; that is tracking the remote &#8220;development_phase_1&#8243; branch. Everyone who needs to work on development branch tracks this remote &#8220;development_phase_1&#8243; branch and pushes to it. The only pushes to master branch are production fixes.</p>
<p><strong>c. Merge the development branch with the master branch.</strong></p>
<p>Once work on development branch is finished we are ready to merge the two branches:</p>
<pre class="brush: bash; gutter: false;">git checkout development_phase_1
git rebase master
git checkout master
git merge development_phase_1
git push
git branch -d development_phase_1
git push origin :heads/development_phase_1</pre>
<p>Normally a rebase is not a good idea in a remotely tracked branch but since our phase is finished and we will create a new remote branch for the next phase, I do so here. Alternatively, I could do a force push for the remote development branch and everyone working on it would need to remove and retrack it again. The second last line removes our locally tracked development branch and the last one removes it from the remote repository.</p>
<p><big><big><strong>Final Thoughts</strong></big></big></p>
<p>As I mentioned before, the above presented work-flow is not perfect by any means but it works for me. I would appreciate feedback from anyone who reads this and has some  suggestions/recommendations to help me manage my projects better.</p>
]]></content:encoded>
			<wfw:commentRss>http://darthsid.com/blog/2009/07/21/git-work-flow-for-rails-developers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
