<?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>jonathanjulian.com &#187; Rails</title>
	<atom:link href="http://jonathanjulian.com/category/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://jonathanjulian.com</link>
	<description>Ruby, Rails, JavaScript, software development</description>
	<lastBuildDate>Wed, 30 Jun 2010 21:40:38 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Rails to_json or as_json?</title>
		<link>http://jonathanjulian.com/2010/04/rails-to_json-or-as_json/</link>
		<comments>http://jonathanjulian.com/2010/04/rails-to_json-or-as_json/#comments</comments>
		<pubDate>Sun, 04 Apr 2010 17:08:36 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://jonathanjulian.com/?p=187</guid>
		<description><![CDATA[A really great modification was introduced in Rails 2.3.3 &#8211; and while everyone clamored about JSON encoding speeds and C vs Ruby implementations, the blogosphere overlooked the clean separation of responsibility that was introduced.

In the &#8220;old days&#8221;, you&#8217;d override to_json in your model class to provide a JSON implementation of your model. Then in your [...]]]></description>
			<content:encoded><![CDATA[<p>A really great modification was introduced in <a href="http://weblog.rubyonrails.org/2009/7/20/rails-2-3-3-touching-faster-json-bug-fixes">Rails 2.3.3</a> &#8211; and while everyone clamored about JSON <a href="http://www.ruby-forum.com/topic/200017">encoding speeds</a> and <a href="http://flori.github.com/json/">C vs Ruby implementations</a>, the blogosphere overlooked the clean separation of responsibility that was introduced.</p>

<p>In the &#8220;old days&#8221;, you&#8217;d override <code>to_json</code> in your model class to provide a JSON implementation of your model. Then in your controller, <code>render :json =&gt; @model</code> would work perfectly. And some folks would even redundantly code <code>render :json =&gt; @model.to_json</code>, and that would work too.</p>

<p><code>to_json</code> even had some great options for ActiveRecord objects! You could tell the method to only render certain attributes, or to include associations or method calls!</p>

<pre><code>render :json =&gt; 
  @user.to_json(:only =&gt; [:email], :include =&gt; [:addresses])
</code></pre>

<p>Life was good. But things start to fall apart when you want to do something a little out of the ordinary. Like return JSON with the model as part of a bigger structure.</p>

<pre><code>render :json =&gt; { :success =&gt; true, 
  :user =&gt; @user.to_json(:only =&gt; [:email]) }
</code></pre>

<p>Oops. <code>{\"user\":{\"email\":\"me@example.com\","success":true}</code>has the JSON characters <em>escaped</em>, which is not what we want. So what do we do? We hack around it:</p>

<pre><code>render :json =&gt; { :success =&gt; true, 
  :user =&gt; { :email =&gt; @user.email } }
</code></pre>

<p>But this doesn&#8217;t scale &#8211; we have to explicitly create the JSON <em>by hand</em> in the <em>controller</em>. What if we need 5 or more attributes? Yuck!</p>

<p>Enter <strong>ActiveSupport 2.3.3</strong>. Now the <em>creation</em> of the json is separate from the <em>rendering</em> of the json. <code>as_json</code> is used to create the structure of the JSON as a Hash, and the rendering of that hash into a JSON string is left up to <a href="http://as.rubyonrails.org/classes/ActiveSupport/JSON.html"><code>ActiveSupport::json.encode</code></a>. You should never use <code>to_json</code> to <em>create</em> a representation, only to <em>consume</em> the representation.</p>

<pre><code>def as_json(options={})
  { :email =&gt; self.email }
end
</code></pre>

<p>Anytime <code>to_json</code> is called on an object, <code>as_json</code> is invoked to create the data structure, and then that hash is encoded as a JSON string using <code>ActiveSupport::json.encode</code>. This happens for all types: Object, Numeric, Date, String, etc (see <a href="http://github.com/rails/rails/tree/2-3-stable/activesupport/lib/active_support/json">active_support/json</a>).</p>

<p>ActiveRecord objects behave the same way. There is a default <code>as_json</code> <a href="http://github.com/rails/rails/blob/2-3-stable/activerecord/lib/active_record/serializers/json_serializer.rb">implementation</a> that creates a Hash that includes all the model&#8217;s attributes. <strong>You should override <code>as_json</code> in your Model to create the JSON structure you want</strong>. <code>as_json</code>, just like the old <code>to_json</code>, takes an option hash where you can specify attributes and methods to include declaratively.</p>

<pre><code>def as_json(options={})
  super(:only =&gt; [:email, :avatar], :include =&gt;[:addresses])
end
</code></pre>

<p>Your controller code to display one model should always look like this:</p>

<pre><code>render :json =&gt; @user
</code></pre>

<p>And if you have to do anything <a href="http://namxam.tumblr.com/post/396486333/rails-as-json-vs-to-json">out of the ordinary</a>, call <code>as_json</code> passing your options.</p>

<pre><code>render :json =&gt; { :success =&gt; true, 
  :user =&gt; @user.as_json(:only =&gt; [:email]) }
</code></pre>

<p>The moral of the story is: <strong>In controllers, do not call <code>to_json</code> directly, allow <code>render</code> to do that for you. If you need to tweak the JSON output, override <code>as_json</code> in your model, or call <code>as_json</code> directly.</strong></p>

<p>Fix your code now to use <code>as_json</code> &#8211; it will be one less thing to worry about when you migrate to Rails 3.</p>

<p><em>This post was inspired by the investigation I went into while exploring the answer to <a href="http://stackoverflow.com/questions/2572284/override-to-json-in-rails-2-3-5/2574900">this question on Stack Overflow</a>.</em></p>

<p><em>Hey Brian Morearty &#8211; Rails was never Javaficated to begin with. So the answer is <a href="http://bmorearty.wordpress.com/2009/07/20/to_json-as_json/">yes</a>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanjulian.com/2010/04/rails-to_json-or-as_json/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Introduction to delayed_job</title>
		<link>http://jonathanjulian.com/2009/11/introduction-to-delayed_job/</link>
		<comments>http://jonathanjulian.com/2009/11/introduction-to-delayed_job/#comments</comments>
		<pubDate>Wed, 11 Nov 2009 13:03:58 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://jonathanjulian.com/?p=119</guid>
		<description><![CDATA[I gave this short presentation at the November bmore-on-rails meeting last night. Flip Sasser also presented an overview of Resque, and Michael Dotterer showed us a bit about background_job.

We decided that delayed_job is an easy and solid way to get background tasks running in your Rails app, but if you are a massive site that needs [...]]]></description>
			<content:encoded><![CDATA[<p>I gave this short presentation at the <a href="http://www.meetup.com/bmore-on-rails/calendar/11620904/">November</a> <a href="http://www.meetup.com/bmore-on-rails/">bmore-on-rails</a> meeting last night. <a href="http://twitter.com/flipsasser">Flip Sasser</a> also presented an overview of <a href="http://github.com/blog/542-introducing-resque">Resque</a>, and <a href="http://www.workingwithrails.com/person/17379-michael-dotterer">Michael Dotterer</a> showed us a bit about <a href="http://codeforpeople.rubyforge.org/svn/bj/trunk/README">background_job</a>.</p>

<p>We decided that delayed_job is an easy and solid way to get background tasks running in your Rails app, but if you are a massive site that needs a heavy-duty and configurable solution, then Resque may be what you need. Resque&#8217;s complexity makes this a non-trivial decision! Start with delayed_job since it&#8217;s so quick to implement, and you can always choose another solution later.</p>

<div id="__ss_2467230" style="width: 425px; text-align: left;"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" title="Introduction To Delayed Job" href="http://www.slideshare.net/jonathanjulian/introduction-to-delayed-job">Introduction To Delayed Job</a><object style="margin:0px" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtodelayedjob-091110110012-phpapp01&amp;stripped_title=introduction-to-delayed-job" /><param name="allowfullscreen" value="true" /><embed style="margin:0px" type="application/x-shockwave-flash" width="425" height="355" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtodelayedjob-091110110012-phpapp01&amp;stripped_title=introduction-to-delayed-job" allowscriptaccess="always" allowfullscreen="true"></embed></object>
<div style="font-size: 11px; font-family: tahoma,arial; height: 26px; padding-top: 2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">documents</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/jonathanjulian">Jonathan Julian</a>.</div>
</div>

<p>Want to get delayed_job running in your app in 10 minutes? Follow the steps in <a href="http://railstips.org/2008/11/19/delayed-gratification-with-rails">Delayed Gratification with Rails</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanjulian.com/2009/11/introduction-to-delayed_job/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Wrapping a div around will_paginate page_entries_info</title>
		<link>http://jonathanjulian.com/2009/11/wrapping-a-div-around-will_paginate-page_entries_info/</link>
		<comments>http://jonathanjulian.com/2009/11/wrapping-a-div-around-will_paginate-page_entries_info/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 20:19:26 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://jonathanjulian.com/?p=116</guid>
		<description><![CDATA[The page_entries_info view helper looks great, but it is just plain text; I can&#8217;t add margin or padding or float it. Here&#8217;s a quick alias_method to wrap it up in a div with the class of your choice.



Just drop that into an file in config/initializers, restart, and get styling!
]]></description>
			<content:encoded><![CDATA[<p>The page_entries_info view helper looks great, but it is just plain text; I can&#8217;t add margin or padding or float it. Here&#8217;s a quick alias_method to wrap it up in a div with the class of your choice.</p>

<script src="http://gist.github.com/230245.js"></script>

<p>Just drop that into an file in config/initializers, restart, and get styling!</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanjulian.com/2009/11/wrapping-a-div-around-will_paginate-page_entries_info/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>rake jslint</title>
		<link>http://jonathanjulian.com/2009/07/rake-jslint/</link>
		<comments>http://jonathanjulian.com/2009/07/rake-jslint/#comments</comments>
		<pubDate>Thu, 30 Jul 2009 02:38:12 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://jonathanjulian.com/?p=71</guid>
		<description><![CDATA[JSLint is one of the most valuable tools for a JavaScript developer. Short of being a &#8220;compiler&#8221;, it&#8217;s a &#8220;code quality tool&#8221; that can keep you from doing things that may come back to haunt you in the future. I&#8217;ll leave the detailed explanation to the author, Douglas Crockford &#8211; I assume you&#8217;re reading this [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jslint.com/">JSLint</a> is one of the most valuable tools for a JavaScript developer. Short of being a &#8220;compiler&#8221;, it&#8217;s a &#8220;code quality tool&#8221; that can keep you from doing things that may come back to haunt you in the future. I&#8217;ll leave the <a href="http://www.JSLint.com/lint.html">detailed explanation</a> to the author, <a href="http://www.crockford.com/">Douglas Crockford</a> &#8211; I assume you&#8217;re reading this because you want to integrate jslint into your Rails project and run it on the command-line!</p>

<p>To run jslint as a rake task in your Rails project, you&#8217;ll only need a few things:</p>

<ul>
    <li>the Java runtime</li>
    <li>Rhino, the java-based javascript runtime environment</li>
    <li>jslint itself</li>
    <li>a rake task to invoke it</li>
</ul>

<p>So let&#8217;s get it set up. First, the java. Drop into a shell on your development system (or build system, wherever you want to run jslint), and make sure you have access to the java runtimes (run java -v, or which java). If not, <a href="http://www.java.com/en/download/index.jsp">go get it</a>. Don&#8217;t be afraid, it&#8217;s easy.</p>

<p>Next you&#8217;ll need <a href="http://www.mozilla.org/rhino/">Rhino</a>, the javascript execution environment. There are many js implementations (spidermonkey/treemonkey, v8, etc), but Rhino is the one that Crockford chose when he wrote the extension to jsunit that loads a file to be parsed. Its a jar file, <a href="http://www.mozilla.org/rhino/download.html">go get it</a> and put it into your project as vendor/rhino.jar.</p>

<p>Now you need Crockford&#8217;s jslint code. There are two parts: one is <a href="http://www.JSLint.com/fulljslint.js">jslint.js</a>, and the other is the Rhino extension (<a href="http://www.JSLint.com/rhino/rhino.js">rhino.js</a>). We will need both of these, and I&#8217;ve found it&#8217;s easiest when they are combined into one. Concatenate rhino.js to the bottom of jslint.js and save as vendor/jslint.js.</p>

<p>Hey, we&#8217;re almost there! Now you just have to add the rake task to your project.
<script src="http://gist.github.com/158504.js"></script></p>

<p>Drop <a href="http://gist.github.com/raw/158504/0f20e0805e6298fba8d434f28059d5aba62b9431/jslint%20rake%20task">this gist</a> into an existing Rakefile, or rake task. If you don&#8217;t have any rake tasks, then simply save this as lib/tasks/jslint.rake. Rake will find it in your project automatically. Run rake -T to confirm.</p>

<p>A short explanation: it finds all the js files you want to inspect, and runs jslint on them one at a time, printing out failures. Line 6 is the key line &#8211; you can change two parts of this to suit your project. First, the list of files to check is created using a Dir glob. My example gets all <em>.js files under /public recursively (</em>*). Then the second part of that line is used to reject js files you DO NOT want to inspect. Frameworks, 3rd party code, for example (although it can be fun to run jslint on your framework code to see <em>their</em> level of quality). This example excludes the ExtJS installation.</p>

<p>Now youre ready to run</p>

<h2>rake jslint</h2>

<p>and enjoy the benefits of quality-checking your JavaScript code! And since you&#8217;ve just built a rake task that returns 0 or 1, it can be easily integrated into you automated or continuous build process. Heh heh &#8211; now the build will fail and everyone will know who doesn&#8217;t use triple-effing-equals! (see slide 13 of <a href="http://www.slideshare.net/voodootikigod/naked-javascript">Naked JavaScript</a>)</p>

<p>Enjoy command-line jslint. And if you develop using TextMate, I highly recommend <a href="http://www.phpied.com/jslint-on-mac-textmate/">integrating jslint into that as well</a>.</p>

<p>(I&#8217;ve been thinking and talking about this for too long. Inspiration to finally get command-line jslint set up came from reading <a href="http://stackoverflow.com/questions/247209/javascript-how-do-you-organize-this-mess/248951#248951">this</a> stackoverflow earlier today.)</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanjulian.com/2009/07/rake-jslint/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Removing Rails formatted routes too soon</title>
		<link>http://jonathanjulian.com/2009/03/removing-rails-formatted-routes-too-soon/</link>
		<comments>http://jonathanjulian.com/2009/03/removing-rails-formatted-routes-too-soon/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 18:54:06 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://jonathanjulian.com/?p=26</guid>
		<description><![CDATA[Here&#8217;s something to watch out for when serving different types of content using the Rails respond_to and :format parameters. Browsers don&#8217;t always know exactly what to do when serving non-html content. In my app, we serve many pages as csv as well as html.
Since the formatted_ routes are going to be removed from Rails, I [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s something to watch out for when serving different types of content using the Rails respond_to and :format parameters. Browsers don&#8217;t always know exactly what to do when serving non-html content. In my app, we serve many pages as csv as well as html.
Since the <a href="http://ryandaigle.com/articles/2008/11/27/what-s-new-in-edge-rails-no-more-formatted-routes">formatted_ routes are going to be removed</a> <a href="http://rails.lighthouseapp.com/projects/8994/tickets/1359-add-optional-format-argument-to-named-routes">from Rails</a>, I stopped defining them in favor of simply using the :format parameter.</p>

<p><em><strong>This means the url in the browser location bar will NOT end with &#8220;.csv&#8221;. Don&#8217;t do this on Rails 2.2.2 and earlier!
</strong></em></p>

<p>Rails 2.2.2 properly sets the Content-Type to text/csv. But that&#8217;s not enough for our browser to know what to do with it. Poking around this morning reveals that Numbers on my MacBook Pro will not open the csv file without an extension. Same issue reported by QA on Windows with IE and Firefox and Microsoft Excel. Same results whether you let the browser open the file in an app directly, or Save As and then open it.</p>

<p><em><strong>Along with the content-type, the filename and extension needs to be correct.
</strong></em></p>

<p>I fixed this on the server side, by forcing a disposition header the same way send_data does.
<pre>respond_to do |format|
  format.html
  format.csv { headers["Content-Disposition"] ||= "attachment; filename=\"#{params[:action] + '.csv'}\"" }
end</pre>
Now we get a disposition header, which explicitly tells the browser what type of file it is.
<pre>Content-Disposition: attachment; filename="index.csv"</pre>
This is ugly. Don&#8217;t do it. It won&#8217;t be needed when <a href="http://github.com/rails/rails/commit/fef6c32afe2276dffa0347e25808a86e7a101af1">this patch</a>, which removes the formatted_ routes, it released. It seamlessly keeps support for incoming requests such as &#8220;/posts.csv&#8221; working as they should.</p>

<p>So the moral of the story is: <strong>don&#8217;t be overzealous and stop using formatted routes yet!</strong> When you upgrade your app, just remove the formatted routes from routes.rb and everything will continue to work as it should.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanjulian.com/2009/03/removing-rails-formatted-routes-too-soon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
