<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
 
 <title>Gabriele Roselli</title>
 
 <link href="http://gabrieleroselli.com/" />
 <updated>2012-03-21T19:35:03-07:00</updated>
 <id>http://gabrieleroselli.com/blog</id>
 <author>
   <name>Gabriele Roselli</name>
   <email>gabroselli@gmail.com</email>
 </author>
 
 
   <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/GabrieleRoselli" /><feedburner:info uri="gabrieleroselli" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
     <title>Google Map View For Rails App</title>
     <link href="http://feedproxy.google.com/~r/GabrieleRoselli/~3/_Jgvcfs8xA4/Google-Map-View-For-Rails-App.html" />
     <updated>2011-04-06T00:00:00-07:00</updated>
     <id>http://gabrieleroselli.com/2011/04/06/Google-Map-View-For-Rails-App</id>
     <content type="html">&lt;p&gt;I recently built a view for a dynamic google map on a Rails application. Displaying the map then is as simple as dropping an iframe tag with parameters for latitude and longitude in the view. For this post I will be creating a personalized dynamic map for users.&lt;/p&gt;

&lt;p&gt;When a user creates an account the app relies on the &lt;a href='https://github.com/jlecour/geokit-rails3'&gt;geokit-rails3&lt;/a&gt; gem to geocode the user&amp;#8217;s location and store the latitude and longitude in the database.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='lineno'&gt;1&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;User&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
&lt;span class='lineno'&gt;2&lt;/span&gt;  &lt;span class='n'&gt;before_validation&lt;/span&gt; &lt;span class='ss'&gt;:geocode_address&lt;/span&gt;
&lt;span class='lineno'&gt;3&lt;/span&gt;  
&lt;span class='lineno'&gt;4&lt;/span&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;geocode_address&lt;/span&gt;
&lt;span class='lineno'&gt;5&lt;/span&gt;   &lt;span class='n'&gt;geo&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Geokit&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Geocoders&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;MultiGeocoder&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;geocode&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;location&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='lineno'&gt;6&lt;/span&gt;   &lt;span class='n'&gt;errors&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;add&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:address&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Could not Geocode address&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='n'&gt;geo&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;success&lt;/span&gt;
&lt;span class='lineno'&gt;7&lt;/span&gt;   &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lat&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lng&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;zip&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;geo&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lat&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='n'&gt;geo&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lng&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='n'&gt;geo&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;zip&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;geo&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;success&lt;/span&gt;
&lt;span class='lineno'&gt;8&lt;/span&gt;  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;9&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In the maps controller the index action is set to pass the params for latitude and longitude. Also the layout is set to false, so the application layout won&amp;#8217;t show up in the iframe.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='lineno'&gt;1&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;MapsController&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ApplicationController&lt;/span&gt;
&lt;span class='lineno'&gt;2&lt;/span&gt;   &lt;span class='n'&gt;layout&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
&lt;span class='lineno'&gt;3&lt;/span&gt;   &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;index&lt;/span&gt;
&lt;span class='lineno'&gt;4&lt;/span&gt;     &lt;span class='vi'&gt;@lat&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:lat&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
&lt;span class='lineno'&gt;5&lt;/span&gt;     &lt;span class='vi'&gt;@lng&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:lng&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
&lt;span class='lineno'&gt;6&lt;/span&gt;   &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;7&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In order to really understand the code on the map index view reading the &lt;a href='http://code.google.com/apis/maps/documentation/javascript/basics.html'&gt;google maps JavaScript API docs&lt;/a&gt; it&amp;#8217;s a must.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='html'&gt;&lt;span class='lineno'&gt; 1&lt;/span&gt; &lt;span class='nt'&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt; 2&lt;/span&gt;  &lt;span class='nt'&gt;&amp;lt;style &lt;/span&gt;&lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt; 3&lt;/span&gt;   &lt;span class='nt'&gt;html&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='k'&gt;height&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='m'&gt;100&lt;/span&gt;&lt;span class='o'&gt;%&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='lineno'&gt; 4&lt;/span&gt;   &lt;span class='nt'&gt;body&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='k'&gt;height&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='m'&gt;100&lt;/span&gt;&lt;span class='o'&gt;%&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt; &lt;span class='k'&gt;margin&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='m'&gt;0px&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt; &lt;span class='k'&gt;padding&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='m'&gt;0px&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='lineno'&gt; 5&lt;/span&gt;   &lt;span class='nf'&gt;#map_canvas&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='k'&gt;height&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='m'&gt;100&lt;/span&gt;&lt;span class='o'&gt;%&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='lineno'&gt; 6&lt;/span&gt;  &lt;span class='nt'&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt; 7&lt;/span&gt;  &lt;span class='nt'&gt;&amp;lt;script &lt;/span&gt;&lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;src=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;http://maps.google.com/maps/api/js?sensor=true&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt; 8&lt;/span&gt;  &lt;span class='nt'&gt;&amp;lt;script &lt;/span&gt;&lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt; 9&lt;/span&gt;   &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;city&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;google&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;maps&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;LatLng&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='err'&gt;@&lt;/span&gt;&lt;span class='nx'&gt;lat&lt;/span&gt; &lt;span class='o'&gt;-%&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='err'&gt;@&lt;/span&gt;&lt;span class='nx'&gt;lng&lt;/span&gt; &lt;span class='o'&gt;-%&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='lineno'&gt;10&lt;/span&gt;   &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;place&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;google&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;maps&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;LatLng&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='err'&gt;@&lt;/span&gt;&lt;span class='nx'&gt;lat&lt;/span&gt; &lt;span class='o'&gt;-%&amp;gt;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='err'&gt;@&lt;/span&gt;&lt;span class='nx'&gt;lng&lt;/span&gt; &lt;span class='o'&gt;-%&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='lineno'&gt;11&lt;/span&gt;   &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;marker&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='lineno'&gt;12&lt;/span&gt;   &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='lineno'&gt;13&lt;/span&gt;   &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;initialize&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
&lt;span class='lineno'&gt;14&lt;/span&gt;    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;mapOptions&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
&lt;span class='lineno'&gt;15&lt;/span&gt;     &lt;span class='nx'&gt;zoom&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='mi'&gt;15&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
&lt;span class='lineno'&gt;16&lt;/span&gt;     &lt;span class='nx'&gt;mapTypeId&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;google&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;maps&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;MapTypeId&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;ROADMAP&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
&lt;span class='lineno'&gt;17&lt;/span&gt;     &lt;span class='nx'&gt;center&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;city&lt;/span&gt;&lt;span class='p'&gt;};&lt;/span&gt;
&lt;span class='lineno'&gt;18&lt;/span&gt;     &lt;span class='nx'&gt;map&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;google&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;maps&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;getElementById&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;map_canvas&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='nx'&gt;mapOptions&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='lineno'&gt;19&lt;/span&gt;     &lt;span class='nx'&gt;marker&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;google&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;maps&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Marker&lt;/span&gt;&lt;span class='p'&gt;({&lt;/span&gt;
&lt;span class='lineno'&gt;20&lt;/span&gt;     &lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
&lt;span class='lineno'&gt;21&lt;/span&gt;     &lt;span class='nx'&gt;draggable&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='kc'&gt;true&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
&lt;span class='lineno'&gt;22&lt;/span&gt;     &lt;span class='nx'&gt;position&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;place&lt;/span&gt;
&lt;span class='lineno'&gt;23&lt;/span&gt;    &lt;span class='p'&gt;});}&lt;/span&gt;
&lt;span class='lineno'&gt;24&lt;/span&gt;   &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='lineno'&gt;25&lt;/span&gt;  &lt;span class='nt'&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt;26&lt;/span&gt; &lt;span class='nt'&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt;27&lt;/span&gt; &lt;span class='nt'&gt;&amp;lt;body&lt;/span&gt; &lt;span class='na'&gt;onload=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;initialize()&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt;28&lt;/span&gt;   &lt;span class='nt'&gt;&amp;lt;div&lt;/span&gt; &lt;span class='na'&gt;id=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;map_canvas&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt;29&lt;/span&gt; &lt;span class='nt'&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Once the map index view is ready, it can be placed in other views with the code below.&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='html'&gt;&lt;span class='lineno'&gt;1&lt;/span&gt; &lt;span class='nt'&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class='na'&gt;src=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;/map/?lat=&amp;lt;%= @user.lat %&amp;gt;&amp;amp;lng=&amp;lt;%= @user.lng %&amp;gt;&amp;amp;zoom=15&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;width=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;400&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;height=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;400&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;frameborder=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;</content>
   <feedburner:origLink>http://gabrieleroselli.com/2011/04/06/Google-Map-View-For-Rails-App.html</feedburner:origLink></entry>
 
   <entry>
     <title>Rails - Tagging a Model.</title>
     <link href="http://feedproxy.google.com/~r/GabrieleRoselli/~3/tV4cQ24Izaw/Rails_Tagging_a_Model.html" />
     <updated>2011-03-12T00:00:00-08:00</updated>
     <id>http://gabrieleroselli.com/2011/03/12/Rails_Tagging_a_Model</id>
     <content type="html">&lt;p&gt;Tagging is a very simple concept. Wikipedia describes a tag as &amp;#8220;a non-hierarchical keyword or term assigned to a piece of information&amp;#8221;.&lt;/p&gt;

