<?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>All Things (v8)</title>
	<atom:link href="http://www.anthonyeden.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.anthonyeden.com</link>
	<description>Technology Blog</description>
	<lastBuildDate>Tue, 16 Feb 2010 22:08:11 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>XSS and Building HTML in JavaScript</title>
		<link>http://www.anthonyeden.com/2010/02/xss-and-building-html-in-javascript/</link>
		<comments>http://www.anthonyeden.com/2010/02/xss-and-building-html-in-javascript/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 22:04:31 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[ujs]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=123</guid>
		<description><![CDATA[In my recent article on Rails, JQuery, Unobtrusive JS and Graceful Degradation I implemented the Ajax logic for adding a new entry using JSON returned from the server to build the HTML in JavaScript. An attentive reader brought to my attention the cross-site scripting vulnerability that is possible with this implementation and I think this [...]]]></description>
			<content:encoded><![CDATA[<p>In my recent article on <a href="http://www.anthonyeden.com/2010/02/rails-jquery-unobtrusive-js-and-graceful-degradation/">Rails, JQuery, Unobtrusive JS and Graceful Degradation</a> I implemented the Ajax logic for adding a new entry using JSON returned from the server to build the HTML in JavaScript. An attentive reader brought to my attention the cross-site scripting vulnerability that is possible with this implementation and I think this would be a good time to address the issue and open the comments to other options.</p>
<p>First of all let&#8217;s look at the most obvious attack vector, which is pretty simple: a malicious user would enter a script into the person name field and save that and then it would execute the script when the person is rendered in the person list. First I verified that this attack vector worked, and yes it did work, so then I considered where the value entered by the user needed to be sanitized. It&#8217;s pretty straightforward to sanitize the rendering when Rails is involved, just add the <code>h()</code> helper before the name output in the listing, so line 4 of index.html.erb becomes:</p>
<p><script src="http://gist.github.com/305978.js?file=gistfile1.rhtml"></script></p>
<p>This is a fairly standard idiom in Rails (not necessarily the best way to sanitize user input, but the most common way to do it). This fix only fixes the problem when the page is rendered by Rails, but it does not address the issue for items that are added via Ajax, and here is where things get a bit tricky.</p>
<p>You&#8217;d think that sanitizing user input in JavaScript would be fairly easy, and to be clear you can do it with the JavaScript <code>escape()</code> function, however this results in some pretty ugly percent-encoded content (which may or may not matter to you. I was curious though whether there was something similar to the <code>h()</code> helper in Rails available in JavaScript. There is but finding it proved to be a bit of a challenge.</p>
<p>What I ended up doing what searching <a href="http://stackoverflow.com/">Stack Overflow</a> for solutions that others had come up with and eventually landed upon this bit of code: <a href="http://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/plugin/html-sanitizer.js">http://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/plugin/html-sanitizer.js</a>. Unfortunately this bit of code by itself doesn&#8217;t work unless you have another JS library (html4) and that library requires building with Ant. Fortunately additional searching led me to a minified version with everything already compiled. I&#8217;ve included this minified library as html-sanitizer-minified.js and added a call to html_santize before rendering the person name in the JavaScript as such:</p>
<p><script src="http://gist.github.com/305989.js?file=gistfile1.js"></script></p>
<p>..and it works. I&#8217;ve deployed this fix to <a href="http://rails-jquery-unobtrusive.heroku.com/">http://rails-jquery-unobtrusive.heroku.com/</a> and have updated the <a href="http://github.com/aeden/unobtrusive-jquery-example">github repo</a> so you can see the changes in action.</p>
<p>So is this the best solution for handling user input and avoiding XSS when you want to build HTML in JavaScript? I&#8217;m not sure. It&#8217;s probably not the only solution so feel free to add yours in the comments below. Also, consider this a warning if you are developing JavaScript code that builds and renders HTML: tainted user input is a threat and you need to deal with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2010/02/xss-and-building-html-in-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Aloha on Rails Talk Online</title>
		<link>http://www.anthonyeden.com/2010/02/aloha-on-rails-talk-online/</link>
		<comments>http://www.anthonyeden.com/2010/02/aloha-on-rails-talk-online/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 17:52:37 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Presentations]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=121</guid>
		<description><![CDATA[Well look at that, the video for my talk from Aloha on Rails is online now. Go check it out if you&#8217;re interested in identifying and reducing your technical debt.
]]></description>
			<content:encoded><![CDATA[<p>Well look at that, the video for <a href="http://www.alohaonrails.com/2010/02/09/technical-debt-video-by-anthony-eden-now-online/">my talk from Aloha on Rails is online now</a>. Go check it out if you&#8217;re interested in identifying and reducing your technical debt.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2010/02/aloha-on-rails-talk-online/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rails, JQuery, Unobtrusive JS and Graceful Degradation</title>
		<link>http://www.anthonyeden.com/2010/02/rails-jquery-unobtrusive-js-and-graceful-degradation/</link>
		<comments>http://www.anthonyeden.com/2010/02/rails-jquery-unobtrusive-js-and-graceful-degradation/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 21:50:24 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[ujs]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=115</guid>
		<description><![CDATA[I&#8217;m always on the lookout for ways to improve my web applications. To that end I wanted to see if I could come up with a way to marry jQuery and Rails in a way that was both unobtrusive and a way that would degrade gracefully in a Rails 2.3.5 application. I&#8217;m looking forward to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m always on the lookout for ways to improve my web applications. To that end I wanted to see if I could come up with a way to marry jQuery and Rails in a way that was both unobtrusive and a way that would degrade gracefully in a Rails 2.3.5 application. I&#8217;m looking forward to seeing how UJS with jQuery in Rails looks as of Rails 3.0, however in the meantime the method I describe below may prove to be useful.</p>
<p>If you want to go straight to the code it is available on Github: <a href="http://github.com/aeden/unobtrusive-jquery-example">http://github.com/aeden/unobtrusive-jquery-example</a>. I have also put a live demo on this up on Heroku: <a href="http://rails-jquery-unobtrusive.heroku.com">http://rails-jquery-unobtrusive.heroku.com</a>.</p>
<p>Rather than going through all of the steps needed to set up a Rails app, the best thing to do is to follow along in the code from the example above.</p>
<p>First let&#8217;s take a look at the PeopleController (app/controllers/people_controller.rb):</p>
<p><script src="http://gist.github.com/296266.js?file=gistfile1.rb"></script></p>
<p>This looks like a fairly normal RESTful controller. The one exception is the delete method, which will be used by browsers that have JavaScript turned off to provide a page that 1.) confirms that the record should be deleted and 2.) has a form that can post to the destroy method.</p>
<p>Next, let&#8217;s take a look at the index view:</p>
<p><script src="http://gist.github.com/296269.js?file=gistfile1.rhtml"></script></p>
<p>There is a list of people with each person having a delete link next to their name. The delete link points to /person/:id/delete which will execute the delete action that I mentioned above (I&#8217;ll show you how to remove the &#8220;/delete&#8221; part of that link with JavaScript later). There is also a form for adding a new person. Note that there is no JavaScript in this page, just normal HTML elements with classes.</p>
<p>While we&#8217;re looking at views, let&#8217;s look at the only other view, the delete view:</p>
<p><script src="http://gist.github.com/296270.js?file=gistfile1.rhtml"></script></p>
<p>This is just a simple form that confirms that they want to delete the user and provides a cancel link back to the people_url if they don&#8217;t. Note that the form tag uses the REST-ful URL for accessing the resource and sets &#8216;_method&#8217; to &#8216;delete&#8217; in the hidden field tag.</p>
<p>Finally, let&#8217;s take a look at the most complicated bit, the jQuery JavaScript. To make things easier to follow I&#8217;ll go through it piece by piece, starting with the document ready handler:</p>
<p><script src="http://gist.github.com/296271.js?file=gistfile1.js"></script></p>
<p>This is the jQuery way for executing code when the document has finished loading. All it does is call two methods, one for connecting up the add form and one for connecting up the delete links. To keep things organized and namespaced a bit I placed these two methods onto a JS object called &#8216;Actions&#8217;. First, the connectAddForm implementation:</p>
<p><script src="http://gist.github.com/296272.js?file=gistfile1.js"></script></p>
<p>This function finds the form element with the class &#8220;people&#8221; and attaches an event handler to the submit event. When the form is submitted an AJAX POST is made. The data type is JSON, which will call the &#8216;create&#8217; action in the people controller with the accepts type set to a value that triggers Rails to render JSON as the response. The form is serialized and passed as data and when a successful response is received a bit of HTML is appended to the people list and the person name field is cleared.</p>
<p>Now for the connect delete links JavaScript:</p>
<p><script src="http://gist.github.com/296273.js?file=gistfile1.js"></script></p>
<p>Here each element that is in the people list that matches the selector a.delete and adds a click handler to it. Notice that I used the jQuery live method here, the benefit being that as new records are added, and new elements that match the selector expression are added automatically get the click handler that I define here. This saves me from the trouble of having to add the handler each time that a record is added to the page. The click handler first finds the li that it may eventually delete, displays a confirmation message to the viewer and if they confirm that they want to delete the record it will post via AJAX to the /person/:id URL with the method &#8216;delete&#8217;. The URL is pulled from the anchor&#8217;s href attribute and the &#8216;/delete&#8217; is removed using a simple regular expression replace. Upon a successful delete the li that was found earlier is hidden using the slideToggle() function.</p>
<p>That&#8217;s it. You can try this in a browser either with JavaScript turned on, in which case it&#8217;ll use all of the JavaScript goodness, or you can turn of JavaScript and see the magic of graceful degradation. I hope you&#8217;ve enjoyed reading this little tutorial and if you have any suggestions on how to improve the code in the project please feel free to fork the github project, make your changes and send me a pull request. I&#8217;ll add any cool mods into the tutorial as I can.</p>
<p><b>Update:</b> I&#8217;ve <a href="http://www.anthonyeden.com/2010/02/xss-and-building-html-in-javascript/">published a follow-on article</a> that talks about changes to the code for this tutorial to handle sanitizing user input both in Rails and in JavaScript. I suggest reading it to understand XSS vulnerabilities that you need to deal with when accepting user input.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2010/02/rails-jquery-unobtrusive-js-and-graceful-degradation/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Aloha on Rails &#8211; Technical Debt Slides</title>
		<link>http://www.anthonyeden.com/2009/10/aloha-on-rails-technical-debt-slides/</link>
		<comments>http://www.anthonyeden.com/2009/10/aloha-on-rails-technical-debt-slides/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 07:55:42 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[alohaonrails]]></category>
		<category><![CDATA[presentation]]></category>
		<category><![CDATA[refactoring]]></category>
		<category><![CDATA[technical debt]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=111</guid>
		<description><![CDATA[Thanks to everyone who came out to Aloha on Rails and a huge mahalo to Seth for putting so much into it. It was awesome.
Here are the slides for my talk: Technical Debt . I&#8217;ve left the presenter notes in so you can see what I was thinking when I put the slide together (since [...]]]></description>
			<content:encoded><![CDATA[<p>Thanks to everyone who came out to <a href="http://alohaonrails.com">Aloha on Rails</a> and a huge mahalo to <a href="http://blog.semergence.com/">Seth</a> for putting so much into it. It was awesome.</p>
<p>Here are the slides for my talk: <a href="http://www.anthonyeden.com/wp-content/uploads/2009/10/Technical-Debt.pdf">Technical Debt</a> . I&#8217;ve left the presenter notes in so you can see what I was thinking when I put the slide together (since most of the slides are just pictures anyhow.) Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2009/10/aloha-on-rails-technical-debt-slides/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SDC Hawaii LLC &#8211; Agile Web Development in Paradise</title>
		<link>http://www.anthonyeden.com/2009/10/sdc-hawaii-llc-agile-web-development-in-paradise/</link>
		<comments>http://www.anthonyeden.com/2009/10/sdc-hawaii-llc-agile-web-development-in-paradise/#comments</comments>
		<pubDate>Sun, 04 Oct 2009 18:16:51 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[consulting]]></category>
		<category><![CDATA[contracting]]></category>
		<category><![CDATA[sdchawaii]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=109</guid>
		<description><![CDATA[Over the last year-and-a-half (maybe even longer), we at SDC Hawaii LLC have been working hard on building dotMP, chi.mp and other projects for a Saipan-based company. We&#8217;ve decided that the time is right to start taking on new contracts, so as of Friday SDC Hawaii LLC is available for custom web application development. We&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>Over the last year-and-a-half (maybe even longer), we at SDC Hawaii LLC have been working hard on building dotMP, chi.mp and other projects for a Saipan-based company. We&#8217;ve decided that the time is right to start taking on new contracts, so as of Friday SDC Hawaii LLC is available for custom web application development. We&#8217;ve even rolled out <a href="http://sdchawaii.com/">a brand new SDC Hawaii LLC web site</a>.</p>
<p>So what do you get if you contract the SDC Hawaii team? How about this: you get 4 top notch Ruby developers, including yours truly, along with one awesome designer/UX expert, who are ready to bend over backwards to make sure that your web application is designed, tested and implemented with great care. We are all passionate about web application development and put our hearts and souls into everything we create. Our team is well-versed in agile development, with daily stand-ups, pair programming and test-driven development. And finally we have extensive experience with Amazon&#8217;s Web Services including S3, EC2, SQS and Elastic Map Reduce.</p>
<p>So come on over to the <a href="http://sdchawaii.com/">SDC Hawaii web site</a> and contact us if you&#8217;re interested in having our team develop your next web application.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2009/10/sdc-hawaii-llc-agile-web-development-in-paradise/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Moving from blog.anthonyeden.com to anthonyeden.com</title>
		<link>http://www.anthonyeden.com/2009/08/moving-from-blog-anthonyeden-com-to-anthonyeden-com/</link>
		<comments>http://www.anthonyeden.com/2009/08/moving-from-blog-anthonyeden-com-to-anthonyeden-com/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 01:04:40 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[blog move]]></category>

		<guid isPermaLink="false">http://www.anthonyeden.com/?p=106</guid>
		<description><![CDATA[At some point the DNS should update and should be proper. In the meantime http://blog.anthonyeden.com/ looks like it&#8217;s broken. Just go to http://anthonyeden.com/
]]></description>
			<content:encoded><![CDATA[<p>At some point the DNS should update and should be proper. In the meantime <a href="http://blog.anthonyeden.com/">http://blog.anthonyeden.com/</a> looks like it&#8217;s broken. Just go to <a href="http://anthonyeden.com/">http://anthonyeden.com/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2009/08/moving-from-blog-anthonyeden-com-to-anthonyeden-com/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Profiling JRuby</title>
		<link>http://www.anthonyeden.com/2009/08/profiling-jruby/</link>
		<comments>http://www.anthonyeden.com/2009/08/profiling-jruby/#comments</comments>
		<pubDate>Wed, 26 Aug 2009 19:00:54 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[chi.mp]]></category>
		<category><![CDATA[refinery jruby profiling]]></category>

		<guid isPermaLink="false">http://anthonyeden.wordpress.com/?p=102</guid>
		<description><![CDATA[Writing multi-threaded applications is quite a challenging task, but perhaps even more challenging is debugging them when they don&#8217;t work as you expect. These past couple of weeks I&#8217;ve been working hard to troubleshoot issues with a distributed processing system built on Refinery. When running with a relatively small number of threads things work fine [...]]]></description>
			<content:encoded><![CDATA[<p>Writing multi-threaded applications is quite a challenging task, but perhaps even more challenging is debugging them when they don&#8217;t work as you expect. These past couple of weeks I&#8217;ve been working hard to troubleshoot issues with a distributed processing system built on <a href="http://github.com/aeden/refinery">Refinery</a>. When running with a relatively small number of threads things work fine &#8211; processing goes about its merry way at a level of throughput that is expected. As soon as we increase the number of threads though, all hell breaks loose.</p>
<p>As part of the troubleshooting process we decided to hook up a profiler. I started out looking at the profiler that&#8217;s built into JRuby (use the &#8211;sample option) and got a little bit of data. Urged on by <a href="http://twitter.com/dje">@dje</a> I started looking at Java profilers. It&#8217;s been a while since I&#8217;ve dug into the world of Java so I started with open source tools to get my bearings. Suffice to say I did not find what I was looking for there, so I did what any self-respecting Internet-savvy being would do in my place: I twittered it.</p>
<p>Thanks to <a href="http://twitter.com/sethladd">@sethladd</a> I downloaded <a href="http://www.yourkit.com/">YourKit</a>, got it hooked up in about 30 minutes with the production system and away I went. The results so far have been promising. Some of the issues that could be fixed have, however we are basically at a point where we&#8217;ve run into a wall with Ruby&#8217;s Net::HTTP implementation. The long term solution is probably to replace the Net::HTTP library with something based on the Reactor pattern (see my <a href="http://github.com/aeden/jruby-http-reactor">jruby-http-reactor</a> project for the initial baby-steps in that direction) but the bottom line is without a profiler to help us get headed on the right path we probably would have spent a lot more time &#8220;fixing&#8221; things that weren&#8217;t broken. If you&#8217;re considering using JRuby consider that you will have access to a wide variety of Java tools that can be quite helpful when troubleshooting.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2009/08/profiling-jruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Browser on VMWare Talking to Server on Host</title>
		<link>http://www.anthonyeden.com/2009/05/browser-on-vmware-talking-to-server-on-host/</link>
		<comments>http://www.anthonyeden.com/2009/05/browser-on-vmware-talking-to-server-on-host/#comments</comments>
		<pubDate>Fri, 29 May 2009 12:51:04 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Flotsam]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[vmware tricks]]></category>

		<guid isPermaLink="false">http://blog.anthonyeden.com/2009/05/29/browser-on-vmware-talking-to-server-on-host/</guid>
		<description><![CDATA[One of the things I have been meaning to do for a while is set up VMWare so I can run a browser on WinXP that connects to a server running in OS X. I finally did that this morning. Here&#8217;s how:
1.) Follow the instructions here (Rob Sanheim, FTW): http://robsanheim.com/2007/12/11/creating-a-static-loopback-address-to-use-in-vmware/
2.) If you provide a different [...]]]></description>
			<content:encoded><![CDATA[<p>One of the things I have been meaning to do for a while is set up VMWare so I can run a browser on WinXP that connects to a server running in OS X. I finally did that this morning. Here&#8217;s how:</p>
<p>1.) Follow the instructions here (Rob Sanheim, FTW): <a href="http://robsanheim.com/2007/12/11/creating-a-static-loopback-address-to-use-in-vmware/">http://robsanheim.com/2007/12/11/creating-a-static-loopback-address-to-use-in-vmware/</a></p>
<p>2.) If you provide a different interface depending on the requested host name, then Edit C:\WINDOWS\system32\drivers\etc\hosts to point 10.0.0.100 (or whatever IP address you selected in step 1 to a hostname (for example local.mysite.com).</p>
<p>That&#8217;s pretty much it. I noticed that I had to restart IE for it to recognize the new hosts file changes, but otherwise it works like a charm.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2009/05/browser-on-vmware-talking-to-server-on-host/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ensure has_one Instance Exists</title>
		<link>http://www.anthonyeden.com/2009/05/ensure-has_one-instance-exists/</link>
		<comments>http://www.anthonyeden.com/2009/05/ensure-has_one-instance-exists/#comments</comments>
		<pubDate>Wed, 20 May 2009 18:48:28 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[has_one]]></category>

		<guid isPermaLink="false">http://blog.anthonyeden.com/?p=87</guid>
		<description><![CDATA[Sometimes you want to ensure that a has_one relationship always exists, even if the relationship is added after existing instances have already been created in your database. One way to solve the problem is to add an after_create and then have a rake task go through your database and create instances in each case where [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes you want to ensure that a has_one relationship always exists, even if the relationship is added after existing instances have already been created in your database. One way to solve the problem is to add an after_create and then have a rake task go through your database and create instances in each case where the has_one instance doesn&#8217;t yet exist.</p>
<p>I think the following is more elegant:</p>
<pre>
  has_one :thing
  def thing_with_create
    thing_without_create || create_thing
  end
  alias_method_chain :thing, :create
</pre>
<p>I can then access o.thing and it will automatically create it if it doesn&#8217;t exist.</p>
<p>What do you think?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2009/05/ensure-has_one-instance-exists/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Capistrano, Rails and Amazon CloudFront</title>
		<link>http://www.anthonyeden.com/2009/04/capistrano-rails-and-amazon-cloudfront/</link>
		<comments>http://www.anthonyeden.com/2009/04/capistrano-rails-and-amazon-cloudfront/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 18:17:34 +0000</pubDate>
		<dc:creator>Anthony</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[amazon web services]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[cloudfront]]></category>

		<guid isPermaLink="false">http://blog.anthonyeden.com/?p=66</guid>
		<description><![CDATA[Amazon CloudFront (ACF), the content delivery network that is now part of Amazon's Web Services provides a simple means of deploying content to a fast, low-cost global content delivery network. As part of our deployment process for chi.mp we now deploy our static assets to ACF. Here's how we do it.]]></description>
			<content:encoded><![CDATA[<p><a href="http://aws.amazon.com/cloudfront/">Amazon CloudFront (ACF)</a>, the content delivery network that is now part of Amazon&#8217;s Web Services provides a simple means of deploying content to a fast, low-cost global content delivery network. As part of our deployment process for chi.mp we now deploy our static assets to ACF (well, technically this will be deployed as part of the next release). Here&#8217;s how we do it: <a href="http://gist.github.com/95255">http://gist.github.com/95255</a>.</p>
<p>Let&#8217;s go through this piece by piece:</p>
<p><code><br />
# get the previous timestamp<br />
old_timestamp = File.read("config/deploy_timestamp").to_i rescue 0<br />
</code></p>
<p>The first step is to get the previous timestamp. This will be saved in memory and compared against file modification times to determine if a put or a copy should be used.</p>
<pre>
# generate timestamp into config/deploy_timestamp
timestamp = Time.now.to_i
File.open("config/deploy_timestamp", 'w') do |f|
  f.write(timestamp)
end
</pre>
<p>The next step is to update the time stamp file and store the new time stamp in memory.</p>
<pre>
# generate minified JS and CSS
system('rake asset:packager:build_all')
</pre>
<p>This portion uses the asset packager plugin for Rails to package up JS and CSS files into bundled assets.</p>
<pre>
# sync local public/ directory to S3 bucket
# the S3 bucket directory should be the
#  timestamp generated above
require 'right_aws'
s3 = RightAws::S3.new(access_key_id, secret_access_key)
bucket = s3.bucket('a-bucket')
</pre>
<p>Here we connect to S3 using RightScale&#8217;s RightAws library. You will need to put your access key ID and secret access key into the variables provided. The bucket name should be a bucket that has already been set up as an Amazon CloudFront S3 source. Documentation on how to set up a CloudFront configuration can be found in the <a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/GettingStartedGuide/">ACF Getting Started Guide</a>.</p>
<pre>
put_count = 0
copy_count = 0
Dir.glob('public/**/*').each do |f|
  next if File.directory?(f)
  key = "#{timestamp}/#{f.gsub(/public\//, '')}"
  if File.new(f).mtime.to_i &gt; old_timestamp
    puts "putting #{f} into S3 as #{key}"
    bucket.put(key, File.read(f), {}, 'public-read')
    put_count += 1
  else
    old_key = bucket.key(
      "#{old_timestamp}/#{f.gsub(/public\//, '')}"
    )
    if old_key.exists?
      puts "copying #{old_key} to #{key}"
      old_key.copy(key)

      acl = s3.interface.get_acl(bucket.name, old_key.name)
      s3.interface.put_acl(bucket.name, new_key.name, acl[:object])

      copy_count += 1
    else
      puts "putting #{f} into S3 as #{key}"
      bucket.put(key, File.read(f), {}, 'public-read')
      put_count += 1
    end
  end
end
puts "done. #{put_count} files uploaded,
  #{copy_count} keys copied"
</pre>
<p>This code loops through all of the files and directories in the <code>public</code> directory and for any file it first checks to see if the file modification time is after the previous timestamp. If it is then the data from the file will be pushed to S3 using a key that is the file path prefixed with the time stamp. If the modification time is before the previous time stamp then the file hasn&#8217;t changed. In this case the script will look up the old key in S3. If the old key exists then <code>key.copy()</code> is used to make a copy of the resource (reducing the time required to process large files) and set the ACL to the old key&#8217;s ACL. If the key does not exist then the file data will be put into S3.</p>
<p>The S3 key is always prefixed with the time stamp. This is done because Amazon CloudFront will cache files for a minimum of 24 hours. If you were to release a new version of an asset and overwrite the old asset in S3 it could be quite some time before ACF would pick up the change. By prefixing the key with the time stamp you will always get the latest version as long as the asset host is configured properly in your Rails application (more on that in a bit).</p>
<pre>
# add and commit the config/deploy_timestamp file
system('git add config/deploy_timestamp')
system('git commit -m "deploy_assets complete,
   updating timestamp"')
system('git push')
</pre>
<p>This last little bit of code commits the updated deploy_timestamp file into the git repository and pushes it to the remote repo. This works for us because we use Github. If you do not then you&#8217;d want to adjust these lines to push the file into your source code repository.</p>
<p>The last piece of the puzzle is to set the asset host in Rails. Here&#8217;s what that might look like:</p>
<pre>
ts_file = File.join(RAILS_ROOT, "config/deploy_timestamp")
ts = File.read(ts_file).to_i
config.action_controller.asset_host = Proc.new { |source, request|
  if request.ssl?
    "https://yoursite.com"
  else
    "http://cdn.yoursite.com/#{ts}"
  end
}
</pre>
<p>This code can go either in your config block in <code>config/environment.rb</code> or in specific environment configs. You&#8217;ll also need to set up a CNAME record pointing cdn.yoursite.com to your Amazon CDN host. If you aren&#8217;t using Rails you&#8217;d still need some way to indicate that all images should be originating from Amazon CloudFront. Note that resources requested from SSL encrypted pages must still go to your SSL-enabled servers since CloudFront does not support SSL at this time.</p>
<p>One final caveat: if you are using images that are specified in stylesheets you&#8217;ll need to ensure that you use relative paths to those images.</p>
<p><del datetime="2009-05-29T14:48:01+00:00"><strong>Update 1</strong> It turns out that when you copy a key in S3 the original key ACL is not retained. This is unfortunate since it means copied assets will now be marked private. Furthermore it appears that RightAWS does not support URI-based group identifiers for S3 ACLs, which means there is no way to change the permissions on a copied key to public-read. It seems likely that I can switch to another S3 lib to get this functionality, but that&#8217;ll have to wait. More updates will be forthcoming when I fix this.</del></p>
<p><strong>Update 2</strong> Thanks to Alex&#8217;s comment I&#8217;ve re-enabled the key copy in the example code. It&#8217;s a bit slow to copy the ACL, but for large files it will still perform significantly better.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anthonyeden.com/2009/04/capistrano-rails-and-amazon-cloudfront/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
