<?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>BetterExplained &#187; Web</title>
	<atom:link href="http://betterexplained.com/articles/category/web/feed/" rel="self" type="application/rss+xml" />
	<link>http://betterexplained.com</link>
	<description>Learn Right, Not Rote.</description>
	<lastBuildDate>Wed, 16 May 2012 00:45:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>How To Make a Bookmarklet For Your Web Application</title>
		<link>http://betterexplained.com/articles/how-to-make-a-bookmarklet-for-your-web-application/</link>
		<comments>http://betterexplained.com/articles/how-to-make-a-bookmarklet-for-your-web-application/#comments</comments>
		<pubDate>Wed, 16 Apr 2008 18:49:59 +0000</pubDate>
		<dc:creator>kalid</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://betterexplained.com/articles/how-to-make-a-bookmarklet-for-your-web-application/</guid>
		<description><![CDATA[Browser buttons (bookmarklets) are shortcuts that act like a simple browser plugin. Their advantages include:


<ul>
<li><strong>Fast installation</strong>: Just add a link to your bookmarks</li>
<li><strong>Convenient</strong>: Use features while on your current page</li>
<li><strong>Easy to write</strong>: Bookmarklets are </li>&#8230; <a href="http://betterexplained.com/articles/how-to-make-a-bookmarklet-for-your-web-application/" class="read_more">Read article</a></ul>]]></description>
			<content:encoded><![CDATA[<p>Browser buttons (bookmarklets) are shortcuts that act like a simple browser plugin. Their advantages include:</p>


<ul>
<li><strong>Fast installation</strong>: Just add a link to your bookmarks</li>
<li><strong>Convenient</strong>: Use features while on your current page</li>
<li><strong>Easy to write</strong>: Bookmarklets are just like making a webpage; there&#8217;s no need to write a whole browser plugin</li>
<li><strong>Cross-browser</strong>: The same bookmarklet can work in <span class="caps">IE,</span> Firefox, Opera and Safari.</li>
</ul>



<p>Here&#8217;s a few bookmarklets I use regularly:</p>


<ul>
<li><a href="http://code.jalenack.com/delicious/">Delicious buttons</a>: Tag a webpage (useful for browsers that don&#8217;t have the delicious toolbar, like Opera and Firefox 3)</li>
<li><a href="http://www.google.com/translate_tools?hl=en">Google translate</a>: Translate the current page in one click</li>
<li><a href="http://instacalc.com/blog/new-feature-instacalc-bookmarklet">InstaCalc Bookmarklet</a>: Open a real-time calculator on any site</li>
</ul>



<h2>How easy is it?</h2>

<p>Only one way to find out. Try the instacalc bookmarklet right here:</p>

<p> <a href="javascript:(function(){instacalc_script=document.createElement('SCRIPT');instacalc_script.type='text/javascript';instacalc_script.src='http://instacalc.com/gadget/instacalc.bookmarklet.js?x='+(Math.random());document.getElementsByTagName('head')[0].appendChild(instacalc_script);})();"><br />
<img src="http://instacalc.com/blog/wp-content/uploads/images/bookmarklet_full.png" style="border: 0px" /></img></a></p>


<ul>
<li>Click this link: <a href="javascript:(function(){instacalc_script=document.createElement('SCRIPT');instacalc_script.type='text/javascript';instacalc_script.src='http://instacalc.com/gadget/instacalc.bookmarklet.js?x='+(Math.random());document.getElementsByTagName('head')[0].appendChild(instacalc_script);})();"style="border: 2px solid #999; padding: 2px; background: #cacaca; font-weight: bold;" >instacalc bookmarklet</a>.</li>
<li>A calculator opens in the corner of the page. Type 1 + 1 to see the result.</li>
<li>Select this text <b><code>15 mph in fps</code></b> and click the link again. Voila! The text is automatically inserted.</li>
<li>Close the window by clicking the red &#8220;x&#8221;</li>
</ul>



<p>Neat, eh? No install, just click and go. To save the bookmarklet, right click the link and &#8220;add to favorites/bookmarks&#8221;. Now you can open the calculator on any page.</p>

<p>Today we&#8217;ll walk through the anatomy of a bookmarklet, dissect a few, and give you the tools to build your own.</p>

<h2>Bookmarklets 101</h2>

<p>Regular bookmarks (aka favorites) are just locations to visit, like &#8220;http://gmail.com&#8221;. <strong>Bookmarklets are javascript code</strong> that the browser runs on the current page, and they&#8217;re marked by &#8220;javascript:&#8221; instead of &#8220;http://&#8221;.</p>

<p>When clicking a bookmarklet, imagine the page author wrote <code>&lt;script&gt;bookmarklet code here&lt;/script&gt;</code> &#8212; it can do almost anything. There are a few restrictions:</p>


<ul>
<li>Restricted length: Most <span class="caps">URL</span>s have a limit around 2000 characters, which limits the amount of code you can run. There&#8217;s a way around this.</li>
<li>No spaces allowed: Some browsers choke on spaces in a <span class="caps">URL, </span>so yourcodelookslikethis. We have a trick for this too.</li>
</ul>



<p>A simple bookmarklet looks like this:</p>

<p><code>&lt;a href="javascript:alert('hi');"&gt;my link&lt;/a&gt;</code></p>

<p>Click <a href="javascript:alert('hi');">this link</a> to see it in action. This example isn&#8217;t too wild, but the key is that <strong>bookmarklets let you run code on an existing page.</strong></p>

<h2>What do you want to do?</h2>

<p>Your bookmarklet should do something useful. Ideas include:</p>


<ul>
<li><strong>Transform the current page.</strong> Do find/replace, highlight certain words or images, change <span class="caps">CSS </span>styles&#8230;</li>
<li><strong>Open/overlay a new page</strong>. Open a new page or draw a window on the current one, like a sidebar</li>
<li><strong>Send data to another site</strong>. Post, share, or upload the current <span class="caps">URL </span>or selected text (like Google translate).</li>
<li>Look at the <a href="https://www.squarefree.com/bookmarklets/">bookmarklet</a> <a href="http://www.bookmarklets.com/tools/categor.html">directories</a> for more inspiration.</li>
</ul>



<p>People spend most of their time on other sites. Web application authors, think creatively: how can people use your service when away from your site?</p>

<h2>Javascript for Bookmarklets</h2>

<p>A bookmarklet can use any <a href="http://betterexplained.com/articles/the-single-page-javascript-overview/">javascript command</a>, but certain ones are helpful:</p>

<p><strong>Get current page title:</strong>  <code>document.title</code><br />
<strong>Get the current <span class="caps">URL</span></strong>: <code>location.href</code><br />
<strong>Get the currently selected text</strong>:</p>


<pre>
<code>
  // get the currently selected text
  var t;
  try {
    t= ((window.getSelection &amp;&amp; window.getSelection()) ||
(document.getSelection &amp;&amp; document.getSelection()) ||
(document.selection &amp;&amp;
document.selection.createRange &amp;&amp;
document.selection.createRange().text));
  }
  catch(e){ // access denied on https sites
    t = "";
  }
</code>
</pre>



<p><strong>Make text url-safe:</strong> <code>encodeURIComponent(text)</code> (and corresponding <code>decodeURIComponent()</code>). The page title or <span class="caps">URL </span>may have invalid characters (spaces, slashes, etc.) so it&#8217;s a good habit to encode them before sending them over (spaces become %20, etc.).</p>

<h2>Dissecting the Delicious Bookmarklet</h2>

<p>Here&#8217;s the code for the delicious bookmarklet (spaces added for readability):</p>



<pre>
<code>
javascript:location.href='http://del.icio.us/post?v=4;
url='+encodeURIComponent(location.href)+';
title='+encodeURIComponent(document.title)
</code>
</pre>



<p>And here&#8217;s what&#8217;s happening:</p>


<ul>
<li>Change to a new <span class="caps">URL </span>(to post the item)</li>
<li>Specify query parameters for the current document&#8217;s url (location.href) and title (document.title)</li>
<li>Make the paramaters url-safe with encodeURIComponent</li>
</ul>



<p>Once you tag and save the post, delicious sends you to the original page. How do they know where? Because it was sent along in the original request!</p>

<h2>Bookmarklet Interface Ideas</h2>

<p><strong>Imagine this:</strong> Your users are browsing for cat photos (or the journals of the American Chemical Society, but <a href="http://www.alexa.com/data/details/traffic_details/mlb.com?site0=acs.org&amp;%23038;site1=http%3A%2F%2Ficanhascheezburger.com%2F&amp;%23038;y=r&amp;%23038;z=3&amp;%23038;h=300&amp;%23038;w=610&amp;%23038;u%5B%5D=acs.org&amp;%23038;u%5B%5D=http%3A%2F%2Ficanhascheezburger.com%2F&amp;%23038;x=2008-04-16T05%3A53%3A49.000Z&amp;%23038;check=www.alexa.com&amp;%23038;signature=ecukkPnUzH3K0NIAEy25JIBcSyk%3D&amp;%23038;range=3m&amp;%23038;size=Medium">probably lolcats</a>) when they click your killer Web 2.0 bookmarklet. What happens?</p>

<p><img src="http://betterexplained.com/wp-content/uploads/bookmarklet/bookmarklet_interface_ideas.png" alt="Bookmarklet interface ideas" title="Bookmarklet interface ideas" width="500" height="382" border="0" /></p>

<p>Common techniques are:</p>


<ul>
<li><strong>Take the user to a new page.</strong> Hopefully, you can use some data from the current page, otherwise it&#8217;s a regular bookmark.</li>
<li><strong>Frame the current page</strong>, like Google translate or Stumbleupon. This is similar to the first technique, but your site displays the old page inside the window.</li>
<li><strong>Overlay a new interface.</strong> Use <span class="caps">CSS </span><a href="http://www.brunildo.org/test/CPop.html">absolute positioning</a> to make a window in a set place, or <a href="http://divinentd.com/experiments/emulating-position-fixed.html">fixed positioning</a> to have the window follow you as you scroll. Beware the <span class="caps">CSS </span>bugs.</li>
</ul>



<p>Overlaid windows are great, but won&#8217;t that be hard to cram into a single line?</p>

<h2>The Big Trick: Dynamic Javascript</h2>

<p>Direct javascript works fine if you just want to redirect the user to another page, like the delicious bookmarklet. The no spaces, 2000 character limit really hurts when you want a more complicated interface.</p>

<p>There&#8217;s a fix: Our bookmarklet becomes a <strong>stub</strong> to load another (regular) javascript file. Here&#8217;s the code (spaces added for readability):</p>



<pre>
<code>
javascript:(function(){
  _my_script=document.createElement('SCRIPT');
  _my_script.type='text/javascript';
  _my_script.src='http://mysite.com/script.js?';
  document.getElementsByTagName('head')[0].appendChild(_my_script);
})();
</code>
</pre>



<p>Here&#8217;s how it works:</p>


<ul>
<li>Define an anonymous function to download the script</li>
<li>Create a <code>script</code> element, type <code>text/javascript</code>. We can&#8217;t use <code>var _my_script</code> because of the spaces, so choose a unique name.</li>
<li>Set the src of the script to our real javascript file. This file could pull down more javascript also.</li>
<li>Add the <code>script</code> element to the current page</li>
</ul>



<p>And that&#8217;s it! Our bookmarklet can now load any javascript we please, without the annoying restrictions. An added bonus: see how many people are using your tool, and you we can change our script (fix bugs or add features) on the server.</p>

<h2>Dissecting the Instacalc Bookmarklet</h2>

<p>Here&#8217;s the steps I went through to make the instacalc bookmarklet</p>

<p><strong>Create a bookmarklet interface</strong></p>

<p>I made a <a href="http://instacalc.com/gadget/bookmarklet.html">trimmed-down page</a> designed for the bookmarklet. If you click the page it appears fullscreen, but it resizes to the parent container. I planned on hosting this page inside a smaller iframe.</p>

<p><strong>Create a stub bookmarklet</strong></p>

<p>Because I wanted to get the currently selected text and overlay an interface, I knew I couldn&#8217;t fit my javascript into 2000 characters. So I used the dynamic javascript technique above to get the <a href="http://instacalc.com/gadget/instacalc.bookmarklet.js">real javascript file</a>.</p>

<p><strong>Careful caching</strong></p>

<p>I didn&#8217;t want to cache the bookmarklet javascript in case I wanted to change its behavior (but I did cache <a href="http://www.ircache.net/cgi-bin/cacheability.py?query=http%3A%2F%2Finstacalc.com%2Fgadget%2Fbookmarklet.html&amp;%23038;descend=on">the other files</a>). I added a dummy query parameter using <code>Math.random()</code>, which forces the browser to download the file each time. Since the script is small, this wasn&#8217;t too much of an issue.</p>


<pre>
<code>
instacalc_script.src='http://instacalc.com/gadget/instacalc.bookmarklet.js?x='+(Math.random());
</code>
</pre>



<p><strong>Build the interface</strong></p>

<p><a href="http://instacalc.com/gadget/instacalc.bookmarklet.js">The script</a> to build the interface is pretty straightforward. There&#8217;s some helper functions for encoding (instacalc stores data using base64). The script gets the selected text, constructs the <span class="caps">URL </span>for the iframe, and loads it up. It generates the <span class="caps">CSS </span>to have a fixed window on the top right of the screen, and a button to hide the window.</p>

<p>As a slight trick, if the bookmarklet is run again on the same page, it just shows the existing window instead of creating a new iframe.</p>

<h2>Tips &#038; Tricks</h2>

<p>Keep this in mind when making your bookmarklet:</p>

<p><strong>Make it friendly</strong>. Don&#8217;t interrupt the user&#8217;s flow. Bring up the window on the same page, or a new page that closes. If you must redirect the user to their original page.</p>

<p>This is important: the user was nice enough to use your service, so put &#8216;em back where they were!</p>

<p><strong>Make it fast</strong>. After you&#8217;ve got it working, tweak your bookmarklet&#8217;s speed using the following techniques</p>


<ul>
<li><a href="http://betterexplained.com/articles/how-to-optimize-your-site-with-http-caching/">http caching</a></li>
<li><a href="http://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/">gzip compression</a></li>
<li><a href="http://betterexplained.com/articles/speed-up-your-javascript-load-time/">javascript optimization</a></li>
</ul>



<p><strong>Give people instructions</strong>. Bookmarklets aren&#8217;t that common, so help people understand your tool. A few instructions (&#8220;right click this link and add to bookmarks/favorites&#8221;) and a screenshot go a long way.</p>

<p><strong>The gotcha: cross-domain communication</strong></p>

<p>Because of cross-domain security restrictions, your bookmarklets can&#8217;t use fancy-pants Ajax techniques to communicate with your site. The easiest way to communicate is through query parameters in a <span class="caps">URL.</span></p>

<p><strong>Debugging</strong></p>

<p>What&#8217;s programming without bugs? Use <a href="http://betterexplained.com/articles/how-to-debug-web-applications-with-firefox/">firefox to debug</a> your javascript and <span class="caps">CSS.</span> Instead of clicking a bookmarklet each time, just make a page that runs the javascript file directly: <code>&lt;script src="..."&gt;</code>. This is what the bookmarklet does.</p>

<p>Once the dummy page is working, try your bookmarklet on other sites. You&#8217;d be surprised how other <span class="caps">CSS </span>rules can mess up your carefully positioned elements (remember, you&#8217;re running in the context of another site).</p>

<h2>Links &#038; Resources</h2>

<p>I&#8217;m sure you&#8217;ll come up with crazy ways to use your newfound toy. The main benefits are simple installation, compatibility, and being able to interact with the current page.</p>


<ul>
<li>There are <a href="http://ted.mielczarek.org/code/mozilla/bookmarklet.html">crunching tools</a> to make your javascript bookmarklet-friendly. But it&#8217;s nice to just dynamically load the real script and be done with it.</li>
</ul>





<ul>
<li>People have put the <a href="http://ejohn.org/blog/super-fast-delicious-bookmarklet/">delicious bookmarklet on steroids</a>, such as letting you type the tags in the url before hitting the button.</li>
</ul>




<ul>
<li>Taking this to the extreme, <a href="http://www.greasespot.net/">Greasemonkey</a> is a firefox plugin letting you run really powerful scripts. For example, there was a script to add a &#8220;delete&#8221; button to Gmail before it was available.</li>
</ul>




<p>Have fun.</p>]]></content:encoded>
			<wfw:commentRss>http://betterexplained.com/articles/how-to-make-a-bookmarklet-for-your-web-application/feed/</wfw:commentRss>
		<slash:comments>86</slash:comments>
		</item>
		<item>
		<title>Intermediate Rails: Understanding Models, Views and Controllers</title>
		<link>http://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/</link>
		<comments>http://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/#comments</comments>
		<pubDate>Sun, 12 Aug 2007 07:47:05 +0000</pubDate>
		<dc:creator>kalid</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/</guid>
		<description><![CDATA[I&#8217;m glad people liked the <a href="http://betterexplained.com/articles/starting-ruby-on-rails-what-i-wish-i-knew/">introduction to Rails</a>; now you scallawags get to avoid my headaches with the model-view-controller (MVC) pattern. This isn&#8217;t quite an <a href="http://slash7.com/articles/2005/2/22/mvc-the-most-vexing-conundrum">intro&#8230; <a href="http://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/" class="read_more">Read article</a></a> to MVC, it&#8217;s a list of gotchas as you plod through MVC the]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m glad people liked the <a href="http://betterexplained.com/articles/starting-ruby-on-rails-what-i-wish-i-knew/">introduction to Rails</a>; now you scallawags get to avoid my headaches with the model-view-controller (MVC) pattern. This isn&#8217;t quite an <a href="http://slash7.com/articles/2005/2/22/mvc-the-most-vexing-conundrum">intro</a> to <span class="caps">MVC, </span>it&#8217;s a list of gotchas as you plod through <span class="caps">MVC </span>the first few times.</p>

<p>Here&#8217;s the big picture as I understand it:</p>

<p><img src="http://betterexplained.com/wp-content/uploads/rails/mvc-rails.png" alt="mvc.png" title="mvc.png" width="500" height="472" border="0" /></p>


<ul>
<li>The <strong>browser</strong> makes a request, such as http://mysite.com/video/show/15</li>
</ul>




<ul>
<li>The <strong>web server</strong> (mongrel, <span class="caps">WEB</span>rick, etc.) receives the request. It uses <strong>routes</strong> to find out which controller to use: the default route pattern is &#8220;/controller/action/id&#8221; as defined in <code>config/routes.rb</code>. In our case, it&#8217;s the &#8220;video&#8221; controller, method &#8220;show&#8221;, id &#8220;15&#8243;. The web server then uses the <strong>dispatcher</strong> to create a new controller, call the action and pass the parameters.</li>
</ul>




<ul>
<li><strong>Controllers</strong> do the work of parsing user requests, data submissions, cookies, sessions and the &#8220;browser stuff&#8221;. They&#8217;re the pointy-haired manager that orders employees around. <strong>The best controller is Dilbert-esque:</strong> It gives orders without knowing (or caring) how it gets done. In our case, the show method in the video controller knows it needs to lookup a video. It asks the model to get video 15, and will eventually display it to the user.</li>
</ul>




<ul>
<li><strong>Models</strong> are Ruby classes. They talk to the database, store and validate data, perform the business logic and otherwise do the heavy lifting. <strong>They&#8217;re the chubby guy in the back room</strong> crunching the numbers. In this case, the model retrieves video 15 from the database.</li>
</ul>




<ul>
<li><strong>Views</strong> are what the user sees: <span class="caps">HTML, CSS, XML,</span> Javascript, <span class="caps">JSON.</span> They&#8217;re the sales rep putting up flyers and collecting surveys, at the manager&#8217;s direction. <strong>Views are merely puppets</strong> reading what the controller gives them. They don&#8217;t know what happens in the back room. In our example, the controller gives video 15 to the &#8220;show&#8221; view. The show view generates the <span class="caps">HTML</span>: divs, tables, text, descriptions, footers, etc.</li>
</ul>




<ul>
<li>The controller returns the response body (HTML, <span class="caps">XML, </span>etc.) &#038; metadata (caching headers, redirects) to the server. The server combines the raw data into a proper <span class="caps">HTTP </span>response and sends it to the user.</li>
</ul>



<p>It&#8217;s more fun to imagine a story with &#8220;fat model, skinny controller&#8221; instead of a sterile &#8220;3-tiered architecture&#8221;. Models do the grunt work, views are the happy face, and controllers are the masterminds behind it all.</p>

<p>Many <span class="caps">MVC </span>discussions ignore the role of the web server. However, it&#8217;s important to mention <strong>how</strong> the controller magically gets created and passed user information. The web server is the invisible gateway, shuttling data back and forth: users never interact with the controller directly.</p>

<h2>SuperModels</h2>

<p>Models are fat in Railsville: they do the heavy lifting so the controller stays lean, mean, and ignorant of the details. Here&#8217;s a few model tips:</p>

<p><strong>Using ActiveRecord</strong></p>



<pre>
<code>class User &lt; ActiveRecord::Base
end</code>
</pre>



<p>The code <code>&lt; ActiveRecord::Base</code> means your lowly User model inherits from class ActiveRecord::Base, and gets Rails magic to query and save to a database.</p>

<p>Ruby can also handle &#8220;undefined&#8221; methods with ease. ActiveRecord allows methods like &#8220;find_by_login&#8221;, which don&#8217;t actually exist. When you call &#8220;find_by_login&#8221;, Rails handles the &#8220;undefined method&#8221; call and searches for the &#8220;login&#8221; field. Assuming the field is in your database, the model will do a query based on the &#8220;login&#8221; field. There&#8217;s no configuration glue required.</p>

<p><hr class="hr1"/></p>

<p><strong>Defining Class and Instance Methods</strong></p>


<pre>
<code> def self.foo
    "Class method"    # User.foo
  end

  def bar
   "instance method"  # user.bar
  end</code>
</pre>



<p>Class and instance methods can cause confusion.</p>

<p><code>user</code> (lowercase u) is an object, and you call instance methods like <code>user.save</code>.</p>

<p><code>User</code> (capital U) is a class method &#8211; you don&#8217;t need an object to call it (like <code>User.find</code>). ActiveRecord adds both instance and class methods to your model.</p>

<p>As a tip, define class methods like <code>User.find_latest</code> rather than explicitly passing search conditions to <code>User.find</code> (thin controllers are better).</p>

<p><hr class="hr1"/></p>

<p><strong>Using Attributes</strong></p>

<p>Regular Ruby objects can define attributes like this:</p>



<pre>
<code>
  # attribute in regular Ruby
  attr_accessor :name	     # like @name
  def name=(val)             # custom setter method
    @name = val.capitalize   # clean it up before saving
  end

  def name					 # custom getter
   "Dearest " + @name		 # make it nice
  end</code>
</pre>



<p>Here&#8217;s the deal:</p>


<ul>
<li><strong>attr_accessor :name</strong> creates get and set methods (name= and name) on your model. It&#8217;s like having a public instance variable <code>@name</code>.</li>
<li>Define method <code>name=(val)</code> to change how @name is saved (such as validating input).</li>
<li>Define method <code>name</code> to control how the variable is output (such as changing formatting).</li>
</ul>



<p>In Rails, attributes can be <a href="http://theocacao.com/document.page/187">confusing</a> because of the database magic. Here&#8217;s the deal:</p>


<ul>
<li>ActiveRecord grabs the database fields and throws them in an <code>attributes</code> array. It makes default getters and setters, but you need to call <code>user.save</code> to save them.</li>
<li>If you want to <b>override</b> the default getter and setter, use this:</li>
</ul>





<pre>
<code>
    # ActiveRecord: override how we access field
    def length=(minutes)
      self[:length] = minutes * 60
    end

    def length
      self[:length] / 60
    end
</code>
</pre>



<p>ActiveRecord defines a &#8220;<code>[]</code>&#8221; method to access the raw attributes (wraps the write_attribute and read_attribute). This is how you change the raw data. You can&#8217;t redefine length using</p>



<pre>
<code>def length			# this is bad
  length / 60
end
</code></pre>



<p>because it&#8217;s an infinite loop (and that&#8217;s no fun). So <code>self[]</code> it is. This was a particularly frustrating Rails headache of mine &#8211; when in doubt, use <code>self[:field]</code>.</p>

<p><hr class="hr1"/></p>

<p><strong>Never forget you&#8217;re using a database</strong></p>

<p>Rails is clean. So clean, you forget you&#8217;re using a database. Don&#8217;t.</p>

<p><strong>Save your models.</strong> If you make a change, save it. It&#8217;s very easy to forget this critical step. You can also use update_attributes(params) and pass a hash of key -&gt; value pairs.</p>

<p><strong>Reload your models after changes</strong>. Suppose a user <code>has_many</code> videos. You create a new video, point it at the right user, and call user.videos to get a list. Will it work?</p>

<p>Probably not. If you already queried for videos, user.videos may have stale data. You need to call <code>user.reload</code> to get a fresh query. Be careful &#8212; the model in memory acts like a cache that can get stale.</p>

<p><hr class="hr1"/><br />
<strong>Making New Models</strong></p>

<p>There&#8217;s two ways to create new objects:</p>



<pre>
<code>
joe = User.new( :name =&gt; "Sad Joe" )        # not saved
bob = User.create ( :name =&gt; "Happy Bob" )  # saved
</code>
</pre>




<ul>
<li><code>User.new</code> makes a new object, setting attributes with a hash. <code>new</code> <strong>does not save</strong> to the database: you must call <code>user.save</code> explicitly. Method <code>save</code> can fail if the model is not valid.</li>
<li><code>User.create</code> makes a new model and <strong>saves it to the database</strong>. Validation can fail; <code>user.errors</code> is a hash of the fields with errors and the detailed message.</li>
</ul>



<p>Notice how the hash is passed. With Ruby&#8217;s brace magic, <code>{}</code> is not explicitly needed so</p>



<pre><code>user = User.new( :name =&gt; "kalid", :site =&gt; "instacalc.com" )</code></pre>


<p>becomes</p>



<pre><code>User.new( {:name =&gt; "kalid", :site =&gt; "instacalc.com"} )</code></pre>



<p>The arrow (<code>=&gt;</code>) implies that a hash is being passed.</p>

<p><hr class="hr1"/></p>

<p><strong>Using Associations</strong></p>

<p>Quick quiz, hotshot: suppose users have a &#8220;status&#8221;: active, inactive, pensive, etc. What&#8217;s the right association?</p>



<pre>
<code>
class User &lt; ActiveRecord::Base
  belongs_to :status  # this?
  has_one :status     # or this?
end
</code>
</pre>



<p>Hrm. Most likely, you want <code>belongs_to :status</code>. Yeah, it sounds weird. Don&#8217;t think about the phrase &#8220;has_one&#8221; and &#8220;belongs_to&#8221;, consider the meaning:</p>


<ul>
<li>belongs_to: <strong>links_to</strong> another table. Each user references (links to) a status.</li>
<li>has_one: <strong>linked_from</strong> another table. A status is linked_from a user. In fact, statuses don&#8217;t <strong>even know</strong> about users &#8211; there&#8217;s no mention of a &#8220;user&#8221; in the statuses table at all. Inside class Status we&#8217;d write <code>has_many :users</code> (has_one and has_many are the same thing &#8211; has_one only returns 1 object that <strong>links_to</strong> this one).</li>
</ul>



<p>A mnemonic:</p>


<ul>
<li>&#8220;belongs_to&#8221; rhymes with &#8220;links_to&#8221;</li>
<li>&#8220;has_one&#8221; rhymes with &#8220;linked_from&#8221;</li>
</ul>



<p>Well, they sort of rhyme. Work with me here, I&#8217;m trying to help.</p>

<p>These associations actually define methods used to lookup items of the other class. For example, &#8220;user belongs_to status&#8221; means that <code>user.status</code> queries the Status for the proper status_id. Also, &#8220;status has_many :users&#8221; means that <code>status.users</code> queries the user table for everyone with the current <code>status_id</code>. ActiveRecord handles the magic once we declare the relationship.</p>

<p><hr class="hr1"/></p>

<p><strong>Using Custom Associations</strong></p>

<p>Suppose I need <strong>two</strong> statuses, primary and secondary? Use this:</p>



<pre><code>
belongs_to :primary_status, :model =&gt; 'Status', :foreign_key =&gt; 'primary_status_id'
belongs_to :secondary_status, :model =&gt; 'Status', :foreign_key =&gt; 'secondary_status_id'
</code></pre>



<p>You define a new field, and explicitly reference the model and foreign key to use for lookups. For example, user.primary_status returns a Status object with the id of &#8220;primary_status_id&#8221;. Very nice.</p>

<h2>Quick Controllers</h2>

<p>This section is short, because controllers shouldn&#8217;t do much besides boss the model and view around. They typically:</p>


<ul>
<li>Handle things like sessions, logins/authorization, filters, redirection, and errors.</li>
<li>Have default methods (added by ActionController). Visiting <code>http://localhost:3000/user/show</code> will attempt to call the &#8220;show&#8221; action if there is one, or automatically render show.rhtml if the action is not defined.</li>
<li><strong>Pass instance variables like @user get passed to the view</strong>. Local variables (those without @) don&#8217;t get passed.</li>
<li>Are hard to debug. Use <code>render :text =&gt; "Error found" and return</code> to do printf-style debugging in your page. This is another good reason to put code in models, which are easy to debug from the console.</li>
<li>Use sessions to store data between requests: session[:variable] = &#8220;data&#8221;.</li>
</ul>



<p>I&#8217;ll say it again because it&#8217;s burned me before: <strong>use @foo (not &#8220;foo&#8221;) to pass data to the view</strong>.</p>

<h2>Using Views</h2>

<p>Views are straightforward. The basics:</p>


<ul>
<li>Controller actions use views with the same name (method <code>show </code> loads <code>show.rhtml</code> by default)</li>
<li>Controller instance variables (@foo) are available in all views and partials (wow!)</li>
</ul>



<p>Run code in a view using <span class="caps">ERB</span>:</p>


<ul>
<li><code>&lt;% ... %&gt;</code>: Run the code, but don&#8217;t print anything. Used for if/then/else/end and array.each loops. You can comment out sections of <span class="caps">HTML </span>using <% if false %> Hi there <% end %>. You get a free blank line, since you probably have a newline after the closing %&gt;.</li>
</ul>




<ul>
<li><code>&lt;%- ...  %&gt;</code>: Run the code, and don&#8217;t print the trailing newline. Use this when generating <span class="caps">XML </span>or <span class="caps">JSON </span>when breaking up .rhtml code blocks for your readability, but don&#8217;t want newlines in the output.</li>
</ul>




<ul>
<li><code>&lt;%= ... %&gt;</code>: Run the code and print the return value, for example: <%= @foo %> (You did remember the @ sign for controller variables passed to the view, right?). Don&#8217;t put <code>if</code> statements inside the <code>&lt;%=</code>, you&#8217;ll get an error.</li>
</ul>




<ul>
<li><code>&lt;%= h ... %&gt;</code>: Print the code and html escape the output: <code>&gt;</code> becomes <code>&gt;</code>. h() is actually a Ruby function, but called without parens, as Rubyists are apt to do.</li>
</ul>



<p>It&#8217;s a bit confusing when you start out &#8212; run some experiments in a dummy view page.</p>

<h2>Take a breather</h2>

<p>The <span class="caps">MVC </span>pattern is a lot to digest in one sitting. As you become familiar with it, any Rails program becomes easy to dissect: it&#8217;s clear how the pieces fit together. <span class="caps">MVC </span>keeps your code nice and modular, great for debugging and maintenance.</p>

<p>In future articles I&#8217;ll discuss the inner details of <span class="caps">MVC </span>and how Rails forms work (another headache of mine). If you want a jumpstart on the nitty gritty, browse the <a href="http://dev.rubyonrails.org/browser/trunk/">Rails source</a> and try to follow the path of a request:</p>


<ul>
<li><a href="http://dev.rubyonrails.org/browser/trunk/railties/lib/webrick_server.rb"><span class="caps">WEB</span>rick server</a> modified to call the Rails routing library and dispatcher.</li>
<li><a href="http://dev.rubyonrails.org/browser/trunk/railties/lib/dispatcher.rb">Rails Dispatcher</a> actually creates the controller and passes it data.</li>
<li><a href="http://dev.rubyonrails.org/browser/trunk/actionpack/lib/action_controller/base.rb">ActionController Base</a> defines many functions, including those to call a controller action (using appropriate defaults), render text, and return a response.</li>
</ul>



<p>But all in good time my friends &#8212; I&#8217;ll explain it as I understand it. And if you had any forehead-slapping moments with <span class="caps">MVC, </span>drop me a note below.</p>]]></content:encoded>
			<wfw:commentRss>http://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/feed/</wfw:commentRss>
		<slash:comments>65</slash:comments>
		</item>
		<item>
		<title>Build a site you (and your readers) will love</title>
		<link>http://betterexplained.com/articles/build-a-site-you-and-your-readers-will-love/</link>
		<comments>http://betterexplained.com/articles/build-a-site-you-and-your-readers-will-love/#comments</comments>
		<pubDate>Sun, 05 Aug 2007 00:05:48 +0000</pubDate>
		<dc:creator>kalid</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Personal Development]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://betterexplained.com/articles/build-a-site-you-and-your-readers-will-love/</guid>
		<description><![CDATA[I&#8217;m thrilled by the <a href="http://digg.com/programming/Starting_Ruby_on_Rails_What_I_Wish_I_Knew">recent attention</a> and <a href="http://www.stumbleupon.com/url/betterexplained.com/articles/mental-math-shortcuts/">your feedback&#8230; <a href="http://betterexplained.com/articles/build-a-site-you-and-your-readers-will-love/" class="read_more">Read article</a></a>. Seeing your &#8220;Aha!&#8221; moments motivates me to write &#8212; though I&#8217;ve been neglectful lately. I&#8217;m busy, the dog ate my browser, the draft&#8217;s in the email&#8230; you know the drill.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m thrilled by the <a href="http://digg.com/programming/Starting_Ruby_on_Rails_What_I_Wish_I_Knew">recent attention</a> and <a href="http://www.stumbleupon.com/url/betterexplained.com/articles/mental-math-shortcuts/">your feedback</a>. Seeing your &#8220;Aha!&#8221; moments motivates me to write &#8212; though I&#8217;ve been neglectful lately. I&#8217;m busy, the dog ate my browser, the draft&#8217;s in the email&#8230; you know the drill. If you need an explanation fix, check out my old site from college:</p>

<p><a href="http://www.cs.princeton.edu/~kazad/resources.htm">http://www.cs.princeton.edu/~kazad/resources.htm</a></p>

<p>It has many posts I&#8217;ll be revising and importing over time.</p>

<p>This post is for betterexplained newcomers and old-timers: the how and why of the site. If you like my approach, it&#8217;s a guide to writing. Otherwise it&#8217;s your own list of advice to avoid.</p>

<h2>Find your purpose</h2>

<p>Blogging is introspective. I&#8217;ve realized my interests <a href="http://betterexplained.com/articles/surviving-and-thriving-on-your-own-know-thyself/">after much thought</a>:</p>


<ul>
<li>I like math, writing, computers, business, personal development, communication, and learning.</li>
<li><strong>I cringe when ideas are explained poorly.</strong> Jargon and complicated explanations discourage the beginner. It shows you don&#8217;t really know the material. I get upset thinking that a poor explanation may turn someone away from a field forever, and want to fix that.</li>
<li><strong>I have many beliefs about education</strong>. Insight beats memorization. Any subject (anything!) can be explained simply if you understand it well enough. Curiosity and passion are enough to conquer a subject.</li>
</ul>



I&#8217;ve always wanted to share hard-won ideas and save other people mental anguish &#8212; BetterExplained has been a nagging thought in my mind. Today it&#8217;s alive with a purpose:<br />
<blockquote>
To explain topics clearly, intuitively, and share the &#8220;a-ha!&#8221; moments that make learning fun. Any subject can be better explained; today it&#8217;s just me writing, but I want to catalog insights from everyone.<br />
</blockquote>

<p>This vision excites me &#8212; find the one that motivates you.</p>

<h2>Be yourself (it&#8217;s harder than you think)</h2>

<p>Writing naturally is hard. When you put pen to paper, fingers to keyboard, or stand before an audience, you stiffen. You get self conscious. You don&#8217;t act like yourself.</p>

<p>Fortunately this feeling <a href="http://instacalc.com/blog/instacalc-in-the-real-world">disappears with practice</a>. You stop pontificating; you explain. You don&#8217;t &#8220;write an article&#8221;; you have a conversation. You use humor, stories, and personal examples instead of abstract generalities. You write even if people won&#8217;t agree with everything you say.</p>

<p>Use your talents in whatever combination you can.</p>

<blockquote>
But if you want something extraordinary, you have two paths:

<p>1. Become the best at one specific thing.<br />
2. Become very good (top 25%) at two or more things.</p>

&#8211; <a href="http://dilbertblog.typepad.com/the_dilbert_blog/2007/07/career-advice.html">Scott Adams</a><br />
</blockquote>

<p>I feel my greatest talents are being curious, having enthusiasm and wanting things to be simple. I&#8217;m no expert. But I&#8217;m going to learn what I can and share it in the most intuitive way possible. Someone I admire feels similarly:</p>

<blockquote>
I have no special talents. I am only passionately curious.<br />
&#8211;Albert Einstein<br />
</blockquote>

<h2>Write what you know; link what you don&#8217;t</h2>

<p>You may not be an expert (I&#8217;m not), but you&#8217;ve collected nuggets of information and personal insights that nobody else has. Share them in your own style.</p>

<p>Then link to wikipedia, delicious, and the detailed articles so readers can learn the nitty gritty. Eventually you&#8217;ll learn the nitty gritty too, have your own insights, and simplify them into a new article.</p>

<h2>Write well</h2>

<p>Writing well is hard. Really hard. My definition means:</p>


<ul>
<li><strong>Timeless content</strong> that is still relevant in a year.</li>
<li><strong>Original thought and deep insights</strong> that aren&#8217;t immediately obvious. If sharing details, organize them in a clever way.</li>
<li><strong>Fun to read</strong>. Write for people. Use humor, quotes, stories. Remember: I&#8217;m Kalid, you&#8217;re you, and we&#8217;re having a conversation. This is no textbook.</li>
<li><strong>Succinct, clear, and organized.</strong> I want to pump ideas into your head as fast as possible (I hope you don&#8217;t mind). Fewer words = faster intake = happier user.</li>
</ul>



<p>That&#8217;s the goal, not that I always reach it.</p>

<p>Why write quality, not quantity? In my experience, an outstanding post trumps a dozen average ones. Top posts create traffic, links, diggs, and get people talking. You receive emails and comments which make your day and motivate you to write more, and better. Sub-par posts dilute your site and waste time.</p>

<p>Astound visitors with the quality of your content. Define your own quality bar and run towards it. Be merciless when revising. Don&#8217;t be afraid to fix up old posts &#8212; streamlining previous articles is good practice.</p>

<h2>Just write</h2>

<p>Blogging has no holy book. This is a non-fiction site about math and programming topics; a poetry blog has different goals. I don&#8217;t know your goals, so just write and push your own bar. You can be top-quality in your field.</p>


<p>I think I have above-average interest in math, science, simplicity, education, curiosity, and passion. The combination lead to my style and the focus of this site. I&#8217;m thrilled that others seem to like it too. Find your style; someone will like it.</p>

<h2>Pace yourself</h2>

<p>Writing on a consistent schedule is hard &#8212; if you&#8217;ve mastered the secret, let me know. I have dozens of posts in various draft forms, and it seems I need a Herculean effort to go back and revise them. Some posts stream out of my head and I&#8217;m done in a few hours. Others weigh over me for days or weeks, requiring a flurry of energy to finish and clean up.</p>

<p>I suggest an &#8220;articles&#8221; folder to collect your thoughts, in whatever stage. Sometimes you just have a sentence or two, but it can grow into a whole post over time.</p>

<p>I&#8217;ve learned writing isn&#8217;t all fun, even on topics you enjoy. Editing can be painful &#8212; push yourself through.</p>

<h2>Keep learning</h2>

<p>My opinions were shaped by these authors:</p>


<ul>
<li><a href="http://steve.yegge.googlepages.com/you-should-write-blogs">Steve Yegge</a></li>
<li><a href="http://www.problogger.net/archives/2007/07/13/how-to-write-excellent-blog-content-what-we-wish-we-knew/">Darren Rowse</a></li>
<li><a href="http://www.paulgraham.com/writing44.html">Paul Graham</a></li>
<li><a href="http://www.stevepavlina.com/blog/2006/01/how-to-build-a-high-traffic-web-site-or-blog/">Steve Pavlina</a></li>
<li><a href="http://www.writingclasses.com/InformationPages/index.php/PageID/300">George Orwell&#8217;s Tips</a></li>
<li><a href="http://www.amazon.com/Elements-Style-Fourth-William-Strunk/dp/020530902X">Elements of Style</a> (<a href="http://www.crockford.com/wrrrld/style.html">read online</a>) by Strunk and White</li>
<li><a href="http://www.amazon.com/Writing-Well-25th-Anniversary-Nonfiction/dp/0060006641">On Writing Well</a> by White&#8217;s mentee, William Zinsser.</li>
</ul>



<p>Good luck in your writing. Now that you know my passions, I&#8217;m interested in what <strong>you</strong> care about. Drop me a note anytime.</p>]]></content:encoded>
			<wfw:commentRss>http://betterexplained.com/articles/build-a-site-you-and-your-readers-will-love/feed/</wfw:commentRss>
		<slash:comments>37</slash:comments>
		</item>
		<item>
		<title>Starting Ruby on Rails: What I Wish I Knew</title>
		<link>http://betterexplained.com/articles/starting-ruby-on-rails-what-i-wish-i-knew/</link>
		<comments>http://betterexplained.com/articles/starting-ruby-on-rails-what-i-wish-i-knew/#comments</comments>
		<pubDate>Sun, 17 Jun 2007 04:10:58 +0000</pubDate>
		<dc:creator>kalid</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://betterexplained.com/articles/starting-ruby-on-rails-what-i-wish-i-knew/</guid>
		<description><![CDATA[<a href="http://rubyonrails.com">Ruby on Rails</a> is an elegant, compact and fun way to build web applications. Unfortunately, many gotchas await the new programmer. Now that I have a few <a href="http://instacalc.com">rails projects&#8230; <a href="http://betterexplained.com/articles/starting-ruby-on-rails-what-i-wish-i-knew/" class="read_more">Read article</a></a> under my belt, here&#8217;s my shot at sparing you the suffering]]></description>
			<content:encoded><![CDATA[<p><a href="http://rubyonrails.com">Ruby on Rails</a> is an elegant, compact and fun way to build web applications. Unfortunately, many gotchas await the new programmer. Now that I have a few <a href="http://instacalc.com">rails projects</a> under my belt, here&#8217;s my shot at sparing you the suffering I experienced when first getting started.</p>

<h2>Tools: Just Get Them</h2>

<p>Here&#8217;s the tools you&#8217;ll need. Don&#8217;t read endless reviews trying to decide on the best one; start somewhere and get going.</p>


<ul>
<li><a href="http://www.pragmaticprogrammer.com/titles/rails/">Agile Web Development with Rails</a>. Yes, it&#8217;s a book. And a cohesive book is worth 100 hobbled-together <a href="http://wiki.rubyonrails.com/rails">online tutorials</a>.</li>
<li><a href="http://rubyforge.org/projects/instantrails/">InstantRails</a>: A .zip file containing Ruby, Apache, MySQL and <span class="caps">PHP </span>(for PhpMyAdmin), packaged and ready to go.</li>
<li><a href="http://www.aptana.com">Aptana/RadRails</a> (like Eclipse) or <a href="http://www.sapphiresteel.com/">Ruby In Steel</a> (like Visual Studio) for editing code.</li>
<li><a href="http://subversion.tigris.org" title="command-line">Subversion</a> and/or <a href="http://tortoisesvn.net/downloads" title="Windows GUI">TortoiseSVN</a> for source control.</li>
<li>Browse popular ruby on rails links on <a href="http://del.icio.us/popular/rubyonrails">del.icio.us</a>, <a href="http://railsbrain.com">Rails documentation</a> and <a href="http://docs.huihoo.com/ruby/ruby-man-1.4/syntax.html">Ruby syntax &#038; examples</a>.</li>
</ul>



<h2>But What Does It All Mean?</h2>

<p>&#8220;Ruby on Rails&#8221; is catchy but confusing. Is Rails some type of magical drug that Ruby is on? (Depending on who you ask, yes.)</p>

<p><strong>Ruby</strong> is a programming language, similar to Python and Perl. It is dynamically typed (no need for &#8220;int i&#8221;), interpreted, and can be modified at runtime (such as adding new methods to classes). It has dozens of shortcuts that make it very clean; methods are rarely over 10 lines. It has good RegEx support and works well for shell scripting.</p>

<p><strong>Rails</strong> is a <a href="http://rubygems.org/read/book/1">gem</a>, or a Ruby library. Some gems let you use the Win32 <span class="caps">API.</span> Others handle networking. Rails helps make web applications, providing classes for saving to the database, handling <span class="caps">URL</span>s and displaying html (along with a webserver, maintenance tasks, a debugging console and much more).</p>

<p><strong><span class="caps">IRB</span></strong> is the interactive Ruby console (type &#8220;irb&#8221; to use). Rails has a special <span class="caps">IRB </span>console to access your web app as it is running (excellent for live debugging).</p>

<p><strong>Rake</strong> is Ruby&#8217;s version of Make. Define and run maintenance tasks like setting up databases, reloading data, backing up, or even deploying an app to your website.</p>

<p><strong>Erb</strong> is embedded Ruby, which is like <span class="caps">PHP.</span> It lets you mix Ruby with <span class="caps">HTML </span>(for example):</p>



<pre>
<code>&lt;div&gt;Hello there, &lt;%= get_user_name() %&gt;&lt;/div&gt;</code>
</pre>



<p><strong><span class="caps">YAML </span>(or <span class="caps">YML</span>)</strong> means &#8220;YAML Ain&#8217;t a Markup Language&#8221; &#8212; it&#8217;s a simple way to <a href="http://en.wikipedia.org/wiki/YAML">specify data</a>:</p>



<pre>
<code>{name: John Smith, age: 33}</code>
</pre>



<p>It&#8217;s like <span class="caps">JSON, </span>much leaner than <span class="caps">XML, </span>and used by Rails for setting configuration options (like setting the database name and password).</p>

<p>Phew! Once Ruby is installed and in your path, you can add the rails gem using:</p>



<pre>
<code>
gem install rails
</code>
</pre>



<p>In general, use gem install &#8220;gem_name&#8221;, which searches online sources for that library. Although Rails is &#8220;just another gem&#8221;, it is the killer library that brought Ruby into the limelight.</p>

<h2>Understanding Ruby-Isms</h2>

<p>It&#8217;s daunting to learn a new library and a new language at the same time. Here are some of the biggest Ruby gotchas for those with a C/C++/Java background.</p>

<p><strong>Ruby removes unnecessary cruft: (){};</strong></p>


<ul>
<li>Parenthesis on method calls are optional; use <code>print "hi"</code>.</li>
<li>Semicolons aren&#8217;t needed after each line (crazy, I know).</li>
<li>Use &#8220;if then else end&#8221; rather than braces.</li>
<li>Parens aren&#8217;t needed around the conditions in if-then statements.</li>
<li>Methods automatically return the last line (call <code>return</code> explicitly if needed)</li>
</ul>



<p>Ruby scraps the annoying, ubiquitous punctuation that distracts from the program logic. Why put parens ((around),(everything))? Again, if you want parens, put &#8216;em in there. But you&#8217;ll take off the training wheels soon enough.</p>

<p>The line noise (er, &#8220;punctuation&#8221;) we use in C and Java is for the compiler&#8217;s benefit, not ours. Be warned: after weeks with Ruby, other languages become a bit painful to read.</p>



<pre>
<code>
def greet(name)              # simple method
   "Hello, " + name          # returned automatically
end

greet "world"                # ==&gt; "Hello, world"
</code>
</pre>



<p><strong>Those Funny Ruby Variables</strong></p>


<ul>
<li><code>x = 3</code> is a local variable for a method or block (gone when the method is done)</li>
<li><code>@x = 3</code> is a instance variable owned by each object (it sticks around)</li>
<li><code>@@x = 3</code> is a class variable shared by all objects (it sticks around, too).</li>
<li><code>:hello</code> is a symbol, like a constant string. Useful for indexing hashes. Speaking of which&#8230;</li>
<li><code>dictionary = { :cat =&gt; "Goes meow", :dog =&gt; "Barks loud."}</code> is a hash of key/value pairs. Access elements with dictionary[:cat].</li>
</ul>



<p><strong>Those Funny Ruby Assignments</strong></p>

<p>Ruby has the <code>||</code> operator which is a bit funky. When put in a chain</p>



<pre>
<code>x = a || b || c || "default"</code>
</pre>



<p>it means &#8220;test each value and return the first that&#8217;s not false.&#8221; So if a is false, it tries b. If b is false, it tries c. Otherwise, it returns the string &#8220;default&#8221;.</p>

<p>If you write <code>x = x || "default"</code> it means &#8220;set x to itself (if it has a value), otherwise use the default.&#8221; An easier way to write this is</p>

<p><code>x ||= "default"</code></p>

<p>which means the same: set x to the default value unless it has some other value. You&#8217;ll see this a lot in Ruby programs.</p>

<p><strong>Those Funny Ruby Blocks</strong></p>

<p>Ruby has &#8220;blocks&#8221;, which are like anonymous functions passed to a loop or another function. These blocks can specify a parameter using |param| and then take actions, call functions of their own, and so on. Blocks are useful when applying some function to each element of an array. It helps to think of them as a type of anonymous function that can, but doesn&#8217;t have to, take a parameter.</p>



<pre>
<code>
3.times do |i|
   print i*i
end
</code>
</pre>



<p>In this example, the numbers 0,1 and 2 are passed to a block (do&#8230; end) that takes a single parameter (i) and prints i squared. The output would be 0, followed by 1 followed by 4 (and looks like &#8220;014&#8243; since we didn&#8217;t include spaces). Blocks are common in Ruby but take some getting used to, so be forewarned.</p>

<p>These are the Ruby lessons that were tricky when starting out. Try <a href="http://qa.poignantguide.net/">Why&#8217;s Poignant Guide To Ruby</a> for more info (&#8220;Why&#8221; is the name of the author&#8230; it confused me too).</p>

<h2>Understanding Rails-isms</h2>

<p>Rails has its own peculiarities. &#8220;Trust us, it&#8217;s good for you.&#8221; say the programmers. It&#8217;s true &#8211; the features/quirks make Rails stand out, but they&#8217;re confusing until they click. Remember:</p>


<ul>
<li><strong>Class and table names are important.</strong> Rails has certain naming conventions; it expects objects from the class <code>Person</code> to be saved to a database table named <code>people</code>. Yes, Rails has a <strong>pluralization engine</strong> to figure out what object maps to what table (<a href="http://nubyonrails.com/tools/pluralize">I kid you not</a>).  This magic is great, but scary at first when you&#8217;re not sure how classes and tables are getting linked together.</li>
<li>Many methods take an &#8220;options&#8221; hash as a parameter, rather than having dozens of individual parameters. When you see</li>
</ul>





<pre>
<code>
link_to "View Post", :action =&gt; 'show', :controller =&gt; 'article', :id =&gt; @article
</code>
</pre>



<p>The call is really doing this:</p>



<pre>
<code>
link_to("View Post", {:action =&gt; 'show', :controller =&gt; 'article', :id =&gt; @article})
</code>
</pre>



<p>There are only two parameters: the name (&#8220;View Post&#8221;) and a hash with 3 key/value pairs. Ruby lets us remove the extra parens and braces, leaving the stripped-down function call above.</p>

<h2>Understanding The Model-View-Controller Pattern</h2>

<p>Rails is built around the <a href="http://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/">model-view-controller</a> pattern. It&#8217;s a simple concept: separate the data, logic, and display layers of your program. This lets you split functionality cleanly, just like having separate <span class="caps">HTML, CSS </span>and Javascript files prevents your code from mushing together. Here&#8217;s the <span class="caps">MVC </span>breakdown:</p>


<ul>
<li><strong>Models</strong> are classes that talk to the databse. You find, create and save models, so you don&#8217;t (usually) have to write <span class="caps">SQL.</span> Rails has a class to handle the magic of saving to a database when a model is updated.</li>
<li><strong>Controllers</strong> take user input (like a <span class="caps">URL</span>) and decide what to do (show a page, order an item, post a comment). They may initially have business logic, like finding the right models or changing data. As your rails ninjitsu improves, constantly refactor and move business logic into the model (<a href="http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model">fat model, skinny controller</a>). Ideally, controllers just take inputs, call model methods, and pass outputs to the view (including error messages).</li>
<li><strong>Views</strong> display the output, usually <span class="caps">HTML.</span> They use <span class="caps">ERB </span>and this part of Rails is like <span class="caps">PHP </span>- you use <span class="caps">HTML </span>templates with some Ruby variables thrown in. Rails also makes it easy to create views as <span class="caps">XML </span>(for web services/RSS feeds) or <span class="caps">JSON </span>(for <span class="caps">AJAX </span>calls).</li>
</ul>



<p>The <span class="caps">MVC </span>pattern is key to building a readable, maintainable and easily-updateable web app.</p>

<h2>Understanding Rails&#8217; Directory Structure</h2>

<p>When you create your first rails app, the directories are laid out for you. The structure is well-organized: Models are in app/models, controllers in app/controllers, and views in app/my_local_views (just kidding).</p>

<p>The naming conventions are important &#8211; it lets rails applications &#8220;find their parts&#8221; easily, without additional configuration. Also, it&#8217;s very easy for another programmer to understand and learn from any rails app. I can take a look at Typo, the rails blogging software, and have a good idea of how it works in minutes. Consistency creates comprehension.</p>

<h2>Understanding Rails&#8217; Scaffolding</h2>

<p>Scaffolding gives you default controller actions (URLs to visit) and a view (forms to fill out) to interact with your data &#8212; you don&#8217;t need to build an interface yourself. You do need to define the Model and create a database table.</p>

<p>Think of scaffolds as the &#8220;default&#8221; interface you can use to interact with your app &#8211; you&#8217;ll slowly override parts of the default as your app is built. You specify scaffolds in the controller with a single line:</p>



<pre><code>scaffold :person</code></pre>



<p>and it adds default actions and views for showing, editing, and creating your &#8220;Person&#8221; object. Rails forms take some getting used to, so scaffolding helps a lot in the initial stages.</p>

<h2>More Tips and Tricks</h2>

<p>I originally planned on a list of tips &#038; tricks I found helpful when learning rails. It quickly struck me that Ruby on Rails actually requires a lot of background knowledge, and despite (or because of) its &#8220;magic&#8221;, it can still be confusing. I&#8217;ll get into my favorite tricks in an upcoming article.</p>

<p>As you dive further into web development, these guides may be helpful:</p>


<ul>
<li><a href="http://betterexplained.com/articles/how-to-debug-web-applications-with-firefox/">How To Debug Web Applications With Firefox</a></li>
<li><a href="http://betterexplained.com/articles/how-to-optimize-your-site-with-http-caching/">How To Optimize Your Site With <span class="caps">HTTP</span> Caching</a></li>
<li><a href="http://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/">How To Optimize Your Site With <span class="caps">GZIP</span> Compression</a></li>
<li><a href="http://betterexplained.com/articles/speed-up-your-javascript-load-time/">Speed Up Your Javascript Load Time</a></li>
<li><a href="http://betterexplained.com/articles/the-quick-guide-to-guids/">The Quick Guide to <span class="caps">GUID</span>s</a></li>
</ul>



<p>Until next time, enjoy these amusing videos:</p>

<p><object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/p5EIrSM8dCA"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/p5EIrSM8dCA" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></object></p>

<p><object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/H868NSM2yAg"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/H868NSM2yAg" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></object></p>]]></content:encoded>
			<wfw:commentRss>http://betterexplained.com/articles/starting-ruby-on-rails-what-i-wish-i-knew/feed/</wfw:commentRss>
		<slash:comments>105</slash:comments>
		</item>
	</channel>
</rss>