&lt;p&gt;There are few gems out there about tagging such as &lt;a href='https://github.com/mbleigh/acts-as-taggable-on'&gt;acts-as-taggable-on&lt;/a&gt;, &lt;a href='https://github.com/jamesgolick/is_taggable'&gt;is_taggable&lt;/a&gt; and so on. I do value the convenience and power of gems. And if I can I’d rather build my own logic. Mostly because it is the easiest way to deepen my knowledge on the subject.&lt;/p&gt;

&lt;p&gt;If you are dealing only with one model that needs tagging, developing such a system in Rails is quite simple. For this article I will use tagging a blog post as example.&lt;/p&gt;

&lt;p&gt;I usually establish the model associations right away. In this case it’s a many to many association between tags and posts like so:&lt;/p&gt;

&lt;p&gt;In the post model:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='lineno'&gt;1&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Post&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
&lt;span class='lineno'&gt;2&lt;/span&gt;  &lt;span class='n'&gt;has_many&lt;/span&gt; &lt;span class='ss'&gt;:tags&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:through&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:posts_tags&lt;/span&gt;
&lt;span class='lineno'&gt;3&lt;/span&gt;  &lt;span class='n'&gt;has_many&lt;/span&gt; &lt;span class='ss'&gt;:posts_tags&lt;/span&gt; 
&lt;span class='lineno'&gt;4&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In the tag model:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='lineno'&gt;1&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Tag&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
&lt;span class='lineno'&gt;2&lt;/span&gt;  &lt;span class='n'&gt;has_many&lt;/span&gt; &lt;span class='ss'&gt;:posts_tags&lt;/span&gt;
&lt;span class='lineno'&gt;3&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In the join post tag model:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='lineno'&gt;1&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;PostsTag&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
&lt;span class='lineno'&gt;2&lt;/span&gt;  &lt;span class='n'&gt;belongs_to&lt;/span&gt; &lt;span class='ss'&gt;:post&lt;/span&gt; &lt;span class='n'&gt;belongs_to&lt;/span&gt; &lt;span class='ss'&gt;:tag&lt;/span&gt;
&lt;span class='lineno'&gt;3&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Assuming that your post table is already in place, the next step is to generate the migrations to create the tags and the join posts_tags tables.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;$ rails g migration CreateTags
$ rails g migration CreatePostsTags
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='lineno'&gt; 1&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;CreateTags&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Migration&lt;/span&gt;
&lt;span class='lineno'&gt; 2&lt;/span&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nc'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nf'&gt;up&lt;/span&gt; 
&lt;span class='lineno'&gt; 3&lt;/span&gt;   &lt;span class='n'&gt;create_table&lt;/span&gt; &lt;span class='ss'&gt;:tags&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; 
&lt;span class='lineno'&gt; 4&lt;/span&gt;    &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;string&lt;/span&gt; &lt;span class='ss'&gt;:name&lt;/span&gt; 
&lt;span class='lineno'&gt; 5&lt;/span&gt;    &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;timestamps&lt;/span&gt;
&lt;span class='lineno'&gt; 6&lt;/span&gt;   &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt; 7&lt;/span&gt;  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt; 8&lt;/span&gt; 
&lt;span class='lineno'&gt; 9&lt;/span&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nc'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nf'&gt;down&lt;/span&gt;
&lt;span class='lineno'&gt;10&lt;/span&gt;   &lt;span class='n'&gt;drop_table&lt;/span&gt; &lt;span class='ss'&gt;:tags&lt;/span&gt; 
&lt;span class='lineno'&gt;11&lt;/span&gt;  &lt;span class='k'&gt;end&lt;/span&gt; 
&lt;span class='lineno'&gt;12&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='lineno'&gt; 1&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;CreatePostsTags&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Migration&lt;/span&gt;
&lt;span class='lineno'&gt; 2&lt;/span&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nc'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nf'&gt;up&lt;/span&gt;
&lt;span class='lineno'&gt; 3&lt;/span&gt;   &lt;span class='n'&gt;create_table&lt;/span&gt; &lt;span class='ss'&gt;:posts_tags&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; 
&lt;span class='lineno'&gt; 4&lt;/span&gt;   &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;references&lt;/span&gt; &lt;span class='ss'&gt;:post&lt;/span&gt;
&lt;span class='lineno'&gt; 5&lt;/span&gt;   &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;references&lt;/span&gt; &lt;span class='ss'&gt;:tag&lt;/span&gt;
&lt;span class='lineno'&gt; 6&lt;/span&gt;   &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;timestamps&lt;/span&gt;
&lt;span class='lineno'&gt; 7&lt;/span&gt;  &lt;span class='k'&gt;end&lt;/span&gt; 
&lt;span class='lineno'&gt; 8&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt; 9&lt;/span&gt; 
&lt;span class='lineno'&gt;10&lt;/span&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nc'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nf'&gt;down&lt;/span&gt;
&lt;span class='lineno'&gt;11&lt;/span&gt;   &lt;span class='n'&gt;drop_table&lt;/span&gt; &lt;span class='ss'&gt;:posts_tags&lt;/span&gt;
&lt;span class='lineno'&gt;12&lt;/span&gt;  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;13&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Let’s not forget to migrate.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt; $ rake db:migrate
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;After the migration, controller’s actions are next so that we can find, create and associate tags to posts when posts are created or edited.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='lineno'&gt; 1&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;PostsController&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ApplicationController&lt;/span&gt;
&lt;span class='lineno'&gt; 2&lt;/span&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;new&lt;/span&gt;
&lt;span class='lineno'&gt; 3&lt;/span&gt;   &lt;span class='vi'&gt;@post&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;
&lt;span class='lineno'&gt; 4&lt;/span&gt;   &lt;span class='vi'&gt;@tags&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Tag&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;all&lt;/span&gt;
&lt;span class='lineno'&gt; 5&lt;/span&gt; 
&lt;span class='lineno'&gt; 6&lt;/span&gt;   &lt;span class='n'&gt;respond_to&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
&lt;span class='lineno'&gt; 7&lt;/span&gt;    &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;html&lt;/span&gt; &lt;span class='c1'&gt;# new.html.erb&lt;/span&gt;
&lt;span class='lineno'&gt; 8&lt;/span&gt;    &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;xml&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:xml&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vi'&gt;@post&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='lineno'&gt; 9&lt;/span&gt;   &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;10&lt;/span&gt;  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;11&lt;/span&gt; 
&lt;span class='lineno'&gt;12&lt;/span&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;edit&lt;/span&gt;
&lt;span class='lineno'&gt;13&lt;/span&gt;   &lt;span class='vi'&gt;@post&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:id&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='lineno'&gt;14&lt;/span&gt;   &lt;span class='vi'&gt;@tags&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Tag&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;all&lt;/span&gt;
&lt;span class='lineno'&gt;15&lt;/span&gt;  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;16&lt;/span&gt; 
&lt;span class='lineno'&gt;17&lt;/span&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create&lt;/span&gt;
&lt;span class='lineno'&gt;18&lt;/span&gt;   &lt;span class='vi'&gt;@post&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:post&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='lineno'&gt;19&lt;/span&gt;   &lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:tags&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;nil?&lt;/span&gt;
&lt;span class='lineno'&gt;20&lt;/span&gt;    &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:tags&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:tags&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;collect&lt;/span&gt;&lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;tag&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='no'&gt;Tag&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find_or_create_by_name&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;tag&lt;/span&gt;&lt;span class='p'&gt;)}&lt;/span&gt; 
&lt;span class='lineno'&gt;21&lt;/span&gt;   &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;22&lt;/span&gt; 
&lt;span class='lineno'&gt;23&lt;/span&gt;   &lt;span class='n'&gt;respond_to&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
&lt;span class='lineno'&gt;24&lt;/span&gt;    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;save&lt;/span&gt;
&lt;span class='lineno'&gt;25&lt;/span&gt;     &lt;span class='vi'&gt;@post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;create_new_tags&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:new_tags&lt;/span&gt;&lt;span class='o'&gt;][&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:new_tags&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;nil?&lt;/span&gt;
&lt;span class='lineno'&gt;26&lt;/span&gt;     &lt;span class='vi'&gt;@post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;tags&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:tags&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:tags&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='kp'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;?&lt;/span&gt;
&lt;span class='lineno'&gt;27&lt;/span&gt; 
&lt;span class='lineno'&gt;28&lt;/span&gt;     &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;html&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;redirect_to&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='vi'&gt;@post&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:notice&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Post was successfully created.&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='lineno'&gt;29&lt;/span&gt;     &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;xml&lt;/span&gt;  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:xml&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vi'&gt;@post&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:status&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:created&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:location&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vi'&gt;@post&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='lineno'&gt;30&lt;/span&gt;    &lt;span class='k'&gt;else&lt;/span&gt;
&lt;span class='lineno'&gt;31&lt;/span&gt;     &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;html&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;new&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; 
&lt;span class='lineno'&gt;32&lt;/span&gt;     &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;xml&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:xml&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vi'&gt;@post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;errors&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:status&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:unprocessable_entity&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='lineno'&gt;33&lt;/span&gt;    &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;34&lt;/span&gt;   &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;35&lt;/span&gt;  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;36&lt;/span&gt; 
&lt;span class='lineno'&gt;37&lt;/span&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;update&lt;/span&gt;
&lt;span class='lineno'&gt;38&lt;/span&gt;   &lt;span class='vi'&gt;@post&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:id&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='lineno'&gt;39&lt;/span&gt;    &lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:tags&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;nil?&lt;/span&gt;
&lt;span class='lineno'&gt;40&lt;/span&gt;     &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:tags&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:tags&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;collect&lt;/span&gt;&lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;tag&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='no'&gt;Tag&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find_or_create_by_name&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;tag&lt;/span&gt;&lt;span class='p'&gt;)}&lt;/span&gt;
&lt;span class='lineno'&gt;41&lt;/span&gt;    &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;42&lt;/span&gt;   &lt;span class='n'&gt;respond_to&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
&lt;span class='lineno'&gt;43&lt;/span&gt;    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;update_attributes&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:post&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='lineno'&gt;44&lt;/span&gt;     &lt;span class='vi'&gt;@post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;create_new_tags&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:new_tags&lt;/span&gt;&lt;span class='o'&gt;][&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:new_tags&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;nil?&lt;/span&gt;
&lt;span class='lineno'&gt;45&lt;/span&gt;     &lt;span class='vi'&gt;@post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;tags&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:tags&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:tags&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;nil?&lt;/span&gt;
&lt;span class='lineno'&gt;46&lt;/span&gt;     &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;html&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;redirect_to&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;vendors_path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:notice&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Vendor was successfully updated.&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='lineno'&gt;47&lt;/span&gt;     &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;xml&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;head&lt;/span&gt; &lt;span class='ss'&gt;:ok&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='lineno'&gt;48&lt;/span&gt;    &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;html&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;edit&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='lineno'&gt;49&lt;/span&gt;     &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;xml&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:xml&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vi'&gt;@vendor&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;errors&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:status&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:unprocessable_entity&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='lineno'&gt;50&lt;/span&gt;    &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;51&lt;/span&gt;   &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;52&lt;/span&gt;  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;53&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;On line 25 and 45 a “create_new_tags(params[:new_tags])” method is called for @post. This method allows the user the option to create new tags by providing a list of comma separated values. The method in the post model looks like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='lineno'&gt;1&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Post&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
&lt;span class='lineno'&gt;2&lt;/span&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create_new_tags&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;tags&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; 
&lt;span class='lineno'&gt;3&lt;/span&gt;   &lt;span class='n'&gt;new_tags&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;tags&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='sr'&gt;%r{,\s*}&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; 
&lt;span class='lineno'&gt;4&lt;/span&gt;   &lt;span class='n'&gt;new_tags&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;each&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;tag&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
&lt;span class='lineno'&gt;5&lt;/span&gt;    &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;tags&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;create&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:name&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;tag&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='lineno'&gt;6&lt;/span&gt;   &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;7&lt;/span&gt;  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;8&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally the post form view brings the above logic to the surface. The text field starting on line 1 is add new tags as a list of comma separated values. The check boxes assign existing tags to the post.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='lineno'&gt; 1&lt;/span&gt; &lt;span class='x'&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt; 2&lt;/span&gt; &lt;span class='x'&gt; &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;label_tag&lt;/span&gt; &lt;span class='ss'&gt;:tags&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='lineno'&gt; 3&lt;/span&gt; &lt;span class='x'&gt; &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;text_field_tag&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;new_tags[]&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x'&gt; &lt;/span&gt;
&lt;span class='lineno'&gt; 4&lt;/span&gt; &lt;span class='x'&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt; 5&lt;/span&gt; &lt;span class='x'&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt; 6&lt;/span&gt; &lt;span class='x'&gt; &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='vi'&gt;@tags&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;each&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;tag&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='lineno'&gt; 7&lt;/span&gt; &lt;span class='x'&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='lineno'&gt; 8&lt;/span&gt; &lt;span class='x'&gt; &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;check_box_tag&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;tags[]&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;tag&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;name&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='lineno'&gt; 9&lt;/span&gt; &lt;span class='x'&gt; &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;label_tag&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;tag&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;name&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='lineno'&gt;10&lt;/span&gt; &lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And that’s it. You can now tag the post model.&lt;/p&gt;</content>
   <feedburner:origLink>http://gabrieleroselli.com/2011/03/12/Rails_Tagging_a_Model.html</feedburner:origLink></entry>
 
   <entry>
     <title>Using UTC Offset in a Rails app.</title>
     <link href="http://feedproxy.google.com/~r/GabrieleRoselli/~3/2Fix89SuqR8/Using_UTC_Offset_in_a_Rails_App.html" />
     <updated>2011-02-11T00:00:00-08:00</updated>
     <id>http://gabrieleroselli.com/2011/02/11/Using_UTC_Offset_in_a_Rails_App</id>
     <content type="html">&lt;p&gt;Time zone math is no pleasure cruise, especially if, like me, you are new to the matter. Having users scattered all around the globe, apps need to be intelligent enough to be aware of the correct time for each user - particularly when there are scheduled events and notifications that need to be triggered at a specific time for a specific user.&lt;/p&gt;

&lt;p&gt;I pretty much exhausted the internet recently looking for articles about it, and I certainly could have used some more good ones.&lt;/p&gt;

&lt;p&gt;The UTC* offset is without a doubt the one indispensable thing when dealing with time zone calculations, and more specifically the UTC offset expressed in hours. For those not familiar with the concept, the UTC offset is the time offset of a specific time zone from the UTC. In my case I first derived the latitude and longitude from the user&amp;#8217;s address using the &lt;a href='https://github.com/jlecour/geokit-rails3'&gt;geokit-rails3&lt;/a&gt; gem, then I used &lt;a href='http://www.earthtools.org/webservices.htm'&gt;earthtools.org&lt;/a&gt; to get the &lt;span class='cursive'&gt;utc_offset&lt;/span&gt;. I then saved it in the user table.&lt;/p&gt;

&lt;p&gt;In the user model:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='lineno'&gt; 1&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;User&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
&lt;span class='lineno'&gt; 2&lt;/span&gt;   &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;utc_offset&lt;/span&gt;
&lt;span class='lineno'&gt; 3&lt;/span&gt;     &lt;span class='n'&gt;location&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;address&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;, &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;city&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt; &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt; &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;zip&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;
&lt;span class='lineno'&gt; 4&lt;/span&gt;     &lt;span class='n'&gt;geo&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Geokit&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Geocoders&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;MultiGeocoder&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;geocode&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;location&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='lineno'&gt; 5&lt;/span&gt;     &lt;span class='n'&gt;url&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;http://www.earthtools.org/timezone/&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;geo&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lat&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;/&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;geo&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lng&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;
&lt;span class='lineno'&gt; 6&lt;/span&gt;     &lt;span class='n'&gt;response&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;Array&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;HTTParty&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;url&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;parsed_response&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;][&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
&lt;span class='lineno'&gt; 7&lt;/span&gt;     &lt;span class='n'&gt;offset&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;Array&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;response&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;9&lt;/span&gt;&lt;span class='o'&gt;][&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
&lt;span class='lineno'&gt; 8&lt;/span&gt;     &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;update_attributes&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:utc_offset&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;offset&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='lineno'&gt; 9&lt;/span&gt;   &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='lineno'&gt;10&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I picked &lt;a href='http://www.earthtools.org/webservices.htm'&gt;Earthtools.org&lt;/a&gt; because it&amp;#8217;s free, quick and dirty, and I was really eager to dive into the somewhat frustrating subject that is time zone math.&lt;/p&gt;

&lt;p&gt;Rails stores all dates in the database in UTC, so that really helps. Also to avoid any other problems I also set up my app default time to UTC.&lt;/p&gt;

&lt;p&gt;In the config/application.rb:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;time_zone&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;UTC&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, since we are using the &lt;span class='cursive'&gt;DateTime&lt;/span&gt; new_offset method to &amp;#8220;localize&amp;#8221; the date/time needed for our actions, it&amp;#8217;s good practice also to store the dates and time in the database as &lt;span class='cursive'&gt;datetime&lt;/span&gt; data type.&lt;/p&gt;

&lt;p&gt;The &amp;#8220;localization&amp;#8221; happens like so:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='lineno'&gt;1&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;date&lt;/span&gt;
&lt;span class='lineno'&gt;2&lt;/span&gt; &lt;span class='n'&gt;offset&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Rational&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;utc_offset&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='mi'&gt;24&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='lineno'&gt;3&lt;/span&gt; &lt;span class='n'&gt;localize_datetime&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new_offset&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;offset&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;span class='cursive'&gt;new_offset&lt;/span&gt; method creates a new &lt;span class='cursive'&gt;DateTime&lt;/span&gt; object, identical to the current one, except with a new time zone offset (where offset is the new offset from UTC as a fraction of a day). That is why I used Rational to convert the offset into a fraction.&lt;/p&gt;
&lt;span class='cursive'&gt;*UTC (Coordinated Universal Time), differently from GMT (Greenwich Mean Time), is based on atomic time and includes leap seconds as they are added to our clock every so often.&lt;/span&gt;</content>
   <feedburner:origLink>http://gabrieleroselli.com/2011/02/11/Using_UTC_Offset_in_a_Rails_App.html</feedburner:origLink></entry>
 
   <entry>
     <title>Wait, What's the Purpose Here Again?</title>
     <link href="http://feedproxy.google.com/~r/GabrieleRoselli/~3/ccYoB1ZPT-g/Wait_Whats_the_Purpose_Here_Again.html" />
     <updated>2011-01-06T00:00:00-08:00</updated>
     <id>http://gabrieleroselli.com/2011/01/06/Wait_Whats_the_Purpose_Here_Again</id>
     <content type="html">&lt;p&gt;At some point in the summer of 2010 I decided to replace my static website, aimed at marketing my skills as a HTML/CSS/PHP developer and designer, with a blog about my new endeavor: web development in the Ruby world (mostly focused on Rails at the moment). I figured that one of the ways for me to learn more about programming was to write posts about the technologies and the challenges I encounter in my everyday work, therefore the blog.&lt;/p&gt;

&lt;p&gt;Picking up the technology behind it was quite exciting. There are plenty of blog solutions out there, but I really wanted to avoid using a clumsy CMS, and I wanted to be simple. Fortunately &lt;a href='http://tom.preston-werner.com'&gt;Tom Preston-Werner&lt;/a&gt;&amp;#8217;s &lt;a href='https://github.com/mojombo/jekyll'&gt;jekyll&lt;/a&gt;, a very simple blog aware static site generator, came to the rescue. Once I had &lt;a href='https://github.com/mojombo/jekyll'&gt;jekyll&lt;/a&gt; in place all I needed was a design and some content.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve never had a blog before &amp;#8211; I even have a hard time keeping a travel journal (which, according to me, is one of the best things ever) &amp;#8211; so my biggest concern was writing the content. Also I didn&amp;#8217;t mention that I was born and raised in Italy, and, as is the case for most of the folks from the Italian peninsula, my first language is Italian. So writing in English, even if not a challenge, doesn&amp;#8217;t come naturally to me. I quickly found out that content was not scarce. Working as a Ruby and RoR apprentice, everyday I come across perfect topics for articles. All I need to do is take some time to put down reflexions and thoughts.&lt;/p&gt;

&lt;p&gt;Riding the wave of excitement, I decided that if I were to start a blog, it should look really good. But design is not necessarily my forte and I wasn&amp;#8217;t going to hire somebody to do it. So I rolled up my sleeves and started playing with some CSS3 gradients, shadows, feature and so on. Nothing really felt right and I was losing track of my real goal: learning more by producing content.&lt;/p&gt;

&lt;p&gt;On January 5th, 2011 I decided that it was time for me to move on with the project and make something happen. I don&amp;#8217;t believe in New Year&amp;#8217;s resolutions (I believe in resolutions all the time), but the new year started with the idea of making a doer of myself. I have ideas all the time, I start things all the time, but sometimes I get stuck seeking perfection. I was looking for the perfect design, and it wasn&amp;#8217;t anywhere to be found, so I stopped looking for it. Now my blog is far from pretty, but it&amp;#8217;s functional, and that was all that I needed in the first place.&lt;/p&gt;

&lt;p&gt;Ultimately life to me is about the experience; having a beautiful site design is not going to add anything to my experience of writing and learning, so why should I concern myself with it, if it doesn&amp;#8217;t come easily? I know that as I go forth with this project things will come up, designs will come to mind, and they will be shaped around the experience that the content already provides rather than the other way around.&lt;/p&gt;</content>
   <feedburner:origLink>http://gabrieleroselli.com/2011/01/06/Wait_Whats_the_Purpose_Here_Again.html</feedburner:origLink></entry>
 
 
</feed>

