<?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>Brit Gardner &#187; web development</title>
	<atom:link href="http://britg.com/topics/developer-thoughts/feed/" rel="self" type="application/rss+xml" />
	<link>http://britg.com</link>
	<description>The big yellow one&#039;s the sun.</description>
	<lastBuildDate>Fri, 03 Feb 2012 05:08:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Forging Forgecraft: Integrating CSS3 Transitions with Javascript</title>
		<link>http://britg.com/2012/01/15/forging-forgecraft-integrating-css3-transitions-with-javascript/</link>
		<comments>http://britg.com/2012/01/15/forging-forgecraft-integrating-css3-transitions-with-javascript/#comments</comments>
		<pubDate>Sun, 15 Jan 2012 16:01:01 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[gaming]]></category>
		<category><![CDATA[html/css]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[forgecraft]]></category>

		<guid isPermaLink="false">http://britg.com/?p=26688</guid>
		<description><![CDATA[Forgecraft is a game currently in development using Ruby on Rails, Backbone.js, and all sorts of HTML5 buzzwords. Read an introduction here, and play the demo here. With Forgecraft, and any game really, there are usually quite a few animations running concurrently. I found these moments to be choppy, unresponsive and frustrating when they were [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://playforgecraft.com"><img src="http://britg.com.s3.amazonaws.com/forgecraft/logo-shadow.jpg" style="float: right; margin-left: 10px; margin-bottom: 10px; height: 45px;" /></a><em><a href="http://playforgecraft.com">Forgecraft</a> is a game currently in development using Ruby on Rails, Backbone.js, and all sorts of HTML5 buzzwords. Read an introduction <a href="http://britg.com/2011/12/29/forging-forgecraft-part-1-introduction/">here</a>, and play the demo <a href="http://playforgecraft.com">here</a>.</em></p>
<p>With Forgecraft, and any game really, there are usually quite a few animations running concurrently. I found these moments to be choppy, unresponsive and frustrating when they were implemented in javascript (especially on lower CPU environments like the iPad) and needed another solution. <a href="http://www.alistapart.com/articles/understanding-css3-transitions/">CSS3 transitions</a> were an obvious choice to check out, as they&#8217;ve been shown to be a great way to add a little pizzazz to a modern web app and can be executed natively (and even <a href="http://www.html5rocks.com/en/tutorials/speed/html5/#transanim">GPU accelerated</a>).</p>
<p><strong>But, can they provide the technical underpinnings for an interactive gamely element?</strong> To be effective in this context, they&#8217;d have to be:</p>
<ul>
<li>responsive, consistent and reliable</li>
<li>noticeably smoother than their javascript counterparts</li>
<li>simple to integrate with scripting</li>
</ul>
<p>Regarding the first 2 points, CSS3 transitions&#8217; effectiveness will really depend on your particular use-case. With Forgecraft they were definitely response, reliable, and smoother than javascript and I decided early on to use them in lieu of javascript wherever I could. But, I won&#8217;t go into the benchmarks and A/B comparisons in this article… perhaps later. Let&#8217;s just skip straight to the useful part:</p>
<h3>Product Intergortion <span style="font-size:12px"><em><a href="http://www.youtube.com/watch?v=CurP0BRHT9Y&#038;feature=endscreen&#038;NR=1" target="_blank">obscure 30 Rock reference &rarr;</a></em></span></h3>
<p>Integrating CSS3 transitions with the game&#8217;s scripting is pretty straight forward:</p>
<ul>
<li>Define transitions in CSS on your master element</li>
<li>Define classes with resulting properties changed</li>
<li>Trigger a class change using javascript</li>
<li>Listen for the transition-end event with javascript</li>
</ul>
<p>Of course, there are a few pitfalls with each of these steps that I&#8217;ll go into here. Let&#8217;s take an example from Forgecraft: the Bonus Strike event. Randomly while forging the player will see a bar pop-up like this:</p>
<p><img src="http://britg.com.s3.amazonaws.com/forgecraft/active-forge.jpg" style="width: 500px;" /></p>
<p>The bar moves from left-to-right and the player&#8217;s goal is to click the icon when the moving bar is directly under the target (large white) bar. The moving bar is animated with CSS3 transitions.</p>
<h4>Defining the CSS:</h4>
<p>We have a bar that needs an initial negative offset (the start position) that transitions to its final position. Simple enough: we define the base CSS on the <code>#bar</code> element and give it two classes (.new and .activated) defining each of its states. We also define the transition between the two states:</p>
<p><script src="https://gist.github.com/1616386.js?file=bar.css"></script><br />
<noscript><br />
#bar {<br />
  width: 600px;<br />
  height: 60px;</p>
<p>  position: relative;</p>
<p>  background-color: rgba(153, 153, 153, 0.3);<br />
  border-right: solid 5px white;</p>
<p>  -moz-transition-property: left;<br />
  -webkit-transition-property: left;<br />
  -o-transition-property: left;<br />
  transition-property: left;<br />
  -moz-transition-duration: 1.5s;<br />
  -webkit-transition-duration: 1.5s;<br />
  -o-transition-duration: 1.5s;<br />
  transition-duration: 1.5s;</p>
<p>}</p>
<p>#bar.new {<br />
  left: 0px;<br />
}</p>
<p>#bar.activated {<br />
  left: 600px;<br />
}<br />
</noscript></p>
<p><strong>One pitfall you may run into:</strong> for the animations to work in Firefox, you have to explicitly define the initial state for whatever property you are transitioning. In this example we are transitioning the <code>left</code> property of the <code>#bar</code> element. You normally wouldn&#8217;t define <code>left: 0;</code> &#8212; that&#8217;s the default! But Firefox requires this to trigger the transition when that property changes.</p>
<h4>Triggering the Animation in Javascript</h4>
<p>Using jQuery, we simply apply the classes that we defined in the CSS when we want to trigger the transition.</p>
<p><script src="https://gist.github.com/1616386.js?file=activate.js"></script><br />
<noscript><br />
$(&#8216;#bar&#8217;).removeClass(&#8216;new&#8217;).addClass(&#8216;activated&#8217;);<br />
</noscript></p>
<h4>Listening for the transition-end event</h4>
<p>CSS3 Transitions would be useless if we couldn&#8217;t get their context from within our scripting. Luckily, a series of events are fired in javascript while the transitions are running, just like you&#8217;d expect in a javascript-based animation. The primary event we care about is when the transition ends as you&#8217;ll most likely want to trigger callbacks.</p>
<p>Unfortunately, each browser vendor has decided to name these events differently… typical huh. <a href="http://www.modernizr.com/">Modernizr</a> to the rescue! (If you&#8217;re not using Modernizr, you should be. But that&#8217;s another blog post altogether).</p>
<p>There&#8217;s a hidden gem in the comments in the source code of Modernizr that explains how to use its <code><a href="http://www.modernizr.com/docs/#prefixed">.prefixed()</a></code> API to make a simple wrapper around the browser-specific transition event names. Here&#8217;s how I implemented it for the transition-end event. Feel free to use this wherever you need it:</p>
<p><script src="https://gist.github.com/1616386.js?file=transitionend.js"></script><br />
<noscript><br />
// Adapted from the Modernizer source comments</p>
<p>var transEndEventNames = {<br />
  &#8216;WebkitTransition&#8217; : &#8216;webkitTransitionEnd&#8217;,<br />
  &#8216;MozTransition&#8217;    : &#8216;transitionend&#8217;,<br />
  &#8216;OTransition&#8217;      : &#8216;oTransitionEnd&#8217;,<br />
  &#8216;msTransition&#8217;     : &#8216;msTransitionEnd&#8217;, // maybe?<br />
  &#8216;transition&#8217;       : &#8216;transitionEnd&#8217;<br />
}, </p>
<p>CSS3_TRANSITION_END = transEndEventNames[ Modernizr.prefixed('transition') ];<br />
</noscript></p>
<p>Bam, now we can use one simple event binding to handle all browsers:</p>
<p><script src="https://gist.github.com/1616386.js?file=listen.js"></script><br />
<noscript><br />
$(&#8216;#bar&#8217;).bind(CSS3_TRANSITION_END, function() {<br />
  //&#8230; do stuff<br />
});<br />
</noscript></p>
<h4>Stopping a Transition Early</h4>
<p>When the player hits the hammer-and-anvil icon during the Bonus Strike event, I needed to stop the animation early. The easiest way I found to do this, was to just set the animating property to its current value. The transition delta becomes 0, so the animation stops:</p>
<p><script src="https://gist.github.com/1616386.js?file=stop.js"></script><br />
<noscript><br />
$(&#8216;#bar&#8217;)css({ left: $(&#8216;#bar&#8217;).css(&#8216;left&#8217;) });<br />
</noscript></p>
<h3>Transition: End</h3>
<p>You may find that integrating CSS3 Transitions into your game makes your interactions smoother and more responsive, and with a simple API for scripting against transition events, developing against them should look and feel a lot like working in pure javascript.</p>
<hr />
<p><em>More Forging Forgecraft:</em></p>
<ul>
<li> <a href="http://britg.com/2011/12/29/forging-forgecraft-part-1-introduction/">Introducing Forgecraft</a></li>
<li> <a href="http://britg.com/2012/01/07/forging-forgecraft-a-hybrid-sql-mongodb-data-solution/">A Hybrid SQL MongoDB Data Solution</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2012/01/15/forging-forgecraft-integrating-css3-transitions-with-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Forging Forgecraft: A Hybrid SQL MongoDB Data Solution</title>
		<link>http://britg.com/2012/01/07/forging-forgecraft-a-hybrid-sql-mongodb-data-solution/</link>
		<comments>http://britg.com/2012/01/07/forging-forgecraft-a-hybrid-sql-mongodb-data-solution/#comments</comments>
		<pubDate>Sat, 07 Jan 2012 14:27:39 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[gaming]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[forgecraft]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[postgres]]></category>

		<guid isPermaLink="false">http://britg.com/?p=26402</guid>
		<description><![CDATA[Forgecraft is a game currently in development using Ruby on Rails, Backbone.js, and all sorts of HTML5 buzzwords. Read an introduction here, and play the demo here. One of my primary goals while building Forgecraft is to learn as many new technologies as possible. I&#8217;ve learned the hard way that it&#8217;s better to leave this [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://playforgecraft.com"><img src="http://britg.com.s3.amazonaws.com/forgecraft/logo-shadow.jpg" style="float: right; margin-left: 10px; margin-bottom: 10px; height: 45px;" /></a><em><a href="http://playforgecraft.com">Forgecraft</a> is a game currently in development using Ruby on Rails, Backbone.js, and all sorts of HTML5 buzzwords. Read an introduction <a href="http://britg.com/2011/12/29/forging-forgecraft-part-1-introduction/">here</a>, and play the demo <a href="http://playforgecraft.com">here</a>.</em></p>
<p>One of my primary goals while building Forgecraft is to learn as many new technologies as possible. I&#8217;ve learned the hard way that it&#8217;s better to leave this kind of exploration in your hobby projects and out of your production &#8220;for real&#8221; stuff. And, seeing as how there are so many emergent technologies right now in web development there&#8217;s a lot to explore!</p>
<h4>Whole Hog is Too Much Hog</h4>
<p><a href="http://mongodb.org">MongoDB</a> has quite a bit of steam behind it in the Rails/Ruby community (and plenty of other places too), and with projects like <a href="http://mongoid.org">Mongoid</a> and <a href="http://mongomapper.com/">MongoMapper</a> (I went with Mongoid) it&#8217;s an easy drop-in replacement for Active Record that maintains all those ORM conventions you know and love. I decided against the <em>replacement</em> approach for one primary reason: <strong>I wanted to use existing, robust, and actively developed libraries that rely on Active Record</strong>.</p>
<p>Example: There&#8217;s no reason to roll your own authentication/user system when there are insanely popular and feature-full libraries already in place for them like <a href="https://github.com/plataformatec/Devise">Devise</a> and <a href="https://github.com/binarylogic/authlogic">authlogic</a> (I went with Devise).</p>
<p>Fortunately combining Active Record with Mongoid and getting the best of both worlds proved to be easy and painless.</p>
<h4>The Set Up</h4>
<p>The <a href="http://mongoid.org/docs/installation/configuration.html">instructions</a> for Mongoid include a step to remove the Active Record libraries from being loaded and delete your database.yml. Simply skip that step and both systems will run in conjunction.</p>
<p>One small operational change you&#8217;ll have to make during development is explicitly defining when your rails generators should use Active Record. If you want to make an AR-driven model, your generators will look like:</p>
<p><code>rails g active_record:model Player …</code> produces a model the extends from ActiveRecord::Base.</p>
<p>And by default, the data generators will use Mongoid:</p>
<p><code>rails g model Skill …</code> produces a model that includes Mongoid::Document.</p>
<h4>The Implementation</h4>
<p>Here&#8217;s how this combo system really shines in my opinion: get all the great features of gems built on AR with all the schema less features of Mongo. I&#8217;ll walk through an example:</p>
<p>In Forgecraft, the authenticating object is the <code>Player</code> and players have many <code>Skills</code> which, right now, are Accuracy, Craftsmanship, and Perception. But, the skill list will likely grow and change over time as the game evolves. A typical AR/SQL based approach would be to create a skills table and a join table between players and skills resulting in a complex multi-table query to get a player&#8217;s complete skills.</p>
<p>It&#8217;s clear here that the Player and Skills would fit well together as a single document in Mongo, queried all at once in one tidy object. But, since the Player is also our authentication model, using Mongo would prevent us from using Devise to handle all of that boring and complex auth stuff for us.</p>
<p>Enter Hybridization. Forgecraft&#8217;s implementation uses the typical Devise set up around the Player object (again all on top of AR). All of a player&#8217;s skills go into a single document with a reference to the player, like so:</p>
<p><script src="https://gist.github.com/1575059.js?file=skill.rb"></script><br />
<noscript>
<pre>class Skill
  include Mongoid::Document
  field :player_id, :type => Integer

  field :accuracy, :type => Integer, :default => 0
  field :craftsmanship, :type => Integer, :default => 0
  field :perception, :type => Integer, :default => 0

  index :player_id, :unique => true

  def player
    Player.find_by_id(player_id)
  end
end</pre>
<p></noscript></p>
<p>To set up the relationships like one would expect with Active Record is a simple method on your Player object:</p>
<p><script src="https://gist.github.com/1575059.js?file=player.rb"></script><br />
<noscript>
<pre>class Player < ActiveRecord::Base

  # ...

  def skills
    @skills ||= (Skill.where(:player_id => self.id).first || \
                 Skill.create(:player_id => self.id))
  end

end</pre>
<p></noscript></p>
<p>Bam! Now we can retrieve our skills as a single document (fast), and add new skills with ease (easy). Since Mongo is schema less, you could even have a different set of skills per player. Again, all of this is achievable through SQL &#8212; it&#8217;s been done for decades &#8212; but it just makes more conceptual sense to treat these as a single document.</p>
<p>Querying and working with these objects and their relationships looks and feels just like active record:</p>
<pre>player.skills
player.skills.accuracy
player.skills.update_attributes(:accuracy => 5)
player.skills.inc(:accuracy, 1)</pre>
<h4>Benefits Outweight the Consequences</h4>
<p>I know, I know &#8212; any time you introduce an additional system, especially a datastore, you introduce a lot of complexity, failure modes, testing, etc. But, I honestly think the benefits are worth this extra complexity. Speed, ease of development, and the potential for less schema-driven growth make this an ideal environment for me. I highly recommend it, and will be using it in the future!</p>
<hr />
<p><em>More Forging Forgecraft:</em></p>
<ul>
<li> <a href="http://britg.com/2011/12/29/forging-forgecraft-part-1-introduction/">Introducing Forgecraft</a></li>
<li> <a href="http://britg.com/2012/01/15/forging-forgecraft-integrating-css3-transitions-with-javascript/">Integrating CSS3 Transitions with Javascript</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2012/01/07/forging-forgecraft-a-hybrid-sql-mongodb-data-solution/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Perfect Logrotate Config</title>
		<link>http://britg.com/2011/12/06/the-perfect-logrotate-script/</link>
		<comments>http://britg.com/2011/12/06/the-perfect-logrotate-script/#comments</comments>
		<pubDate>Wed, 07 Dec 2011 00:18:45 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[web development]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[sysops]]></category>

		<guid isPermaLink="false">http://britg.com/?p=25847</guid>
		<description><![CDATA[One of the first things I do when setting up a new server somewhere is get all those damn log files rotating. Here&#8217;s the logrotate.conf block I use: in /etc/logrotate.conf /path/to/any/log/file/*.log { daily dateext missingok rotate 365 compress delaycompress notifempty copytruncate } This is a slight modification of this configuration. Check out his explanation for [...]]]></description>
			<content:encoded><![CDATA[<p>One of the first things I do when setting up a new server somewhere is get all those damn log files rotating. Here&#8217;s the logrotate.conf block I use:</p>
<p><code></p>
<p>in /etc/logrotate.conf</p>
<p>/path/to/any/log/file/*.log {<br />
  daily<br />
  dateext<br />
  missingok<br />
  rotate 365<br />
  compress<br />
  delaycompress<br />
  notifempty<br />
  copytruncate<br />
}</p>
<p></code></p>
<p>This is a slight modification of <a href="http://www.nullislove.com/2007/09/10/rotating-rails-log-files/">this configuration</a>. Check out his explanation for all of the params.</p>
<p>The one I added that I think is essential is <code>dateext</code>, which appends dates instead of incrementing digits to the end of the log files, like so: </p>
<p><code><br />
-rw-r--r-- 1 britg britg  64M 2011-10-24 06:49 production.log-20111024.gz<br />
-rw-r--r-- 1 britg britg  62M 2011-10-25 06:52 production.log-20111025.gz<br />
-rw-r--r-- 1 britg britg  56M 2011-10-26 06:29 production.log-20111026.gz<br />
-rw-r--r-- 1 britg britg  56M 2011-10-27 06:51 production.log-20111027.gz<br />
-rw-r--r-- 1 britg britg  57M 2011-10-28 06:51 production.log-20111028.gz<br />
</code></p>
<p>Which, in my opinion, is much more parseable by our puny human brains.</p>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2011/12/06/the-perfect-logrotate-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A SublimeText2 Project File for Rails Projects</title>
		<link>http://britg.com/2011/10/27/a-sublimetext2-project-file-for-rails-projects/</link>
		<comments>http://britg.com/2011/10/27/a-sublimetext2-project-file-for-rails-projects/#comments</comments>
		<pubDate>Thu, 27 Oct 2011 16:03:10 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[dev]]></category>

		<guid isPermaLink="false">http://britg.com/?p=24730</guid>
		<description><![CDATA[The fuzzy finder in SublimeText2 is great, but if you&#8217;ve added a rails folder to your project you may see a bunch of cruft in the result list most likely due to cache files. Here&#8217;s a generic rails project file I use that keeps the fuzzy finder pretty clean. Note: this is a Rails 3.0 [...]]]></description>
			<content:encoded><![CDATA[<p>The fuzzy finder in <a href="http://www.sublimetext.com/">SublimeText2</a> is great, but if you&#8217;ve added a rails folder to your project you may see a bunch of cruft in the result list most likely due to cache files. Here&#8217;s a generic rails project file I use that keeps the fuzzy finder pretty clean.</p>
<p><strong>Note:</strong> this is a Rails 3.0 project with <a href="http://documentcloud.github.com/jammit/">jammit</a> and <a href="http://compass-style.org/">compass</a> installed. The exclusion of the <code>assets</code> folder is probably not ideal in a Rails 3.1 project.</p>
<p><script src="https://gist.github.com/1319965.js?file=project.sublime-project"></script></p>
<p><noscript>
<pre>
{
	"folders":
	[
		{
			"path": "/Users/britg/Projects/ponycorn-fanclub.com",
            "folder_exclude_patterns": ["*.sass-cache", "tmp", "log", "assets", "cache"]
		}
	]
}
</pre>
<p></noscript></p>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2011/10/27/a-sublimetext2-project-file-for-rails-projects/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>New Relic Menu Bars: Multiple Application Support</title>
		<link>http://britg.com/2011/07/04/new-relic-menu-bars-multiple-application-support/</link>
		<comments>http://britg.com/2011/07/04/new-relic-menu-bars-multiple-application-support/#comments</comments>
		<pubDate>Mon, 04 Jul 2011 15:00:11 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[web development]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[osx]]></category>

		<guid isPermaLink="false">http://britg.com/?p=12199</guid>
		<description><![CDATA[Many of you use New Relic to monitor multiple accounts and applications, so I&#8217;ve updated New Relic Menu Bars to support these. Grab the updated version here. The New Relic API is pretty straight forward with regards to listing Accounts and Applications, but I personally don&#8217;t have this use-case. So, please let me know if [...]]]></description>
			<content:encoded><![CDATA[<p>Many of you use New Relic to monitor multiple accounts and applications, so I&#8217;ve updated <a href="http://britg.com/2011/06/21/new-relic-menu-bar-performance-monitoring-app/">New Relic Menu Bars</a> to support these.</p>
<p>Grab the updated version <a href="http://itunes.apple.com/us/app/new-relic-menu-bars/id448212585?mt=12">here</a>.</p>
<p><a href="http://britg.com.s3.amazonaws.com/new_relic_menus2.png" rel="facebox"><img src="http://britg.com.s3.amazonaws.com/new_relic_menus2.png" /></a></p>
<p>The New Relic API is pretty straight forward with regards to listing Accounts and Applications, but I personally don&#8217;t have this use-case. So, please let me know if the current implementation is lacking any functionality for those of you that do!</p>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2011/07/04/new-relic-menu-bars-multiple-application-support/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>New Relic Menu Bar Performance Monitoring App</title>
		<link>http://britg.com/2011/06/21/new-relic-menu-bar-performance-monitoring-app/</link>
		<comments>http://britg.com/2011/06/21/new-relic-menu-bar-performance-monitoring-app/#comments</comments>
		<pubDate>Wed, 22 Jun 2011 03:10:03 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[web development]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[osx]]></category>

		<guid isPermaLink="false">http://britg.com/?p=10233</guid>
		<description><![CDATA[New Relic has quickly become an invaluable tool for monitoring performance of Key Ring for me. I found myself constantly checking the dashboard, partly for the graph, but mostly for the quick metrics at the top. Namely, I pay the most attention to requests-per-minute, response time, and errors. Why keep a browser window dedicated to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://newrelic.com">New Relic</a> has quickly become an invaluable tool for monitoring performance of <a href="http://keyringapp.com">Key Ring</a> for me. I found myself constantly checking the dashboard, partly for the graph, but mostly for the quick metrics at the top. Namely, I pay the most attention to requests-per-minute, response time, and errors.</p>
<p>Why keep a browser window dedicated to this? Fortunately, New Relic <a href="https://github.com/newrelic/newrelic_api">provides an API</a>, so I whipped together a quick and dirty menu bars app to display the stuff I care about. Here&#8217;s what it looks like:</p>
<p><a href="http://britg.com.s3.amazonaws.com/new_relic_menus.png" rel="facebox"><img src="http://britg.com.s3.amazonaws.com/new_relic_menus.png" /></a></p>
<p>If you&#8217;d find this useful, feel free to download the app <a href="http://itunes.apple.com/us/app/new-relic-menu-bars/id448212585?mt=12">here</a>.</p>
<p><strong>Warning</strong>: The app is very simple. It prompts you for your New Relic API key and then loads your first Account and first Application. Perfect for my needs, but I&#8217;m open to suggestions. Do a lot of you have multiple accounts or applications? If so, I can add an account/application selector.</p>
<p><strong>Update</strong>: I&#8217;ve added support for multiple accounts and applications. Get the new version <a href="http://britg.com/2011/07/04/new-relic-menu-bars-multiple-application-support/">here</a>!</p>
<p>Feel free to contact me a brit at britg dot com with suggestions or feature requests!</p>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2011/06/21/new-relic-menu-bar-performance-monitoring-app/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Using Foreman for Logging and Watchr</title>
		<link>http://britg.com/2011/06/02/using-foreman-for-logging-and-watchr/</link>
		<comments>http://britg.com/2011/06/02/using-foreman-for-logging-and-watchr/#comments</comments>
		<pubDate>Fri, 03 Jun 2011 03:03:10 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[dev]]></category>

		<guid isPermaLink="false">http://britg.com/?p=6044</guid>
		<description><![CDATA[Foreman has quickly turned into a must-have gem for local development for me. From @ddollar&#8217;s description of Foreman: Using foreman you can declare the various processes that are needed to run your application using a Procfile. Besides the normal processes (rails, workers, etc.) I&#8217;ve found great success running log tailing and watchr through Foreman. Here&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.daviddollar.org/2011/05/06/introducing-foreman.html">Foreman</a> has quickly turned into a must-have gem for local development for me.</p>
<p>From <a href="https://twitter.com/#!/ddollar">@ddollar&#8217;s</a> description of Foreman:</p>
<blockquote><p>Using foreman you can declare the various processes that are needed to run your application using a Procfile.</p></blockquote>
<p>Besides the normal processes (rails, workers, etc.) I&#8217;ve found great success running log tailing and <a href="https://github.com/mynyml/watchr">watchr</a> through Foreman. Here&#8217;s what my current Procfile looks like:</p>
<p><script src="https://gist.github.com/1005789.js?file=Procfile"></script><br />
<noscript>
<p><em>(View original to see this Gist.)</em></noscript></p>
<p>If your development pattern is anything like mine, it looks like:</p>
<ul>
<li>Edit a test, model or controller: check watchr output</p>
<li>Edit a view, js or scss file: refresh the browser</p>
</ul>
<p>Here&#8217;s what that looks like through Foreman:</p>
<p><a href="http://britg.com.s3.amazonaws.com/foreman_output.png" rel="facebox"><img src="http://britg.com.s3.amazonaws.com/foreman_output.png" style="width:600px;" /></a></p>
<p>This works well with watchr and log tailing output, as they rarely overlap. Even if they do, finding the appropriate output is easy with Foreman&#8217;s prepending of the process name and timestamp.</p>
<p>Have any other tips/tricks with Foreman? Let me know!</p>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2011/06/02/using-foreman-for-logging-and-watchr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Ratings Solicitation</title>
		<link>http://britg.com/2011/05/11/the-ratings-solicitation/</link>
		<comments>http://britg.com/2011/05/11/the-ratings-solicitation/#comments</comments>
		<pubDate>Thu, 12 May 2011 01:26:27 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[news]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[dev]]></category>

		<guid isPermaLink="false">http://britg.com/?p=2294</guid>
		<description><![CDATA[Recently Marco Arment wrote a post and a comment on Twitter about his feelings on the seemingly ubiquitous ratings solicitation in iOS apps: .bbpBox66296559519809536 {background:url(http://a0.twimg.com/profile_background_images/123453052/twitterbackground1.jpg) #C0DEED;padding:20px;} p.bbpTweet{background:#fff;padding:10px 12px 10px 12px;margin:0;min-height:48px;color:#000;font-size:18px !important;line-height:22px;-moz-border-radius:5px;-webkit-border-radius:5px} p.bbpTweet span.metadata{display:block;width:100%;clear:both;margin-top:8px;padding-top:12px;height:40px;border-top:1px solid #fff;border-top:1px solid #e6e6e6} p.bbpTweet span.metadata span.author{line-height:19px} p.bbpTweet span.metadata span.author img{float:left;margin:0 7px 0 0px;width:38px;height:38px} p.bbpTweet a:hover{text-decoration:underline}p.bbpTweet span.timestamp{font-size:12px;display:block} If I ever added a [...]]]></description>
			<content:encoded><![CDATA[<p>Recently <a href="http://marco.org">Marco Arment</a> wrote a <a href="http://www.marco.org/2011/05/05/apps-prompting-for-reviews">post</a> and a comment on Twitter about his feelings on the seemingly ubiquitous ratings solicitation in iOS apps:</p>
<p><!-- <a href="https://twitter.com/#!/marcoarment/status/66296559519809536" rel="nofollow">https://twitter.com/#!/marcoarment/status/66296559519809536</a> --><br />
<style type='text/css'>.bbpBox66296559519809536 {background:url(http://a0.twimg.com/profile_background_images/123453052/twitterbackground1.jpg) #C0DEED;padding:20px;} p.bbpTweet{background:#fff;padding:10px 12px 10px 12px;margin:0;min-height:48px;color:#000;font-size:18px !important;line-height:22px;-moz-border-radius:5px;-webkit-border-radius:5px} p.bbpTweet span.metadata{display:block;width:100%;clear:both;margin-top:8px;padding-top:12px;height:40px;border-top:1px solid #fff;border-top:1px solid #e6e6e6} p.bbpTweet span.metadata span.author{line-height:19px} p.bbpTweet span.metadata span.author img{float:left;margin:0 7px 0 0px;width:38px;height:38px} p.bbpTweet a:hover{text-decoration:underline}p.bbpTweet span.timestamp{font-size:12px;display:block}</style>
<div class='bbpBox66296559519809536'>
<p class='bbpTweet'>If I ever added a rating solicitation in Instapaper, it&#8217;d be buried in the Settings screen somewhere. But I still probably wouldn&#8217;t.<span class='timestamp'><a title='Fri May 06 00:21:46 +0000 2011' href='https://twitter.com/#!/marcoarment/status/66296559519809536'>less than a minute ago</a> via <a href="http://itunes.apple.com/us/app/twitter/id409789998?mt=12" rel="nofollow">Twitter for Mac</a></span><span class='metadata'><span class='author'><a href='http://twitter.com/marcoarment'><img src='http://a1.twimg.com/profile_images/1282173124/untitled-158-2_normal.jpg' /></a><strong><a href='http://twitter.com/marcoarment'>Marco Arment</a></strong><br/>marcoarment</span></span></p>
</div>
<p> <!-- end of tweet --></p>
<p>Believe me,  I understand his reluctancy because I felt it too.  If you had asked me two months ago what I thought users think about these, I&#8217;d say they thought it was spammy, obtrusive, and just plain <em>shady</em>.  But then I found myself implementing it in <a href="http://keyringapp.com">Key Ring</a> in our latest update. Oh, how my feelings have changed.</p>
<h3>The Vocal Minority</h3>
<p>I&#8217;ve heard that review systems tend to expose the vocal minority, and I believe this. It doesn&#8217;t matter if it&#8217;s Amazon or iTunes, the vast majority of people who are satisfied, or heaven forbid <em>happy</em>, with a product will never take the time to write a review or leave a rating.</p>
<p>But, there&#8217;s a small and extremely motivated group of people that are willing, nay <em>eager</em>, to sling around 1-star reviews at the slightest hint of inconvenience. They have a forum, and <em>by God</em> they will use it. This affects the sleep patterns of app developers in ways I never fathomed until I became one.</p>
<h3>The Lazy, Content Majority</h3>
<p>The ratings solicitation is the app developers&#8217; last bastion of defense against the Vocal Minority. Key Ring was a <em>meh</em>-inducing 3 stars for the first year of its existence, and our reviews were pretty evenly dispersed between 1 star and 5 stars.  After implementing a very unobtrusive, one-time, opt-in ratings solicitation, magically Key Ring is now a sturdy 4.5 stars! The 5 star ratings are through the roof.</p>
<p>Oh how I wish I could attribute the dramatic change to the new UI, speed improvements, or something else I could brag about. Nope, if you look at the written reviews for Key Ring it becomes obvious that the users who are content with the app (who would never give a second thought to rating or reviewing it) are blurting a few words of praise and tapping that last star on the far right <em>just because the app happened to remind them, in a moment of whimsical curiousity and boredom, that iTunes has this rating system and using it might be slightly less boring than whatever they are doing</em>.</p>
<p>The surprising thing is, we have not once had a single complaint or mention about the ratings solicitation.  Hell, we get notified by users when we mispell words in our Terms of Service!</p>
<h3>The Bottom Line</h3>
<p>There are people out there who are completely satisfied with whatever you&#8217;re producing, but you&#8217;ve probably never heard from them. In an ecosystem that values the coveted &#8220;<em>rating</em>&#8221; so very dearly, a tactful solicitation for a review is a great way to expose your fans and let potential users of your app know that it is worthwhile.  Don&#8217;t be afraid to implement one, and don&#8217;t think less of apps that do.</p>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2011/05/11/the-ratings-solicitation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Quick Look: WebGL and Web Sockets</title>
		<link>http://britg.com/2010/01/10/quick-look-webgl-and-web-sockets/</link>
		<comments>http://britg.com/2010/01/10/quick-look-webgl-and-web-sockets/#comments</comments>
		<pubDate>Sun, 10 Jan 2010 17:07:11 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[webgl]]></category>
		<category><![CDATA[websockets]]></category>

		<guid isPermaLink="false">http://britg.com/?p=1303</guid>
		<description><![CDATA[The internet is still a very young ecosystem of immature techn&#8230; Woah, the BS meter pegged there for a second. Forget the pontification, let me just spit out the two technologies that get me excited about billing myself as a Web Developer. WebGL This is a new spec that&#8217;s being developed by the Khronos Group [...]]]></description>
			<content:encoded><![CDATA[<p><strike>The internet is still a very young ecosystem of immature techn&#8230;</strike> Woah, the BS meter pegged there for a second.  Forget the pontification, let me just spit out the two technologies that get me excited about billing myself as a Web Developer.</p>
<h3>WebGL</h3>
<p>This is a new spec that&#8217;s being developed by the <a href="http://www.khronos.org/webgl/">Khronos Group</a> (the group behind OpenGL) to expose OpenGL to browsers through the canvas element.</p>
<p>Why is it exciting? Three words: <strong>Javascript</strong>. <strong>Hardware</strong>. <strong>Acceleration</strong>.  Damn, I need three more: <strong>In</strong>. <strong>The</strong>. <strong>Browser</strong>.</p>
<p>The concepts should speak for themselves, but if you still need some convincing follow the steps below and be sure to take a look at your CPU usage while running these demos.  (Hint: CPU usage will be very low because you&#8217;re riding your GPU).</p>
<ul>
<li>Grab the latest nighly of Chromium <a href="http://build.chromium.org/buildbot/snapshots/chromium-rel-xp/?C=M;O=D">here</a> if you are not already running it.</li>
<li>Start Chromium via the command line:
<ul>
<li>Windows: <code>chrome.exe --no-sandbox --enable-webgl</code></li>
<li>OSX: <code>Chromium.app/Contents/MacOS/Chromium --no-sandbox --enable-webgl</code></li>
<li>Linux: <code>./chrome --no-sandbox --enable-webgl</code></li>
</ul>
</li>
<li>Follow <a href="http://hacks.mozilla.org/2009/09/three-more-webgl-demos/">this link</a> to some examples of WebGL in action.</li>
</ul>
<p>Again, check your CPU usage while running the demos. It should be very low (if you have a GPU) as the demos should be hardware accelerated.</p>
<h3>Web Sockets</h3>
<p>Comet? Long-Polling? Forever Frame? In two years we will all be sitting around a trash barrel fire laughing about the days of yore when we had to use such hacks. </p>
<p>Why are we huddled around a trash barrel fire? Because it&#8217;s post-apocolyptic New Zealand, the last bastion of humanity. Anyways, that&#8217;s another &#8220;In This Decade&#8221; blog post&#8230;</p>
<p>From <a href="http://www.websockets.org/">websockets.org</a>:</p>
<blockquote><p>[The Web Socket Interface] defines a full-duplex communications channel that operates over a single socket and is exposed via a JavaScript interface in compliant browsers</p></blockquote>
<p>Here&#8217;s the <a href="http://www.w3.org/TR/2009/WD-websockets-20091222/">spec</a> in case you want to read it&#8230; haha, me neither.</p>
<p>Again, the concept here should speak for itself.  Two-way communication with web servers in an easy-to-use interface.</p>
<pre class="brush: jscript; title: ;">

var websock = new WebSocket(&amp;quot;ws://www.websocket.org&amp;quot;);

websock.onopen = function(evt) {
  console.log(evt)
  websock.send(&amp;quot;Hello Web Socket!&amp;quot;);
};
websock.onmessage = function(evt) {
  console.log(evt)
};
websock.onclose = function(evt) {
  console.log(evt)
};
websock.close();
</pre>
<p>Fortunately, there are already many projects implementing the web sockets protocol.  To name a few,</p>
<ul>
<li><a href="http://github.com/guille/node.websocket.js/">node.websocket.js</a></li>
<li><a href="http://github.com/igrigorik/em-websocket">em-websocket (Ruby)</a></li>
<li><a href="http://code.google.com/p/pywebsocket/">pywebsocket</a></li>
</ul>
<p>One thing to note is that the web socket protocol will adhere to the cross-domain security restriction that XHR has.  The good news is it will ship with support for server-side origin discretion using the same Origin headers in <a href="http://britg.com/2009/12/02/cross-origin-resource-sharing/">CORS</a>.</p>
<h3>It&#8217;s all about the gaming, stupid</h3>
<p>I&#8217;m going to predict that in 2 years, we will see current A quality games developed in-browser ontop of these two technologies.  Don&#8217;t get me wrong, AAA quality console and PC titles won&#8217;t be disrupted like the music and print industries any time soon.  But, the &#8220;casual&#8221; label on browser games will go away.</p>
<p>This is what has me really excited about being a web developer in this decade.  Parity with desktop development is inching closer, and all ontop of open technologies.</p>
<p>No plugins.  No corporate owner.</p>
<p>Win. Win.</p>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2010/01/10/quick-look-webgl-and-web-sockets/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Cross Origin Resource Sharing with Sinatra</title>
		<link>http://britg.com/2009/12/29/cross-origin-resource-sharing-with-sinatra/</link>
		<comments>http://britg.com/2009/12/29/cross-origin-resource-sharing-with-sinatra/#comments</comments>
		<pubDate>Tue, 29 Dec 2009 15:46:45 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[cors]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[sinatra]]></category>

		<guid isPermaLink="false">http://britg.com/?p=1282</guid>
		<description><![CDATA[It&#8217;s no lie that I think highly of the potential of Cross Origin Resource Sharing. One of the great things about it is that it doesn&#8217;t take much re-wiring of existing server (or client-side) apps to start working cross domain. Enabling your server app is as simple as including a few extra headers when you [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s no lie that <a href="http://britg.com/2009/12/02/cross-origin-resource-sharing/">I think highly</a> of the potential of Cross Origin Resource Sharing.  One of the great things about it is that it doesn&#8217;t take much re-wiring of existing server (or client-side) apps to start working cross domain.</p>
<p>Enabling your server app is as simple as including a few extra headers when you detect a cross origin request.  How do you know it&#8217;s a cross origin request?  You&#8217;ll see the <code>Origin:</code> header &#8212; all CORS requests will have it.  From there, response headers depend on the specifics of the request, but I won&#8217;t go over those here &#8212; check out the <a href="https://developer.mozilla.org/En/HTTP_access_control">Mozilla Developer Center treatment</a> for in-depth information.</p>
<p>I&#8217;ve been working with Sinatra a lot lately, so I put together <a href="http://github.com/britg/sinatra-cross_origin">an extension for Sinatra</a> that makes enabling Cross Origin requests even easier.</p>
<p><code>sudo gem install sinatra-cross_origin</code></p>
<p>There are two ways to use the extension: globally or per-route.</p>
<h3>Global</h3>
<p>For when you want to share all your endpoints cross-domain.</p>
<pre class="brush: ruby; title: ;">

require 'sinatra/base'
require 'sinatra/cross_origin'

class MyApp &amp;lt; Sinatra::Base
  register Sinatra::CrossOrigin

  enable cross_origin

  get '/' do
    &amp;quot;This is available to cross domain javascript requests automatically&amp;quot;
  end
end
</pre>
<h3>Per Route</h3>
<p>For when you want to share only some of your routes cross-domain.</p>
<pre class="brush: ruby; title: ;">

require 'sinatra/base'
require 'sinatra/cross_origin'

class MyApp &amp;lt; Sinatra::Base
  register Sinatra::CrossOrigin

  get '/' do
    cross_origin
    &amp;quot;This is available to cross domain javascript requests&amp;quot;
  end
end
</pre>
<h3>Configuration</h3>
<p>You can mix and match app-wide config and request specific config.</p>
<pre class="brush: ruby; title: ;">

require 'sinatra/base'
require 'sinatra/cross_origin'

class MyApp &amp;lt; Sinatra::Base
  register Sinatra::CrossOrigin

  configure do
    # Comma separate list of remote hosts that are allowed.
    # :any will allow any host
    set :allow_origin, :any

    # HTTP methods allowed
    set :allow_methods, [:get, :post]

    # Allow cookies to be sent with the requests
    set :allow_credentials, true
  end

  get '/' do
    # Only available to GET requests originating from
    # <a href="http://example.com" rel="nofollow">http://example.com</a>.  No cookies allowed.
    cross_origin :allow_origin =&amp;gt; '<a href="http://example.com&#039;" rel="nofollow">http://example.com&#039;</a>,
      :allow_methods =&amp;gt; [:get],
      :allow_credentials =&amp;gt; false
    &amp;quot;This is available to cross domain javascripts&amp;quot;
  end
end
</pre>
<p>Grab the source at Github: <a href="http://github.com/britg/sinatra-cross_origin">britg/sinatra-cross_origin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2009/12/29/cross-origin-resource-sharing-with-sinatra/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

