<?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>Coffee Powered &#187; Rails</title>
	<atom:link href="http://www.coffeepowered.net/category/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.coffeepowered.net</link>
	<description>code and content</description>
	<lastBuildDate>Sun, 05 Sep 2010 20:38:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>WillPaginate and custom paging.</title>
		<link>http://www.coffeepowered.net/2010/08/07/willpaginate-and-custom-paging/</link>
		<comments>http://www.coffeepowered.net/2010/08/07/willpaginate-and-custom-paging/#comments</comments>
		<pubDate>Sat, 07 Aug 2010 22:57:19 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[will_paginate]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=300</guid>
		<description><![CDATA[will_paginate is the de facto Rails paging plugin, and with good reason &#8211; it&#8217;s solid, fast, and reliable. Everyone I know uses it, but a lot of people don&#8217;t use it to its full power. I recently discovered some very cool functionality it includes &#8211; the WillPaginate::Collection class can be used as a custom paginator [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://wiki.github.com/mislav/will_paginate/">will_paginate</a> is the de facto Rails paging plugin, and with good reason &#8211; it&#8217;s solid, fast, and reliable. Everyone I know uses it, but a lot of people don&#8217;t use it to its full power.</p>
<p>I recently discovered some <em>very</em> cool functionality it includes &#8211; the <code>WillPaginate::Collection</code> class can be used as a custom paginator for effectively any enumerable collection. It&#8217;s very simple, too. I recently used it to build pages of the most popular tags on posts in my database. My data store is MongoDB, and I&#8217;m fetching an array consisting of two-element arrays, <code>[tag, tag_count]</code>. To use will_paginate&#8217;s functionality with this, I just use the following:</p>
<pre class="brush: ruby;">
tags = Post.tag_counts(nil, {:sort =&gt; [&quot;value&quot;, &quot;descending&quot;]}) # Return an array of tag/count pairs. Custom function, so it can't leverage the finder on Post.
@topics = WillPaginate::Collection.create(current_page, 20, tags.length) do |pager|
	pager.replace(tags.slice(pager.offset, pager.offset + pager.per_page))
end
</pre>
<p><code>current_page</code> is a helper that derives the current page from the request parameters. The rest of it is self-explanitory. I can now use <code>@topics</code> in my page just as I&#8217;d use a paginated result set from the database.</p>
<pre class="brush: ruby;">
- @topics.each do |topic|
    # ...
=will_paginate @topics
</pre>
<p>Bam. Doesn&#8217;t get much easier than that. You can get exceptionally creative with it, too. Effectively, all you need to know is:</p>
<ul>
<li>WillPaginate::Collection#new takes 3 parameters: the current page, the per-page count, and optionally, the total number of entries.</li>
<li>The <code>pager</code> block variable exposes <code>offset</code> and <code>per_page</code> properties, prime for passing into a DB query or slicing an enumerable with</li>
<li>Call pager.replace(sub-array) with the current page&#8217;s set of elements.</li>
</ul>
<p>That&#8217;s literally all there is to it. Now you can have easy pagination on just about any collection you can conceive of. Let WillPaginate handle all the heavy lifting and such. If you&#8217;ve done enough pagination by hand, you&#8217;ll probably appreciate the easy beauty of this particular method.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2010/08/07/willpaginate-and-custom-paging/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eight tips for getting the most out of your Rails app</title>
		<link>http://www.coffeepowered.net/2009/12/23/eight-tips-for-getting-the-most-out-of-your-rails-app/</link>
		<comments>http://www.coffeepowered.net/2009/12/23/eight-tips-for-getting-the-most-out-of-your-rails-app/#comments</comments>
		<pubDate>Wed, 23 Dec 2009 10:04:57 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=205</guid>
		<description><![CDATA[Rails does an awful lot to optimize page generation, but there are a number of hacks, tweaks, and usage patterns you should be using to get the most out of your app. Configuration tweaks There&#8217;s a lot of the Rails stack that&#8217;s written in Ruby, which is great &#8211; it&#8217;s portable, it&#8217;s flexible, it works [...]]]></description>
			<content:encoded><![CDATA[<p>Rails does an awful lot to optimize page generation, but there are a number of hacks, tweaks, and usage patterns you should be using to get the most out of your app.</p>
<h2>Configuration tweaks</h2>
<p>There&#8217;s a lot of the Rails stack that&#8217;s written in Ruby, which is great &#8211; it&#8217;s portable, it&#8217;s flexible, it works out of the box. Unfortunately, for some things, this also means it&#8217;s slow. Other times, pieces of the framework aren&#8217;t implemented as optimally as they could be. What if you could improve your app&#8217;s performance just by installing a few gems and tweaking a few config parameters? Good news &#8211; it&#8217;s not hard.</p>
<h3>1. Replace REXML with LibXML</h3>
<p>By default, Rails uses a Ruby-native XML library called REXML. REXML is slow. REXML is very slow. REXML is personally responsible for me almost entirely giving up on Ruby due to a bad encounter with it in my first Ruby project. Fortunately, Rails provides a very easy way to avoid using REXML.</p>
<pre class="brush: ruby;">gem install libxml-ruby</pre>
<p>Then, in your app&#8217;s config/environment.rb</p>
<pre class="brush: ruby;">ActiveSupport::XmlMini.backend = 'LibXML'</pre>
<p>That&#8217;s it. Now, Rails will use the very lean, very fast libxml to parse XML documents, rather than the very fat, very slow REXML. If you&#8217;re doing feed parsing, Hash.from_xml, or anything of that nature, this will save you massive amounts of pain.</p>
<h3>2. <a href="http://slim-attributes.rubyforge.org/">slim_attributes</a></h3>
<p>If you&#8217;re using MySQL, there&#8217;s no reason why you shouldn&#8217;t be using slim_attributes.</p>
<blockquote><p>Slim Attributes boosts speed in Mysql/Rails ActiveRecord Models by avoiding instantiating Hashes for each result row, and lazily instantiating attributes as needed.</p></blockquote>
<p>Pretty self-explanatory. Rather than creating massive hashes of everything the DB gives you, slim_attributes causes ActiveRecord to only create ruby objects when you actually ask for them in code. This can reduce both your app&#8217;s memory usage and time spent on database queries. It&#8217;s not a massive increase, but given that it takes exactly one line of code to add to your project, there&#8217;s no reason not to use it.</p>
<h3>3. <a href="http://github.com/sdsykes/slim_scrooge">slim_scrooge</a></h3>
<p>From the developers of slim_attributes comes another drop-in database optimization.</p>
<blockquote><p>SlimScrooge is an optimization layer to ensure your application only fetches the database content needed to minimize wire traffic, excessive <span>SQL</span> queries and reduce conversion overheads to native Ruby types.</p>
<p>SlimScrooge implements inline query optimisation, automatically restricting the columns fetched based on what was used during previous passes through the same part of your code.</p></blockquote>
<p>Make your ORM work for you! By only fetching the content you need from your database, you reduce over-the-wire overhead, CPU overtime due to type conversion, and other such niceties. Again, just install the gem, require it in your project, and you&#8217;re off to the races.</p>
<h3>4. <a href="http://fast-xs.rubyforge.org/">fast_xs</a></h3>
<p>By default, string escaping in Rails happens in native Ruby code. This is slow. We don&#8217;t like slow. This is particularly prominent in areas like Builder::XmlMarkup, which you are using if you have any templates like <code>foo.xml.builder</code> lying around.</p>
<p>In modestly-sized document, this can result in pretty substantial slowdown in view construction. Rather than re-hashing what others have already done, I&#8217;ll point you at <a href="http://samsaffron.com/archive/2008/03/29/Speed+up+your+feed+generation+in+rails">Speed up your feed generation in Rails</a> for the long and short on it all. This can result in builder views running upwards of 10x as fast, and all you have to do is install the fast_xs gem &#8211; Rails will automatically detect and patch it in if it&#8217;s on the system.</p>
<h3>5. <a href="http://www.kuwata-lab.com/erubis/">Erubis</a></h3>
<p><img src="http://www.coffeepowered.net/wp-content/uploads/2009/12/erubis01.png" alt="Erubis benchmarks" title="Erubis benchmarks" width="351" height="262" class="alignright size-full wp-image-213" /> Erubis is an ERB implementation written in C, rather than in Ruby. As a result, it parses ERB templates very, very quickly. In fact, the Erubis benchmarks up it at upwards of 3x faster than the native ERB implementation. Installation is easy &#8211; just check the <a href="http://www.kuwata-lab.com/erubis/users-guide.05.html">using Erubis with Ruby on Rails guide</a> and you&#8217;re off to the races.</p>
<p>Do note that if you&#8217;re entirely using <a href="http://haml-lang.com/">Haml</a> or similar, Erubis won&#8217;t do much for you. Erubis is much faster than Haml, but Haml is much prettier than ERB. What you end up using is up to you!</p>
<h2>Reduce action runtimes</h2>
<h3>6. Use <a href="http://github.com/tobi/delayed_job">delayed_job</a></h3>
<p>Sometimes in the course of any web service, you run into some action that takes a little while to process. This is generally a pain and causes a whole host of problems, including frustrated users clicking refresh and spawning a dozen instances of your app all running the same long-running request and tying up valuable request slots. Long-running jobs, or jobs that absolutely must succeed are something of a royal pain in the patootie to handle gracefully. Fortunately, there&#8217;s DelayedJob, which is much like a double shot of Codine to ease that terrible pain.</p>
<p>The concept is pretty simple &#8211; rather than immediately executing a long-running task, you create a &#8220;job&#8221; for it, then use an asynchronous daemon to run your job for you.</p>
<p>For example, let&#8217;s say that your app wants to post to Twitter when you accomplish some task. This is all well and good if Twitter is up (ha!) and fast and isn&#8217;t experiencing any technical issues and you aren&#8217;t having any issues on your end and you don&#8217;t have any exceptions. In short, it&#8217;s fine when things don&#8217;t break, but we all know that things break and go wrong and generally end up sideways when you&#8217;re ever dealing with any kind of I/O, particularly of the remote web service kind. Rather than trying to post to Twitter in-process, we&#8217;ll create a job whose task is to post to Twitter.</p>
<p>Install the delayed_job gem, create the delayed_jobs table as indicated in its documentation, and write your first worker.</p>
<pre class="brush: ruby;">
module Jobs
	class PostToTwitter &lt; Struct.new(:username, :password, :tweet)
		def perform
			auth = Twitter::HTTPAuth.new(username, password)
			client = Twitter::Base.new(auth)
			client.update(tweet)
		end
	end
end
</pre>
<p>Now, in your controller code, or after_create in your model, or where ever, rather than posting to Twitter directly, just enqueue a job:</p>
<pre class="brush: ruby;">

Delayed::Job.enqueue Jobs::PostToTwitter.new(params[:username], params[:password], params[:tweet])
</pre>
<p>Finally, you&#8217;ll want to fire up a DelayedJob daemon. This is pretty easy to do under Rails.</p>
<p>Create a file called <code>script/worker.rb</code> and stick the following in it:</p>
<pre class="brush: ruby;">#!/usr/bin/env ruby
require 'rubygems'
require 'daemons'
dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))

daemon_options = {
  :multiple =&gt;; false,
  :dir_mode =&gt; :normal,
  :dir =&gt; File.join(dir, 'tmp', 'pids'),
  :backtrace =&gt; true
}

Daemons.run_proc('job_runner', daemon_options) do
  if ARGV.include?('--')
    ARGV.slice! 0..ARGV.index('--')
  else
    ARGV.clear
  end

  Dir.chdir dir
  RAILS_ENV = ARGV.first || ENV['RAILS_ENV'] || 'development'
  require File.join('config', 'environment')

  Delayed::Worker.new.start
end
</pre>
<p>Now, all you have to do is call <code>script/worker start</code> and you&#8217;re up and running. Jobs will automatically be processed as they&#8217;re added to the queue. If they fail, the reason why will be logged and the job will be scheduled to be retried in the future. You can correct any mistakes and re-run the job and watch it happily succeed. If the mistake is on the remote end, then the worker will keep retrying it until it succeeds, and your user doesn&#8217;t have to sit there and wait while your app continually receives the API equivalent of the failwhale. Everyone is happy (eventually!)</p>
<p>Once you start using DelayedJob, you&#8217;ll find that there are lots of things you can do with it to smooth out your app&#8217;s user-response speed. Processing user avatars or large file uploads, recomputing expensive queries (like a social graph update), talking to remote web services, or even sending emails can all be moved away from the realtime and into the background with total ease.</p>
<h3>7. Use memcached</h3>
<p>This should probably be tip #1. Good caching can make or break a project, and memcached is a fantastic method for managing your caching. </p>
<blockquote><p>Memcached is an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering.</p></blockquote>
<p>By default, Rails writes page and fragment cache bits to disk. This is slow, is difficult to clean up after, adds a lot of wear-and-tear to your disk, and is generally undesirable. It&#8217;s used because it&#8217;s easy. Memcached is a far better solution &#8211; it is very much a &#8220;giant hash table in the sky&#8221;. Dump a value into memory, read it back out of memory later. It is extremely fast, and comes with some super dandy features like time-based expiration that disk caching just won&#8217;t get you.</p>
<p>Implementation in Rails is easy. First, install both the memcached daemon and the memcache client. Second, in your environment file, add something like so:</p>
<pre class="brush: ruby;">
require_library_or_gem 'memcache'
config.cache_store = :mem_cache_store, [&quot;localhost:11211&quot;]
</pre>
<p>By default, memcached runs on port 11211. Point Rails at it with the above directives and restart your app and that&#8217;s it. You&#8217;re running on memcached. No more ugly disk sweeping, and you get some really nice features. You can add multiple servers to the :mem_cache_store, too, which is several flavors of awesome. The memcached client will do automatic cluster management and balancing, so you can share the same cache between any number of servers, rather than each server having to have its own copy of that cache. Sweet!</p>
<pre class="brush: ruby;">
&lt;% cache(&quot;my_custom_fragment_name:#{@record_id}&quot;, :raw =&gt; true, :expires_in =&gt; 1.hour) do %&gt;
	&lt;%=render :partial =&gt; &quot;some_expensive_partial&quot;, :object =&gt; @record %&gt;
&lt;% end %&gt;
</pre>
<p>This is your standard fragment cache, but the <code>:raw</code> and <code>:expires_in</code> parameters are new.</p>
<p><code>:raw</code> tells the Ruby memcached client to not marshal the content before sticking it in memcached. Since you&#8217;re just storing a document fragment (that is, a string), marshaling a ruby string and then unmarshaling it when you want to read it back is both unnecessary and slow.</p>
<p><code>:expires_in</code> sets a maximum lifetime for this fragment. If we generate a fragment, memcached will timestamp it, and then if we try to read it back, say, 90 minutes later, memcached will recognize &#8220;oh hey, this fragment is expired! Sorry, I don&#8217;t have anything for you!&#8221;. Our view will regenerate and re-cache that fragment, and for the next 60 minutes, rather than trying to regenerate that fragment any time that view is called, it&#8217;ll just pull the cached copy from memcached.</p>
<p>If you need to ever flush your cache, it&#8217;s as easy as just restarting memcached. That&#8217;s it, really. In one fell swoop, you get faster caching (yay!), easier cache management (yay!), and a cache that can scale across multiple servers (double yay!)</p>
<h3>8. Use etags</h3>
<p>etags are a nifty little feature that are woefully under-used by most web developers. You can think of them as a fingerprint for a given page. Consider the following process:</p>
<ol>
<li>I request a page for the first time. The app generates the page and sends me both a copy of the page and a small hash finger print.</li>
<li>I request the page a second time, and send the fingerprint of my cached copy back to the server.</li>
<li>The server compares the fingerprint I sent with the fingerprint of its latest copy of the page. If they match, it just sends back a <code>304 Not Modified</code> header and stops rendering</li>
</ol>
<p>Sounds handy, right? Sure, and it&#8217;s really easy to implement in Rails. Let&#8217;s assume you have a <code>BlogController</code> which has a <code>show</code> method for showing a given blog post. You could use the following to implement etags:</p>
<pre class="brush: ruby;">
def show
	@post = BlogPost.find params[:id]
	@comments = @post.comments.paginate params[:page], 25
	return unless stale? :etag =&gt; [@post, @comments]
end
</pre>
<p>Wait, that&#8217;s it? Yes, actually! What&#8217;s happening there is Rails builds a fingerprint of the object(s) you the <code>:etag</code> parameter of the <code>stale?</code> method. If the objects don&#8217;t change, then the etag doesn&#8217;t change. This means that you would get different etags for the same blog post on a different page of comments (good!), or a different etag if a comment is added (good!) or a different etag if the post is edited (good!), but as long as those objects haven&#8217;t changed since the user&#8217;s last request of that action, the etag will be the same, and the action will stop running right there and tell the browser to just display its cached copy.</p>
<p>On heavily-trafficked pages that aren&#8217;t easily customized on a global scale (for example, if you have custom per-user bits on the page that mean that you can&#8217;t serve the same page to everyone), this is a really decent way to prevent excessive and wasteful application work. If you don&#8217;t use the <code>stale?</code> method, Rails always assumes that the page is stale, and thus needs to be regenerated. </p>
<p>On something of a tangent, can also use <code>stale? :last_modified => @post.updated_at</code> to determine if a page is fresh or stale. However, this does have the drawback of not being compatible with pagination, or sorted views, or anything of that nature. By using etags, you can ensure that each unique data set gets its own etag, and thus, doesn&#8217;t have cache collisions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2009/12/23/eight-tips-for-getting-the-most-out-of-your-rails-app/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>When you have to store user passwords&#8230;</title>
		<link>http://www.coffeepowered.net/2009/12/15/when-you-have-to-store-user-passwords/</link>
		<comments>http://www.coffeepowered.net/2009/12/15/when-you-have-to-store-user-passwords/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 10:14:42 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=203</guid>
		<description><![CDATA[Today we got word of yet-another-database-hack-with-plaintext-passwords. This time, it&#8217;s RockYou, purveyor of many of those Facebook and Myspace apps you use. Oops. Every time this comes up, everyone says &#8220;How naive! They should have been using salted hashed passwords!&#8221; This is true in any case where you don&#8217;t need to use the password again on [...]]]></description>
			<content:encoded><![CDATA[<p>Today we got word of yet-another-database-hack-with-plaintext-passwords.<a href="http://www.techcrunch.com/2009/12/14/rockyou-hack-security-myspace-facebook-passwords/"> This time, it&#8217;s RockYou</a>, purveyor of many of those Facebook and Myspace apps you use. Oops.</p>
<p>Every time this comes up, everyone says &#8220;How naive! They should have been using salted hashed passwords!&#8221; This is true in any case where you don&#8217;t need to use the password again on an external service. With OAuth solutions becoming more and more popular, the need to collect and store user passwords is fortunately becoming more and more rare. However, it does need to happen sometimes, so how do you take the proper precautions when you do need to?</p>
<p>The first step is to encrypt your data before it is persisted into your database. This is pretty easy to do, and there are a number of methods for it. Here&#8217;s an example of something I used in a Rails app to provide encryption services.</p>
<pre class="brush: ruby;">
require 'openssl'
require 'base64'
module Encryption
	class OpenSSL_Key
		PUBLIC_KEY_FILE = &quot;#{RAILS_ROOT}/config/public.pem&quot;
		PRIVATE_KEY_FILE = &quot;#{RAILS_ROOT}/config/private.pem&quot;

		def self.encrypt(data)
			@@public_key ||= OpenSSL::PKey::RSA.new(File.read(PUBLIC_KEY_FILE))
			encrypted_data = @@public_key.public_encrypt(data)
			Base64.encode64(encrypted_data)
		end

		def self.decrypt(data)
			@@private_key ||= OpenSSL::PKey::RSA.new(File.read(PRIVATE_KEY_FILE))
			decoded_data = Base64.decode64(data)
			@@private_key.private_decrypt(decoded_data)
		end
	end

	class OpenSSL_RSA
		IV64 = &quot;xxxxxxxxxxxxxxxxxxxxxxxxxx==\n&quot;
		KEY64 = &quot;xxxxxxxxxxxxxxxxxxxxxxxxxx=\n&quot;
		CIPHER = 'aes-256-cbc'

		def self.encrypt(data)
			@@iv ||= Base64.decode64(IV64)
			@@key ||= Base64.decode64(KEY64)

			cipher = OpenSSL::Cipher::Cipher.new(CIPHER)
			cipher.encrypt
			cipher.key = @@key
			cipher.iv = @@iv
			encrypted_data = cipher.update(data)
			encrypted_data &lt;&lt; cipher.final
			Base64.encode64(encrypted_data)
		end

		def self.decrypt(data)
			@@iv ||= Base64.decode64(IV64)
			@@key ||= Base64.decode64(KEY64)

			cipher = OpenSSL::Cipher::Cipher.new(CIPHER)
			cipher.decrypt
			cipher.key = @@key
			cipher.iv = @@iv
			decrypted_data = cipher.update(Base64.decode64(data))
			decrypted_data &lt;&lt; cipher.final
		end
	end
end
</pre>
<p>This provides two classes, <code>Encryption::OpenSSL_Key</code> and <code>Encryption::OpenSSL_RSA</code> which may be used to encrypt arbitrary strings. The OpenSSL_Key class uses a public/private keypair (in our example, read out of the Rails config directory), and the OpenSSL_RSA class uses an initialization vector and secret key. The latter is probably easier, since it means you don&#8217;t have to worry about keypairs, and since all the encrypt/decrypt is done locally, there isn&#8217;t any need for public public encryption.</p>
<p>Once you have that file in your project, using it is pretty simple.</p>
<pre class="brush: ruby;">
# Our databse is going to have a field called encrypted_password. We'll use attr_accessor for the password itself.

class MySecretModal &lt; ActiveRecord::Base
	before_save :encrypt_fields
	attr_accessor :password

	def password
		@decrypted_password ||= decrypt_field(:password)
	end

private

	def encrypt_fields
		write_attribute :encrypted_password, Encryption::OpenSSL_RSA.encrypt(@password)
	end

	def decrypt_field(field)
		Encryption::OpenSSL_RSA.decrypt read_attribute(&quot;encrypted_#{field}&quot;)
	end
end
</pre>
<p>The net result is that we can still get access to the raw password if we need to, but the content in the database will be RSA-encrypted against a secret key in our application. This is still vulnerable if the attacker gains access to the file containing your RSA IV/key, or if he gains access to your public/private keypair, but it is extremely resilient in the case that an attacker manages to simply dump your users table via SQL injection. You still need to practice good key management, and you absolutely should not use a technique this simplistic for storing financial data &#8211; there are a whole set of guidelines and procedures for that kind of information. However, for adding an extra layer of defense to save yourself and your customers from excess embarrassment in the case of a database breach, this is a quick, easy, and effective technique for hardening your data.</p>
<p>This is a rather raw implementation, and there are ways you could package it up so that you could transparently apply it to any number of models or fields, but the basic technique is solid. You could even use something like <a href="http://github.com/Mechaferret/sql_crypt">sql_crypt</a> to easily protect sensitive fields. The technology is there, and &#8220;We needed to be able to re-use the password!&#8221; isn&#8217;t an excuse anymore. Stop storing plaintext passwords &#8211; just like backups, it&#8217;s just extra work until you need it, and then you&#8217;ll be glad you put that extra work in.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2009/12/15/when-you-have-to-store-user-passwords/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Fine tuning your garbage collector</title>
		<link>http://www.coffeepowered.net/2009/06/13/fine-tuning-your-garbage-collector/</link>
		<comments>http://www.coffeepowered.net/2009/06/13/fine-tuning-your-garbage-collector/#comments</comments>
		<pubDate>Sun, 14 Jun 2009 02:52:13 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=173</guid>
		<description><![CDATA[If you&#8217;re familiar with Ruby at all, you know that it can be a little wacky when it comes to memory usage. Most of us have observed a Mongrel/Passenger instance that starts out small and then grows by leaps and bounds, eventually settling on some uncomfortably high number. We&#8217;re going to fix that with Ruby [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re familiar with Ruby at all, you know that it can be a little wacky when it comes to memory usage. Most of us have observed a Mongrel/Passenger instance that starts out small and then grows by leaps and bounds, eventually settling on some uncomfortably high number. We&#8217;re going to fix that with <a href="http://www.rubyenterpriseedition.com/">Ruby Enterprise Edition</a> and <a href="http://github.com/cheald/scrap/tree/master">Scrap</a>.<br />
<span id="more-173"></span><br />
The Ruby garbage collector&#8217;s behavior is controlled by a number of constants. In the MRI, these are compiled into Ruby itself, and don&#8217;t change. However, if you&#8217;re using REE you can override them with environment variables on startup. It&#8217;s terribly handy.</p>
<h3>First, the boring documentation</h3>
<p>All the juicy information is available <a href="http://www.rubyenterpriseedition.com/documentation.html#_garbage_collector_performance_tuning">in the documentation</a>, but I&#8217;m going to just go over the key points real quick.</p>
<p><code>RUBY_HEAP_MIN_SLOTS</code>: This is the number of &#8220;heap slots&#8221; that each Ruby instance starts up with. One heap slot can hold one Ruby object. By default, this is 10,000. By controlling this value, we can get our apps to stabilize very quickly. More on this later.</p>
<p><code>RUBY_HEAP_SLOTS_INCREMENT</code>: Once Ruby has allocated <code>RUBY_HEAP_MIN_SLOTS</code> objects on its first heap, it will have to allocate a second heap to make room for more. This variable controls the size of this second heap, and sets the baseline for future heaps, as well.</p>
<p><code>RUBY_HEAP_SLOTS_GROWTH_FACTOR</code>: For heaps #3 and onward, Ruby uses <code>RUBY_HEAP_SLOTS_INCREMENT</code> and this value to determine the size to allocate for the new heap. By default, this is 1.8, meaning that your third heap will end up with 10,000 * 1.8 = 18,000 slots in it.</p>
<p><code>RUBY_HEAP_FREE_MIN</code>: After each garbage collection run, if the number of free slots is less than <code>RUBY_HEAP_FREE_MIN</code>, a new heap will be allocated. The default is 4096.</p>
<p>So, let&#8217;s look at this practically. Presume that we have a Rails process that is going to require 50,000 Ruby objects before it&#8217;s fully initialized. The allocation process, when at defaults, will look something like this:</p>
<p>Allocate 10,000 slots (10,000 total available)<br />
Allocate 10,000 slots (20,000 total available)<br />
Allocate 18,000 slots (38,000 total available)<br />
Allocate 68,400 slots (106,400 total available)</p>
<p>So, we end up with about 53% more slots than we actually needed, and it took us four heap allocations to even boot the process. Surely we can do better.</p>
<h3>Enter Scrap.</h3>
<p><a href="http://github.com/cheald/scrap/tree/master">Scrap</a> is a little <a href="http://weblog.rubyonrails.org/2008/12/17/introducing-rails-metal">Metal</a> handler I wrote for tracking memory usage and garbage statistics over an instance&#8217;s lifetime. Installing it is trivial &#8211; just drop it into your vendor directory, restart your app, and navigate to <code>http://yoururl.com/stats/scrap</code>.</p>
<p>With this in hand, we can peek our memory usage and see what we can see.</p>
<p>There are some stats at the top, but for our purposes, we&#8217;re interested in the per-request garbage statistics. The newest request is near the top of the file, and the oldest request is at the bottom of the file. The last 50 requests are tracked. Each request looks something like this:</p>
<pre><code>
[71.92 MB] GET /apps/176568-WordPress

Number of objects    : 817571 (658305 AST nodes, 80.52%)
Heap slot size       : 20
GC cycles so far     : 503
Number of heaps      : 7
Total size of objects: 15968.18 KB
Total size of heaps  : 18036.81 KB (2068.63 KB = 11.47% unused)
Leading free slots   : 27104 (529.38 KB = 2.93%)
Trailing free slots  : 1 (0.02 KB = 0.00%)
Number of contiguous groups of 16 slots: 2829 (4.90%)
Number of terminal objects: 4307 (0.47%)
</code></pre>
<p>Key points here for the time being are <code>Number of objects</code> and <code>Number of heaps</code>. When we look at the number of objects &#8211; in this case, 817,000, it&#8217;s obvious that we&#8217;re going to have to allocate a number of heaps to handle all those objects. Rails&#8217; boot-up cost is fairly significant, and the default Ruby settings just really don&#8217;t cut it here. As you can see, we&#8217;ve allocated 7 heaps, and we&#8217;re using 15.9 of 18.0 MB allocated to the heap. Once a heap is allocated, it&#8217;s never de-allocated, so we&#8217;re perma-stuck at 18 MB of heap usage. Note that this isn&#8217;t the size of all the data in the program &#8211; just the space allocated for objects. A string that contains 100MB of data will only consume 20 bytes (that&#8217;s the &#8220;heap slot size &#8211; the amount of memory each object on the heap consumes&#8221;) on the heap. </p>
<p>However, what if we could just allocate the whole startup cost in the initial heap, and save ourselves the problems of having to reallocate so often?</p>
<p>We note that we have 891k slots allocated, so we can guesstimate at a number to set our initial allocation to. In my production app, I set mine to 1,250,000 &#8211; I was observing peaks around the 1,100,000 mark, and just increased it by 10% and rounded up.</p>
<p>So, my first custom environment variable is </p>
<p><code>RUBY_HEAP_MIN_SLOTS=1250000</code></p>
<p>And it results in something like this on the app&#8217;s first boot:</p>
<p>[137.99 MB] GET /movies/7505-Star-Wars-Episode-V-The-Empire-Strikes-Back</p>
<pre><code>Number of objects    : 933037 (664785 AST nodes, 71.25%)
Heap slot size       : 20
GC cycles so far     : 12
Number of heaps      : 1
Total size of objects: 18223.38 KB
Total size of heaps  : 24414.08 KB (6190.70 KB = 25.36% unused)
Leading free slots   : 316963 (6190.68 KB = 25.36%)
Trailing free slots  : 0 (0.00 KB = 0.00%)
Number of contiguous groups of 16 slots: 19810 (25.36%)
Number of terminal objects: 25941 (2.08%)</code></pre>
<p>Yowza, a full 25% of my heap is unused after boot. But&#8230;well, that&#8217;s okay. We&#8217;ve only allocated 1 heap, and later on, my object allocation grows to around 1,100,000. This is still 15k under the heap size, and I&#8217;ve set <code>RUBY_HEAP_FREE_MIN=12500</code> (1% of the initial size), so if I have less than 12,500 heap objects free after a GC cycle, a new heap will be allocated. Stabilizing there means that I end up with 1 heap for the lifetime of my app, and I end up sitting just under the threshold that&#8217;d cause a new heap to be born. If I have a leak, or a super heavy action or something, though, that might kick me over my limit and require a new heap. So, we come to&#8230;</p>
<p><code>RUBY_HEAP_SLOTS_INCREMENT=100000</code></p>
<p>This value says &#8220;Hey, if you have to allocate a second heap, start with this many slots&#8221;. If we go over our limit of 1.25 million slots, we&#8217;ll allocate a second heap that&#8217;s about 8% the size of the original. That seems awfully small, but consider that we&#8217;re hoping to never get to that heap.</p>
<p>Should we end up using that entire second heap, then we have to worry about our third setting, <code>RUBY_HEAP_SLOTS_GROWTH_FACTOR=1</code>. This says &#8220;Each new heap should be 1.0 as large as the previous heap.&#8221; In this case, it means I&#8217;ll keep allocating 100k-slot heaps until the cows come home. In an untuned environment, this could be bad &#8211; we would either end up having to do a <em>ton</em> of allocations to get to our target, or we would overallocate very badly. However, because we know our app&#8217;s memory requirements, and know about where we want it to end up, a relatively small, linear growth factor is just what the doctor ordered here.</p>
<h3>Okay, now what?</h3>
<p>So, we have a collection of settings with which to run our app. Great! Now, how do we use it?</p>
<p>Fortunately, it&#8217;s easy.</p>
<pre><code>
pushd `which ruby | xargs dirname`
sudo vim ruby-with-env
</code></pre>
<p>We&#8217;re going to create a little bash script with the following:</p>
<pre class="brush: ruby;">
#!/bin/bash
export RUBY_HEAP_MIN_SLOTS=1250000
export RUBY_HEAP_SLOTS_INCREMENT=100000
export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1
export RUBY_GC_MALLOC_LIMIT=30000000
export RUBY_HEAP_FREE_MIN=12500
exec &quot;/opt/ree/bin/ruby&quot; &quot;$@&quot;
</pre>
<p>Note that last line &#8211; the path will have to match the path to your Ruby executable, which fortunately, should be in the directory that you&#8217;re in.</p>
<p>Save it, don&#8217;t forget to <code>chmod a+x ruby-with-env</code>, and then edit your Apache or nginx configuration.</p>
<p>Under nginx, you&#8217;ll have a line like this:</p>
<p><code>passenger_ruby /opt/ruby-enterprise-1.8.6-20090610/bin/ruby;</code></p>
<p>Just change it to use your new wrapper script, like so:</p>
<p><code>passenger_ruby /opt/ruby-enterprise-1.8.6-20090610/bin/ruby-with-env;</code></p>
<p>The process is similarly easy for Apache &#8211; the line you need is something like:</p>
<p><code>PassengerRuby /opt/ruby-enterprise-1.8.6-20090610/bin/ruby</code></p>
<p>It might be in either your <code>httpd.conf</code> or <code>conf.d/passenger.conf</code>.</p>
<p>Once you&#8217;re all edited up, restart your webserver, and congratulations, you&#8217;ve got a fine-tuned garbage collector humming along with your app.</p>
<h3>Taking out the garbage</h3>
<p>&#8220;But Chris!&#8221;, you say, &#8220;There&#8217;s a variable in there that you didn&#8217;t talk about! What gives?&#8221; You are indeed correct, astute reader. We&#8217;ve thus far avoided the <code>RUBY_GC_MALLOC_LIMIT</code> variable. This is a handle little setting that lets you tell Ruby how often to clean up after itself. Ruby is written in C, and C uses <code>malloc</code> to allocate memory. Ruby just keeps a little counter each time it allocates an object with malloc, and it runs its garbage collector after so many malloc calls have been made. I haven&#8217;t found a great way to tune this one yet, except via experimentation, but here&#8217;s what to know about it:</p>
<ol>
<li>The lower this value is, the more often your garbage collector runs. Garbage collection is slow. Garbage collection is painfully slow. If a user is waiting on garbage collection, they are going to become impatient. You want as few users waiting on garbage collection as possible.</li>
<li>The higher this value is, the more memory Ruby will allocate before it tries to clean up after itself. If this value is too high, you&#8217;ll have dead objects hanging around eating up heap space, and possibly causing Ruby to crap itself and allocate a new heap. This is bad.</li>
<li>To tune this value, you want to find the happy medium, wherein you stabilize under your initial heap allocation value, but with as few garbage collection passes as possible. Read up on <a href="http://blog.evanweaver.com/articles/2009/04/09/ruby-gc-tuning/">Evan Weaver&#8217;s blog</a> for some more in-depth analysis of what garbage collection frequency tuning can do to your app&#8217;s performance.
<li>If you have excess memory and want a faster app, err on the side of this being too high. If you are on a tight memory budget, and would prefer slower actions in exchange for not blowing your heap and allocating a whole new one, err on the side of this being too low.</li>
<li>Recommended values for this are all over the board. Evan recommends a setting of 50 million. I&#8217;m using a setting of 30 million. The Ruby default is 8 million. You&#8217;ll have to play around and find what works best for you. Just pay attention to how many requests there are in between that &#8220;GC cycles so far&#8221; number incrementing in Scrap, and you&#8217;ll be able to measure approximately how often you&#8217;re entering a GC cycle.
</ol>
<p>Good luck with it, and have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2009/06/13/fine-tuning-your-garbage-collector/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Announcing Scrap</title>
		<link>http://www.coffeepowered.net/2009/03/24/announcing-scrap/</link>
		<comments>http://www.coffeepowered.net/2009/03/24/announcing-scrap/#comments</comments>
		<pubDate>Tue, 24 Mar 2009 10:02:09 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[metal]]></category>
		<category><![CDATA[objectspace]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=159</guid>
		<description><![CDATA[I do a lot of memory and garbage analysis on my Rails apps, and in upgrading to Rails 2.3, I discovered a practical use for the new Rails Metal middleware. Dumping memory stats to my log was just sorta unreadable in a practical scenario, and was more or less entirely unusable in production. Fortunately, Metal [...]]]></description>
			<content:encoded><![CDATA[<p>I do a lot of memory and garbage analysis on my Rails apps, and in upgrading to Rails 2.3, I discovered a practical use for the new <a href="http://weblog.rubyonrails.org/2008/12/17/introducing-rails-metal">Rails Metal</a> middleware. Dumping memory stats to my log was just sorta unreadable in a practical scenario, and was more or less entirely unusable in production. Fortunately, Metal provides a really easy way to output readable information to the browser without invoking the full Rails stack. (It&#8217;s also an excuse to write a Metal endpoint because it&#8217;s new and shiny, but that&#8217;s beside the point.)</p>
<p>It&#8217;s up at <a href="http://github.com/cheald/scrap/tree/master">github</a> &#8211; installation is dead easy (assuming you&#8217;re on Rails 2.3+, of course) &#8211; just install the plugin, restart your app, and hit <code>&lt;your url&gt;/stats/scrap</code> in your browser. Bam, instant juicy memory goodness about your app at your fingertips. If you&#8217;d like an example of the output, good news! Check it out at <a href="http://tachyonsix.com/scrap.htm">http://tachyonsix.com/scrap.htm</a>.</p>
<p>You can use it to troubleshoot heap leaks &#8211; just run a few requests, hit your Scrap URL, and see what your deltas look like. Seeing a huge growth in a certain type of object? Chances are pretty good that you have a heap leak, and can start tracking it down.</p>
<p>The request history can help you locate certain actions that might be causing spikes in memory usage. It&#8217;ll show the last N requests, along with memory and heap statistics before each request. If there&#8217;s a consistent memory usage leap after a certain action, chances are that it&#8217;s doing something naughty.</p>
<p>Want to get a bigger picture on what objects are hanging around? You can use the <code>config/scrap.yml</code> file to get Scrap to spit out more detailed reports on instances of a given class. There&#8217;s full documentation on it in the README.</p>
<p>Anyhow, give it a shot, let me know what you think.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2009/03/24/announcing-scrap/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Monitoring Rails: Getting instant monitoring alerts</title>
		<link>http://www.coffeepowered.net/2009/03/13/monitoring-rails-getting-instant-monitoring-alerts/</link>
		<comments>http://www.coffeepowered.net/2009/03/13/monitoring-rails-getting-instant-monitoring-alerts/#comments</comments>
		<pubDate>Fri, 13 Mar 2009 08:58:31 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[jabberish]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[uptime]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=145</guid>
		<description><![CDATA[Monitoring is big. Having an automated daemon watch your stuff and make sure it&#8217;s running properly can let you sleep at night, knowing that if something blows up, there&#8217;s an ever-watchful guardian ready to wake you up so you can fix it. There are a number of monitoring solutions that are popular these days, such [...]]]></description>
			<content:encoded><![CDATA[<p>Monitoring is big. Having an automated daemon watch your stuff and make sure it&#8217;s running properly can let you sleep at night, knowing that if something blows up, there&#8217;s an ever-watchful guardian ready to wake you up so you can fix it.</p>
<p>There are a number of monitoring solutions that are popular these days, such as <a href="http://mmonit.com/monit/">monit</a>, <a href="http://god.rubyforge.org/">god</a>, and <a href="http://www.nagios.org/">Nagios</a>. They&#8217;re all fantastic, but sometimes you just want something simple and to-the-point, right?</p>
<p><span id="more-145"></span></p>
<p>With <a href="http://github.com/cheald/jabberish/tree/master/">jabberish</a> in your project, this becomes a no-brainer. I&#8217;m already using Jabberish in my project, so I whipped up a little script that checks system load, available memory, and any changes in swap usage and shoots me an IM under certain conditions. My monitoring still handles automated maintenance in the case of a runaway process or whatnot, but this keeps me instantly informed of any problems that my system might be running in to.</p>
<pre class="brush: ruby;">
require 'rubygems'
require 'drb'
require 'daemons'

MAX_MEMORY = 95
MAX_LOAD = 4.0
DELIVER_TO = &quot;cheald@gmail.com&quot;
JABBERISH_SERVER = &quot;druby://localhost:35505&quot;

$warned = {}
$hostname = `hostname`.strip

def im
	$im_service ||= DRbObject.new(nil, JABBERISH_SERVER)
end

def deliver(msg)
	im.deliver DELIVER_TO, &quot;[#{$hostname}] #{msg}&quot;
end

def check_stats
	meminfo = open(&quot;/proc/meminfo&quot;).read

	mtotal = meminfo.match(/MemTotal:\s+(\d+)/)[1].to_i
	mfree = meminfo.match(/MemFree:\s+(\d+)/)[1].to_i
	mused = mtotal - mfree

	stotal = meminfo.match(/SwapTotal:\s+(\d+)/)[1].to_i
	sfree = meminfo.match(/SwapFree:\s+(\d+)/)[1].to_i
	sused = stotal - sfree

	begin
		if $warned[:swap] and sused &gt; $warned[:swap] then
			deliver &quot;WARNING: Swap has increased from #{$warned[:swap]} to #{sused}&quot;
		end
		$warned[:swap] = sused

		pct = mused / mtotal.to_f * 100.0
		if pct &gt; MAX_MEMORY then
			unless $warned[:memory]
				deliver sprintf(&quot;ALERT: Memory free: %2.2fmb (%2.2f%% used)&quot;, mfree / 1024.0, pct)
				$warned[:memory] = true
			end
		else
			$warned[:memory] = false
		end

		load = open(&quot;/proc/loadavg&quot;).read.split(&quot; &quot;).first
		if load &gt; MAX_LOAD then
			unless $warned[:load]
				deliver sprintf(&quot;WARNING: Load average is %s&quot;, load)
				$warned[:load] = true
			end
		else
			$warned[:load] = false
		end
	rescue
		puts &quot;Error: #{$!}&quot;
	end
end

Daemons.daemonize(:backtrace =&gt; true)

loop {
	check_stats
	sleep(10)
}
</pre>
<p>Not too bad, huh? This is written for a CentOS installation, so you may need to change things like the meminfo regexes depending on your system. It could probably use a YAML config file to be truly correct &#8211; configuration options in constants works, but is a little ugly.</p>
<p>Now I get alerts like these via instant message:</p>
<pre class="brush: ruby;">
[iceman.tagteam] WARNING: Load average is 4.44
[iceman.tagteam] ALERT: Memory free: 99.82mb (93.38% used)
[polaris.tagteam] ALERT: Memory free: 72.20mb (95.14% used)
</pre>
<p>This lets me respond to changing system conditions extremely rapidly, and serves as a high-level alert log when when I&#8217;m not at the keyboard &#8211; when I get back, I check my messages from blippr, and can see when and how often certain marginal conditions are being met.</p>
<p>Hope it&#8217;s useful!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2009/03/13/monitoring-rails-getting-instant-monitoring-alerts/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Mass inserting data in Rails without killing your performance</title>
		<link>http://www.coffeepowered.net/2009/01/23/mass-inserting-data-in-rails-without-killing-your-performance/</link>
		<comments>http://www.coffeepowered.net/2009/01/23/mass-inserting-data-in-rails-without-killing-your-performance/#comments</comments>
		<pubDate>Sat, 24 Jan 2009 03:55:59 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=82</guid>
		<description><![CDATA[Mass inserting is one of those operations that isn&#8217;t really well-supported by ActiveRecord, but which has to be done nonethless. You might say, &#8220;Well hey, I&#8217;ll just run a loop and create a bunch of AR objects, no sweat&#8221;. That&#8217;ll work, but if speed is a factor, it might not be your best option. ActiveRecord [...]]]></description>
			<content:encoded><![CDATA[<p>Mass inserting is one of those operations that isn&#8217;t really well-supported by ActiveRecord, but which has to be done nonethless. You might say, &#8220;Well hey, I&#8217;ll just run a loop and create a bunch of AR objects, no sweat&#8221;.</p>
<p>That&#8217;ll work, but if speed is a factor, it might not be your best option.</p>
<p>ActiveRecord makes interface to the DB very easy, but it doesn&#8217;t necessarily make it fast. Instantiating an ActiveRecord object is costly, and if you do a lot of &#8216;em, that&#8217;s going to cause you to bump up against the garbage collector, which will significantly hinder performance. There are several options, though, depending on how much speed you need.</p>
<p>There are benchmarks at the bottom of the post, so if you&#8217;re just interested in those, scroll down.<br />
<span id="more-82"></span></p>
<h2>Option 1: Use transactions</h2>
<p>This is definitely the easiest method, and while you&#8217;ll realize gains from it, you aren&#8217;t going to be breaking any speed records using only this method. However, it&#8217;s well worth it if you are doing mass inserts via ActiveRecord.</p>
<p>Instead of</p>
<pre class="brush: ruby;">
1000.times { Model.create(options) }
</pre>
<p>You want:</p>
<pre class="brush: ruby;">
ActiveRecord::Base.transaction do
  1000.times { Model.create(options) }
end
</pre>
<p>The net effect is that the database performs all of your inserts in a single transaction, rather than starting and committing a new transaction for every request.</p>
<h2>Options 2: Get down and dirty with the raw SQL</h2>
<p>If you know that your data is valid and can afford to skip validations, you can save a <b>lot</b> of time by just jumping directly to raw SQL.</p>
<p>Imagine, for example, that you&#8217;re running the following:</p>
<pre class="brush: ruby;">
1000.times {|i| Foo.create(:counter =&gt; i) }
</pre>
<p>That&#8217;s going to create 1000 ActiveRecord objects, run validations, generate the insert SQL, and dump it into the database. You can realize large performance gains by just jumping directly to the generated SQL.</p>
<pre class="brush: ruby;">
1000.times do |i|
  Foo.connection.execute &quot;INSERT INTO foos (counter) values (#{i})&quot;
end
</pre>
<p>You should use <code>sanitize_sql</code> and such as necessary to sanitize input values if they are not already sanitized, but with this technique you can realize extremely large performance gains. Of course, wrapping all those inserts in a single transaction, as in Option 1 gets you even more performance.</p>
<pre class="brush: ruby;">
Foo.transaction do
  1000.times do |i|
    Foo.connection.execute &quot;INSERT INTO foos (counter) values (#{i})&quot;
  end
end
</pre>
<h2>Option 3: A single mass insert</h2>
<p>Many databases support mass inserts of data in a single insert statement. They are able to significantly optimize this operation under the hood, and if you&#8217;re comfortable using it, will be your fastest option by far.</p>
<pre class="brush: ruby;">
inserts = []
TIMES.times do
  inserts.push &quot;(3.0, '2009-01-23 20:21:13', 2, 1)&quot;
end
sql = &quot;INSERT INTO user_node_scores (`score`, `updated_at`, `node_id`, `user_id`) VALUES #{inserts.join(&quot;, &quot;)}&quot;
</pre>
<p>No transaction block is necessary here, since it&#8217;s just a single statement, and the DB will wrap it in a transaction. We build an array of value sets to include, then just join them into the <code>INSERT</code> statement. We don&#8217;t use string concatenation, since it will result in significantly more string garbage generated, which could potentially get us into the GC, which we&#8217;re trying to avoid (and hey, memory savings are always good).</p>
<h2>Option 4: ActiveRecord::Extensions</h2>
<p>njero in <code>#rubyonrails</code> pointed me at <a href="http://www.continuousthinking.com/tags/arext/rdoc/index.html">this nifty little gem</a> and I decided to include it. It seems to try to intelligently do mass inserts of data. I wasn&#8217;t able to get it to emulate the single mass insert for a MySQL database, but it does provide a significant speed increase without much additional work, and can preserve your validations and such.</p>
<p>There&#8217;s the obvious added benefit that you stay in pure Ruby, and don&#8217;t have to get into the raw SQL.</p>
<pre class="brush: ruby;">
columns = [:score, :node_id, :user_id]
values = []
TIMES.times do
	values.push [3, 2, 1]
end

UserNodeScore.import columns, values
</pre>
<h2>Benchmarks</h2>
<p>I used a simple script to test each of the methods described here.</p>
<pre class="brush: ruby;">
require &quot;ar-extensions&quot;

CONN = ActiveRecord::Base.connection
TIMES = 10000

def do_inserts
	TIMES.times { UserNodeScore.create(:user_id =&gt; 1, :node_id =&gt; 2, :score =&gt; 3) }
end

def raw_sql
	TIMES.times { CONN.execute &quot;INSERT INTO `user_node_scores` (`score`, `updated_at`, `node_id`, `user_id`) VALUES(3.0, '2009-01-23 20:21:13', 2, 1)&quot; }
end

def mass_insert
	inserts = []
	TIMES.times do
		inserts.push &quot;(3.0, '2009-01-23 20:21:13', 2, 1)&quot;
	end
	sql = &quot;INSERT INTO user_node_scores (`score`, `updated_at`, `node_id`, `user_id`) VALUES #{inserts.join(&quot;, &quot;)}&quot;
	CONN.execute sql
end

def activerecord_extensions_mass_insert(validate = true)
	columns = [:score, :node_id, :user_id]
	values = []
	TIMES.times do
		values.push [3, 2, 1]
	end

	UserNodeScore.import columns, values, {:validate =&gt; validate}
end

puts &quot;Testing various insert methods for #{TIMES} inserts\n&quot;
puts &quot;ActiveRecord without transaction:&quot;
puts base = Benchmark.measure { do_inserts }

puts &quot;ActiveRecord with transaction:&quot;
puts bench = Benchmark.measure { ActiveRecord::Base.transaction { do_inserts } }
puts sprintf(&quot;  %2.2fx faster than base&quot;, base.real / bench.real)

puts &quot;Raw SQL without transaction:&quot;
puts bench = Benchmark.measure { raw_sql }
puts sprintf(&quot;  %2.2fx faster than base&quot;, base.real / bench.real)

puts &quot;Raw SQL with transaction:&quot;
puts bench = Benchmark.measure { ActiveRecord::Base.transaction { raw_sql } }
puts sprintf(&quot;  %2.2fx faster than base&quot;, base.real / bench.real)

puts &quot;Single mass insert:&quot;
puts bench = Benchmark.measure { mass_insert }
puts sprintf(&quot;  %2.2fx faster than base&quot;, base.real / bench.real)

puts &quot;ActiveRecord::Extensions mass insert:&quot;
puts bench = Benchmark.measure { activerecord_extensions_mass_insert }
puts sprintf(&quot;  %2.2fx faster than base&quot;, base.real / bench.real)

puts &quot;ActiveRecord::Extensions mass insert without validations:&quot;
puts bench = Benchmark.measure { activerecord_extensions_mass_insert(true)  }
puts sprintf(&quot;  %2.2fx faster than base&quot;, base.real / bench.real)
</pre>
<p>And the results:</p>
<pre class="brush: ruby;">
Testing various insert methods for 10000 inserts
ActiveRecord without transaction:
 14.930000   0.640000  15.570000 ( 18.898352)
ActiveRecord with transaction:
 13.420000   0.310000  13.730000 ( 14.619136)
  1.29x faster than base
Raw SQL without transaction:
  0.920000   0.170000   1.090000 (  3.731032)
  5.07x faster than base
Raw SQL with transaction:
  0.870000   0.150000   1.020000 (  1.648834)
  11.46x faster than base
Single mass insert:
  0.000000   0.000000   0.000000 (  0.268634)
  70.35x faster than base
ActiveRecord::Extensions mass insert:
  6.580000   0.280000   6.860000 (  9.409169)
  2.01x faster than base
ActiveRecord::Extensions mass insert without validations:
  6.550000   0.240000   6.790000 (  9.446273)
  2.00x faster than base
</pre>
<p>The results are fairly self-explainatory, but of particular note is the specific single INSERT statement. At 70x faster than the non-transactional ActiveRecord insert, if you need speed, it&#8217;s hard to beat.</p>
<h2>Conclusions</h2>
<p>ActiveRecord is great, but sometimes it&#8217;ll hold you back. Finding the balance between ease of use (full ActiveRecord) and performance (bare metal mass inserts) can have a profound effect on the performance of your app.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2009/01/23/mass-inserting-data-in-rails-without-killing-your-performance/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Re: Simple RoR+MySQL optimization</title>
		<link>http://www.coffeepowered.net/2008/09/30/re-simple-rormysql-optimization/</link>
		<comments>http://www.coffeepowered.net/2008/09/30/re-simple-rormysql-optimization/#comments</comments>
		<pubDate>Tue, 30 Sep 2008 21:42:44 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[garabge collector]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=58</guid>
		<description><![CDATA[I recently ran across a rather bare post espousing some generic &#8220;optimization&#8221; techniques for Rails apps. It offered no education, no explanation, no benchmarks. So, I thought, why not put those claims to the test? find_by_sql versus find_by_x First, Konstantin claims that Model#find_by_field is slower than Model#find_by_sql. This one is hard to dispute; the first [...]]]></description>
			<content:encoded><![CDATA[<p>I recently ran across a <a href="http://guruonrails.com/blog/simple-ror-mysql-optimization">rather bare post</a> espousing some generic &#8220;optimization&#8221; techniques for Rails apps. It offered no education, no explanation, no benchmarks. So, I thought, why not put those claims to the test?<br />
<span id="more-58"></span></p>
<h2>find_by_sql versus find_by_x</h2>
<p>First, Konstantin claims that <code>Model#find_by_field</code> is slower than <code>Model#find_by_sql</code>. This one is hard to dispute; the first will invoke method_missing and spend time generating SQL, while the latter simply executes a statement. Is cutting the knees out from under your ORM worth the time saved? Let&#8217;s see!</p>
<pre class="brush: ruby;">
require 'benchmark'

def measure_find_by_sql_vs_orm(num = 1000)
  puts &quot;find_by_sql (#{num}x)&quot;
  puts Benchmark.measure {
    num.times { User.find_by_sql &quot;select * from users where id = 123&quot; }
  }

  puts &quot;find_by_id (#{num}x)&quot;
  puts Benchmark.measure {
    num.times { User.find_by_id 123 }
  }
end

measure_find_by_sql_vs_orm(10000)
</pre>
<p>Let&#8217;s run this a few times.</p>
<pre><code>
[chris@polaris benchmarks]$ script/runner benchmark.rb
find_by_sql (10000x)
  2.290000   0.540000   2.830000 (  4.452150)
find_by_id (10000x)
  4.660000   0.400000   5.060000 (  6.766629)

[chris@polaris benchmarks]$ script/runner benchmark.rb
find_by_sql (10000x)
  2.300000   0.480000   2.780000 (  4.473950)
find_by_id (10000x)
  4.520000   0.560000   5.080000 (  6.837272)

[chris@polaris benchmarks]$ script/runner benchmark.rb
find_by_sql (10000x)
  2.170000   0.540000   2.710000 (  4.419207)
find_by_id (10000x)
  4.580000   0.540000   5.120000 (  6.881676)

find_by_sql: Averages 4.44 sec for 10,000 queries
find_by_id: Averages 6.83 sec for 10,000 queries
</code></pre>
<p>Conclusion the first: Using the ORM to build SQL adds some overhead; in my tests, 2.47 sec/10,000 queries, or 0.000247 seconds per query. Is this worth optimizing out? Yeah, probably not. In fact, the productivity lost by using <code>find_by_sql</code> is likely going to end up costing the project more.</p>
<h2>IDs and numbers in quotes</h2>
<p>Second, they claim that quoting values in your SQL statements slows down your queries. This one struck me as just a <em>little</em> out there. Let&#8217;s see what the benchmarks say.</p>
<pre class="brush: ruby;">
require 'benchmark'

def measure_select_with_quotes(num = 1000)
  puts &quot;Without quotes (#{num}x):&quot;
  db = ActiveRecord::Base.connection.instance_variable_get :@connection
  puts Benchmark.measure {
    num.times { db.query(&quot;select * from users where id = 123&quot;) {} }
  }

  puts &quot;With quotes (#{num}x):&quot;
  puts Benchmark.measure {
    num.times { db.query(&quot;select * from users where id = \&quot;123\&quot;&quot;) {} }
  }
end

measure_select_with_quotes(10000)
</pre>
<p>And the results:</p>
<pre><code>
[chris@polaris benchmarks]$ script/runner benchmark.rb
Without quotes (10000x):
  0.690000   0.340000   1.030000 (  2.639554)
With quotes (10000x):
  0.670000   0.290000   0.960000 (  2.655049)

[chris@polaris benchmarks]$ script/runner benchmark.rb
Without quotes (10000x):
  0.570000   0.320000   0.890000 (  2.654003)
With quotes (10000x):
  0.550000   0.400000   0.950000 (  2.617369)
</code></pre>
<p>Well, that&#8217;s certainly interesting. In 10,000 queries, an average difference of about 3/100ths of a second. Certainly not worth combing through your codebase as an optimization point.</p>
<p>Conclusion the second: The performance gain from quoted versus non-quoted field values is so small to be inconsequential.</p>
<p>On a side note, there is a <b>very</b> interesting subtlety here. Observe the difference between</p>
<pre class="brush: ruby;">
num.times { db.query(&quot;select * from users where id = 123&quot;) {} }
</pre>
<p>and </p>
<pre class="brush: ruby;">
num.times { db.query(&quot;select * from users where id = 123&quot;) }
</pre>
<p>The former passes the <code>Mysql::Result</code> object to a block, and frees it after the block terminates. The latter does not, and the returned <code>Mysql::Result</code> object remains in scope for the entire pass of the benchmark. This subtlety makes a massive difference.</p>
<pre class="brush: ruby;">
def measure_select_with_free(num = 1000)
  db = ActiveRecord::Base.connection.instance_variable_get :@connection

  puts &quot;Query with block, result immediately freed&quot;
  puts Benchmark.measure {
    num.times { db.query(&quot;select * from users where id = 123&quot;) {} }
  }

  puts &quot;Query without block, result remains in scope&quot;
  puts Benchmark.measure {
    num.times { db.query(&quot;select * from users where id = 123&quot;) }
  }
end
</pre>
<pre><code>
[chris@polaris benchmarks]$ script/runner benchmark.rb
Query with block, result immediately freed
  0.060000   0.040000   0.100000 (  0.267983)
Query without block, result remains in scope
  5.040000   0.050000   5.090000 (  5.266476)
</code></pre>
<p>Whoa damn. Ruby&#8217;s GC is <i>slaughtering</i> performance there. Just adding a pair of curly braces makes the benchmark run <i>20 times faster</i>.</p>
<h2>It&#8217;s better to request only specific column</h2>
<p>Finally, Konstantin mentions that selecting only specific fields from a table is faster. This is a truth in both MySQL and in the ActiveRecord ORM, for a number of reasons. However, he says that</p>
<blockquote><p>Person.find_by_name(&#8220;Name&#8221;).phone_number. It would be much faster if you use: Person.find_by_sql(&#8220;SELECT persons.phone_number WHERE persons.name = &#8216;Name&#8217;&#8221;) </p></blockquote>
<p>Why not just use the :select option that ActiveRecord provides?</p>
<pre class="brush: ruby;">
Person.find_by_name(&quot;Name&quot;, :select =&gt; &quot;phone_number&quot;)
</pre>
<p>Let&#8217;s test those assumptions.</p>
<pre class="brush: ruby;">
def measure_single_field_select(num = 1000)
  puts &quot;Find with all fields&quot;
  puts Benchmark.measure {
    num.times { User.find_by_id(123)}
  }

  puts &quot;Find with one field, with :select&quot;
  puts Benchmark.measure {
    num.times { User.find_by_id(123, :select =&gt; &quot;email&quot;)}
  }
end
</pre>
<pre><code>
[chris@polaris benchmarks]$ script/runner benchmark.rb
Find with all fields
  0.720000   0.060000   0.780000 (  0.963273)
Find with one field, with :select
  0.310000   0.010000   0.320000 (  0.364554)

[chris@polaris benchmarks]$ script/runner benchmark.rb
Find with all fields
  0.710000   0.110000   0.820000 (  1.014548)
Find with one field, with :select
  0.260000   0.020000   0.280000 (  0.351761)
</code></pre>
<p>Very significant difference there&#8230;and we didn&#8217;t have to bypass the ORM to get it, either.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2008/09/30/re-simple-rormysql-optimization/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Powerful, easy, DRY, multi-format REST APIs</title>
		<link>http://www.coffeepowered.net/2008/09/27/powerful-easy-dry-multi-format-rest-apis/</link>
		<comments>http://www.coffeepowered.net/2008/09/27/powerful-easy-dry-multi-format-rest-apis/#comments</comments>
		<pubDate>Sun, 28 Sep 2008 03:53:48 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[jsonp]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[yaml]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=38</guid>
		<description><![CDATA[Rails&#8217; baked-in REST support is great. Build your app right, and you can expose a programmatic interface to your users for free. That said, many times providing views in non-HTML formats tends to be bulky and unwieldy. You end up with either very brittle representations of your data, or extremely bulky respond_to blocks in your [...]]]></description>
			<content:encoded><![CDATA[<p>Rails&#8217; baked-in REST support is great. Build your app right, and you can expose a programmatic interface to your users for free.</p>
<p>That said, many times providing views in non-HTML formats tends to be bulky and unwieldy. You end up with either very brittle representations of your data, or extremely bulky respond_to blocks in your controllers.</p>
<p>Fortunately, there&#8217;s a better way! We&#8217;re going to provide two new render targets, <code>:to_yaml</code> and <code>:to_json</code> which will let us write a single XML builder view, and then provide that view in XML, YAML, and JSON formats according to the consuming developer&#8217;s preferences.</p>
<p>In <code>application.rb</code> you&#8217;ll want to override the render method.</p>
<pre class="brush: ruby;">
def render(opts = {}, &amp;block)
  if opts[:to_yaml] then
    headers[&quot;Content-Type&quot;] = &quot;text/plain;&quot;
    render :text =&gt; Hash.from_xml(render_to_string(:template =&gt; opts[:to_yaml], :layout =&gt; false)).to_yaml, :layout =&gt; false
  elsif opts[:to_json] then
    content = Hash.from_xml(render_to_string(:template =&gt; opts[:to_json], :layout =&gt; false)).to_json
    cbparam = params[:callback] || params[:jsonp]
    content = &quot;#{cbparam}(#{content})&quot; unless cbparam.blank?
    render :json =&gt; content, :layout =&gt; false
  else
    super opts, &amp;block
  end
end
</pre>
<p>As you can see, we render a single XML view, and then load it to a hash from XML, and use Rails&#8217; built-in <code>Hash#to_json</code> and <code>Hash#to_yaml</code> methods to provide the data in the desired format. There is a single glaring problem with this approach, though &#8211; <code>Hash#from_xml</code> is <em>dog slow</em> because it uses REXML. There&#8217;s a fantastic solution, though!</p>
<p>Courtesy of a blog post over at <a href="http://www.visnup.com/entries/423-cobravsmongoose-not-slow-vs-hashfrom_xml-slow-vs-faster_xml_simple-fast">cobravsmongoose</a>, we have a libxml drop-in for <code>Hash#from_xml</code></p>
<p>First, install <a href="http://libxml.rubyforge.org/">libxml</a> and then <a href="http://code.google.com/p/faster-xml-simple/">faster_xml_simple</a>.</p>
<p>Second, include a monkeypatch to <code>Hash#from_xml</code> with the following:</p>
<pre class="brush: ruby;">
require 'faster_xml_simple'
class Hash
  def self.from_xml(xml)
    undasherize_keys(typecast_xml_value(FasterXmlSimple.xml_in(xml,
      'forcearray'   =&gt; false,
      'forcecontent' =&gt; true,
      'keeproot'     =&gt; true,
      'contentkey'   =&gt; '__content__')
    ))
  end
end
</pre>
<p>You can run the benchmarks if you&#8217;d like, but it&#8217;s orders of magnitude faster than REXML. Seriously. Don&#8217;t use REXML. It&#8217;s like trying to run a Ferrari off of a 9-volt battery.</p>
<p>Now, let&#8217;s say you have an action you want to provide HTML, XML, JSON, and YAML views for.</p>
<pre class="brush: ruby;">
def index
  ...
  respond_to do |wants|
    wants.html
    wants.xml  { render :layout =&gt; false }
    wants.json { render :to_json =&gt; &quot;posts/index.xml.builder&quot; }
    wants.yaml { render :to_yaml =&gt; &quot;posts/index.xml.builder&quot; }
  end
end
</pre>
<p>Finally, throw together your <code>index.xml.builder</code> file as you best see fit.</p>
<pre class="brush: ruby;">
xml.instruct! :xml, :version=&gt;&quot;1.0&quot;, :encoding=&gt;&quot;UTF-8&quot;
xml.posts do
  @posts.each do |post|
    xml.post(:id =&gt; post.id) do
      xml.user(:id =&gt; post.user.id) +
      xml.content do
        post.post_body
      end
    end
  end
end
</pre>
<p>And all of a sudden, bam! You&#8217;ve got your posts available in HTML&#8230;</p>
<pre><code>/posts/index</code></pre>
<p>&#8230;and in XML, YAML, and JSON, along with the associated User. By using an XML builder, you can make the serialized data as complex and customized as you&#8217;d like. No more funky respond_to blocks, no more exposing data you don&#8217;t want to. Expose what you want, and just what you want, in several formats.</p>
<pre><code>
/posts/index.xml
/posts/index.yml
/posts/index.json
</code></pre>
<p>One final trick is that the JSON views accept an optional <code>callback</code> or <code>jsonp</code> parameter, which will cause the content to be passed to a Javascript function matching the passed parameter, as per the <a href="http://ajaxian.com/archives/jsonp-json-with-padding">JSONP</a> spec.</p>
<p>For example, if you have a <code>/foo/bar.json</code> view that would render the following JSON:</p>
<pre><code>"{\"foo\":\"bar\"}"</code></pre>
<p>Calling <code>/foo/bar.json?jsonp=returnFunc</code> would return the following:</p>
<pre><code>returnFunc("{\"foo\":\"bar\"}")</code></pre>
<p>Check out the <a href="http://ajaxian.com/archives/jsonp-json-with-padding">JSONP</a> spec for more.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2008/09/27/powerful-easy-dry-multi-format-rest-apis/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Hold the RJS, please.</title>
		<link>http://www.coffeepowered.net/2008/09/26/hold-the-rjs-please/</link>
		<comments>http://www.coffeepowered.net/2008/09/26/hold-the-rjs-please/#comments</comments>
		<pubDate>Sat, 27 Sep 2008 00:00:35 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[erb]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[rjs]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=30</guid>
		<description><![CDATA[Rails does a great job at many things, but one of the most consistent stumbling blocks I see in #rubyonrails is RJS. It complicates many things that just don&#8217;t need to be that complex, especially when using a Javascript helper library like Prototype or jQuery. Keep things simple! One little helper, and your AJAX requests [...]]]></description>
			<content:encoded><![CDATA[<p>Rails does a great job at many things, but one of the most consistent stumbling blocks I see in <a href="http://wiki.rubyonrails.org/rails/pages/IRC">#rubyonrails</a> is RJS. It complicates many things that just don&#8217;t need to be that complex, especially when using a Javascript helper library like <a href="http://prototypejs.org/">Prototype</a> or <a href="http://jquery.com/">jQuery</a>.</p>
<p>Keep things simple! One little helper, and your AJAX requests get a whole lot easier to manage. This was inspired by the now-defunct <a href="http://www.danwebb.net/2006/11/24/minusmor-released">MinusMOR</a>.</p>
<pre class="brush: ruby;">
def js(data)
  data.respond_to?(:to_json) &amp;&amp; data.to_json || data.inspect.to_json
end
</pre>
<p>Now, when you want to render a Javascript view, you can use just straight Javascript. For example, if you would like to update a given element in your page with the contents of a partial, save a template, something like <code>update.js.erb</code>, with the following:</p>
<pre class="brush: jscript;">$(&quot;div#post_&lt;%=@post.id%&gt;&quot;).update(&lt;%=js render(:partial =&gt; &quot;post.html.erb&quot;, :object =&gt; @post) %&gt;);</pre>
<p>This is admittedly more complex than RJS in the simple case, but what about when you want to do more complex stuff, like this <code>vote.js.erb</code> template?</p>
<pre class="brush: jscript;">
&lt;% unless @msg.nil? %&gt;
statusMessage(&lt;%=js @msg%&gt;);
&lt;% end %&gt;
var obj = $$('div#post_&lt;%=@post.id%&gt; span.vote a');
for(var i=0; i&lt;obj.length; i++) {
	var e = obj[i];
	e.update(&lt;%=js &quot;+#{@post.vote_score}&quot;%&gt;);
	e.addClassName(&quot;voted_post&quot;);
}
</pre>
<p>Just as easy as writing any of your other views, and won&#8217;t get in your way when you need to go some fancy Javascript gymnastics without requiring ugly heredocs cluttering up the code all over.</p>
<p>How about passing an <code>Array</code> to a client-side Javascript function?</p>
<pre class="brush: jscript;">
runSomeUpdateFunctionThatTakesAJavascriptArray(&lt;%=js @list_of_values %&gt;)
</pre>
<p>No worries about malformed Javascript!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2008/09/26/hold-the-rjs-please/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using memcached
Page Caching using memcached
Database Caching 12/19 queries in 0.012 seconds using memcached

Served from: www.coffeepowered.net @ 2010-09-07 06:16:36 -->