<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Amber on Rails</title>
 <link href="http://amberonrails.com/feed/" rel="self"/>
 <link href="http://amberonrails.com/"/>
 <updated>2013-02-28T13:21:46-08:00</updated>
 <id>http://amberonrails.com/</id>
 <author>
   <name>Amber Feng</name>
 </author>

 
 
 <entry>
   <title>Building Stripe's API</title>
   <link href="http://amberonrails.com/building-stripes-api"/>
   <updated>2013-02-28T00:00:00-08:00</updated>
   <id>http://amberonrails.com/building-stripes-api</id>
   <content type="html">&lt;p&gt;Last week, I gave my first conference talk at the &lt;a href=&quot;http://apistrategyconference.com&quot;&gt;API Strategy and Practice&lt;/a&gt; conference in New York. Pretty exciting!&lt;/p&gt;

&lt;p&gt;I thought it would be interesting to talk about &lt;a href=&quot;https://stripe.com&quot;&gt;Stripe&lt;/a&gt;'s API, particularly lessons learned and what kind of things we did to try to make the API as easy to use as possible. I've included the slides below, but most of the content isn't on the slides so I'll try to cover some of the highlights.&lt;/p&gt;

&lt;p&gt;Of course, we don't claim to have all of the answers. Every API is different, and a lot of what you see on Stripe today is the product of a lot of thought and discussion, as well as a lot of trial and error. We're constantly experimenting and improving.&lt;/p&gt;

&lt;p&gt;Hopefully you find something here applicable towards your own API! (:&lt;/p&gt;

&lt;div style=&quot;width:600px; margin: 30px 0;&quot;&gt;
&lt;script async class=&quot;speakerdeck-embed&quot; data-id=&quot;c65f0040629c0130953122000a9d0218&quot; data-ratio=&quot;1.33333333333333&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;


&lt;h2&gt;Highlights&lt;/h2&gt;

&lt;h3&gt;Make it easy to get started&lt;/h3&gt;

&lt;p&gt;It may sound like a no-brainer, but the best way to get people to try out (and hopefully eventually use) your API is to make it really easy to get started.&lt;/p&gt;

&lt;p&gt;To that end, we do things like including pastable code snippets throughout our site and documentation. One of the first things you'll see on our &lt;a href=&quot;https://stripe.com&quot;&gt;front page&lt;/a&gt; is a curl snippet you can paste into a terminal to simulate charging a credit card.&lt;/p&gt;

&lt;p&gt;Regardless of whether you have a Stripe account or not (if logged in, we fill in your test API key, otherwise, it's a sample account's API key), you can see the Stripe API in action.&lt;/p&gt;

&lt;p&gt;All of our &lt;a href=&quot;https://stripe.com/docs/api&quot;&gt;documentation&lt;/a&gt; code snippets are similarly possible to directly copy and paste&amp;mdash;we try to embed as much information as possible (API keys, actual object IDs from the account, etc.) so our users don't have to.&lt;/p&gt;

&lt;h3&gt;Language-specific libraries and documentation&lt;/h3&gt;

&lt;p&gt;Since Stripe's API speaks HTTP and JSON, you could easily integrate it into your application with any standard HTTP client library. However, this still requires constructing requests and parsing responses on your own.&lt;/p&gt;

&lt;p&gt;We maintain and support &lt;a href=&quot;https://github.com/stripe&quot;&gt;open-source libraries&lt;/a&gt; in some of today's most popular web languages. It turns out people are pretty attached to their favorite languages.&lt;/p&gt;

&lt;p&gt;We had a lot of internal discussions about whether we actually wanted to support our own client bindings or allow the community to organically start and maintain the projects themselves. Is it worth owning the projects if it means that you might have to maintain libraries for languages or frameworks in which you don't have expertise?&lt;/p&gt;

&lt;p&gt;Maybe.&lt;/p&gt;

&lt;p&gt;Official libraries have the benefit of being consistent: they all have the same level of quality, support the same interface, and get updates at the same time. Having our own libraries also makes it easier for us to have language-specific documentation and help our users with any problems they might be having with a particular integration.&lt;/p&gt;

&lt;p&gt;We decided that it was worth it, but this may not be the right answer for everyone.&lt;/p&gt;

&lt;h3&gt;Have a focused API, but allow flexibility&lt;/h3&gt;

&lt;p&gt;We've found that it's critically important to keep the API focused and simple.&lt;/p&gt;

&lt;p&gt;It's often tempting to add new features that are not obviously necessary to the core API. For example, our users frequently want us to add better analytics, tax calculations, or to send customers receipts&lt;sup&gt;1&lt;/sup&gt;. While these things are nice, every feature you add makes the API more complex and cluttered.&lt;/p&gt;

&lt;p&gt;You can instead give your users the tools to be able to write their own extensions. We allow our users (and third party applications) to hook into Stripe in a couple of ways:&lt;/p&gt;

&lt;h4&gt;Webhooks&lt;/h4&gt;

&lt;p&gt;Stripe uses &lt;a href=&quot;https://stripe.com/docs/webhooks&quot;&gt;webhooks&lt;/a&gt; to let our users know when some interesting event has happened. This ranges from events triggered by an API call, like &lt;code&gt;charge.succeeded&lt;/code&gt; or &lt;code&gt;charge.refunded&lt;/code&gt;, to asynchronous events like &lt;code&gt;customer.subscription.trial_will_end&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our aim was to make it easy to layer additional logic on top of Stripe events (like sending customer receipts or &lt;a href=&quot;http://blog.alexmaccaw.com/stripe-push&quot;&gt;enabling push notifications&lt;/a&gt;). Giving our users the ability to build this kind of customized functionality allows them to control the entire experience for their users as well.&lt;/p&gt;

&lt;h4&gt;Stripe Connect&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://stripe.com/connect&quot;&gt;Stripe Connect&lt;/a&gt;, an API we released just last year, is another way of building on top of the Stripe platform.&lt;/p&gt;

&lt;p&gt;Connect is an &lt;a href=&quot;http://oauth.net/2/&quot;&gt;OAuth2&lt;/a&gt; API that allows a Stripe user to authorize access to their Stripe account to a third-party application. We've seen a variety of applications built on top of Stripe so far: marketplaces and checkout pages let users &quot;plug in&quot; their Stripe accounts to accept payments, and analytics dashboards fetch Stripe data in order to show interesting graphs or patterns.&lt;/p&gt;

&lt;h3&gt;Provide a testing environment&lt;/h3&gt;

&lt;p&gt;One of the most important things you need with an API is a great test/sandbox environment. This is particularly important for a payments API&amp;mdash;our users shouldn't have to make live charges when they're trying to test their integration.&lt;/p&gt;

&lt;p&gt;In our test environment, we allow users to send &lt;a href=&quot;https://stripe.com/docs/testing#how-do-i-test-stripe-webhooks&quot;&gt;test webhooks&lt;/a&gt; of any type and provide handy &lt;a href=&quot;https://stripe.com/docs/testing#cards&quot;&gt;test card numbers&lt;/a&gt; that trigger certain errors (like declines).&lt;/p&gt;

&lt;p&gt;Doing this allows them to easily test the behavior of their own application in the face of different scenarios instead of having to manually trigger things that are nondeterministic, like declines, or time-dependent, like expiring subscriptions.&lt;/p&gt;

&lt;h3&gt;Help your users debug&lt;/h3&gt;

&lt;p&gt;We're developers too. We know from experience that debugging is a disproportionately large portion of the development cycle. We also (unfortunately) know that sometimes you spend a lot of time debugging something that eventually turns out to be really obvious or silly.&lt;/p&gt;

&lt;p&gt;For common or easy errors, you (the API) likely know exactly what's wrong. So why not try to help?&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;no-highlight&quot;&gt;
    &gt;&gt; Stripe::Customer.create
    Stripe::AuthenticationError: No API key provided.  (HINT: set your API key
    using &quot;Stripe.api_key = &lt;API-KEY&gt;&quot;.  You can generate API keys from the 
    Stripe web interface.  See https://stripe.com/api for details, or email
    support@stripe.com if you have any questions.)
&lt;/code&gt;
&lt;/pre&gt;




&lt;pre&gt;
&lt;code class=&quot;no-highlight&quot;&gt;
    &gt;&gt; Stripe.api_key = TEST_KEY
    =&gt; ...
    &gt;&gt; Stripe::Charge.retrieve(LIVE_CHARGE_ID)
    Stripe::InvalidRequestError: (Status 404) No such charge: ch_17SOe5QQ2exd2S;
    a similar object exists in live mode, but a test mode key was used to make
    this request.
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;On the other hand, some errors are harder to diagnose (especially from the API's end, since you have limited information about what your user is actually trying to accomplish).&lt;/p&gt;

&lt;p&gt;Where possible, we absolutely think it's worthwhile to try to anticipate our users' errors and help as much as we can.&lt;/p&gt;

&lt;h3&gt;Dealing with Change&lt;/h3&gt;

&lt;p&gt;Lastly, dealing with change is never fun. As much as you hope you'll never have to change the API, sometimes you need to make changes and sometimes those changes are backwards-incompatible.&lt;/p&gt;

&lt;p&gt;There's no easy answer to versioning APIs. We keep a per-user version which reflects the state of the API the first time the user made an API request.  Most of our new features are additions that aren't backwards incompatible, and they just work automatically for everyone.&lt;/p&gt;

&lt;p&gt;Whenever we make a backwards-incompatible change&lt;sup&gt;2&lt;/sup&gt;, however, it doesn't affect the API behavior for any of our current users. Users can then choose to explicitly upgrade their version in the dashboard (after reviewing the &lt;a href=&quot;https://stripe.com/docs/upgrades?since=2011-11-17#API+changelog&quot;&gt;detailed changelogs&lt;/a&gt;) or can send a version override header in any API request to test the behavior of a specific version.&lt;/p&gt;

&lt;h2&gt;Questions?&lt;/h2&gt;

&lt;p&gt;If you have any questions, feel free to &lt;a href=&quot;mailto:%20amber@stripe.com&quot;&gt;email&lt;/a&gt; or &lt;a href=&quot;https://twitter.com/amfeng&quot;&gt;tweet&lt;/a&gt; at me.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Footnotes&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stripe may very well end up implementing these particular features in the future, but it's not generally feasible to try to accommodate everyone's use case.&lt;/li&gt;
&lt;li&gt;We try to avoid this as often as possible.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;&lt;em&gt;Credit for various parts of the presentation content go to Greg Brockman, Sidd Chandrasekaran, Evan Broder, and Ross Boucher. And of course, credit to everyone at Stripe for actually doing the things I outlined in the talk.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Private methods in Ruby</title>
   <link href="http://amberonrails.com/private-methods-in-ruby"/>
   <updated>2012-12-21T00:00:00-08:00</updated>
   <id>http://amberonrails.com/private-methods-in-ruby</id>
   <content type="html">&lt;p&gt;Consider the following code:&lt;/p&gt;

&lt;p&gt;(This blew my mind the other day.)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Hello
  def public_hello
    self.private_hello
  end

  private
  def private_hello
    puts &quot;Hello!&quot;
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You would expect that this would work fine: &lt;code&gt;private_hello&lt;/code&gt; is a private method, but it's being called from within the class.&lt;/p&gt;

&lt;p&gt;Nope.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; hello = Hello.new
=&amp;gt; #&amp;lt;Hello:0x10d0cc200&amp;gt;
&amp;gt;&amp;gt; hello.public_hello
NoMethodError: private method `private_hello' called for #&amp;lt;Hello:0x10d0cc200&amp;gt;
  from (irb):3:in `public_hello'
  from (irb):13
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I spent an embarassingly long time trying to figure out what was wrong (&lt;em&gt;&quot;Do I just not understand how private methods work?!&quot;&lt;/em&gt;), and &lt;a href=&quot;http://twitter.com/maccman/status/281887326639108096&quot;&gt;confused one of my coworkers as well&lt;/a&gt; in the process of doing so.&lt;/p&gt;

&lt;p&gt;However, it turned out to be &lt;a href=&quot;http://twitter.com/maccman/status/281887326639108096&quot;&gt;old&lt;/a&gt; &lt;a href=&quot;http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby&quot;&gt;news&lt;/a&gt;. &lt;a href=&quot;http://www.skorks.com/2010/04/ruby-access-control-are-private-and-protected-methods-only-a-guideline/&quot;&gt;One post&lt;/a&gt; puts the issue pretty succinctly:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;private methods can never be called with an explicit receiver, even if the receiver is self&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;So, the problem with &lt;code&gt;self.private_hello&lt;/code&gt; is that the private method is being called on an explicit receiver, even though the receiver is technically the same object&amp;mdash;you'd need to call &lt;code&gt;private_hello&lt;/code&gt; by itself instead.&lt;/p&gt;

&lt;p&gt;Having learned access control modifiers in Java first, I thought this was really bizarre. I guess I need to learn Ruby a little better! (:&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Discount Code Cards</title>
   <link href="http://amberonrails.com/discount-code-cards"/>
   <updated>2012-10-31T00:00:00-07:00</updated>
   <id>http://amberonrails.com/discount-code-cards</id>
   <content type="html">&lt;p&gt;I love career fairs. In college, I loved going to career fairs to get swag&amp;mdash;EECS majors are definitely ridiculously spoiled when it comes to getting free things like shirts and food (I even got a poker set once!).&lt;/p&gt;

&lt;p&gt;Anyway, while planning our trip to the &lt;a href=&quot;http://ucbstartupfair.com&quot;&gt;UC Berkeley Startup Fair&lt;/a&gt; this year, I wanted Stripe to stand out so I thought pretty hard about what my favorite types of things to get were.&lt;/p&gt;

&lt;p&gt;Number one was shirts, probably. We already had that covered. But I also remembered happily going to the &lt;a href=&quot;https://www.dropbox.com&quot;&gt;Dropbox&lt;/a&gt; booth every semester to get those nifty free space cards: discount codes that you can apply to your account to get 5-10gbs of space at a time.&lt;/p&gt;

&lt;p&gt;What if we made &lt;strong&gt;free Stripe processing cards&lt;/strong&gt;? Since we'd be going to a career fair where all of the students were software engineers, and more specifically, very hacker/startup-minded, it made even more sense as a marketing effort.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/posts/discount-code-cards/discount-cards-blurred.png' style='margin: 30px 0'&gt;&lt;/p&gt;

&lt;h2&gt;Implementation&lt;/h2&gt;

&lt;p&gt;Most of the discount code implementation was already in place from our invite system, so all I really needed to do was generate an extra couple of hundred codes for use at the career fair. The hard part, however, was trying to figure out how to print them.&lt;/p&gt;

&lt;p&gt;Traditional business card printing services won't let you print out cards with unique codes on them unless you go through some kind of custom order. I didn't have too much time to spare, so &lt;a href=&quot;http://johncollison.ie/&quot;&gt;John&lt;/a&gt; told me about this nifty hack he used with &lt;a href=&quot;https://moo.com&quot;&gt;Moo.com&lt;/a&gt; (I later found the same solution on &lt;a href=&quot;http://www.quora.com/How-can-I-print-business-cards-with-unique-codes-on-them/answer/Paul-Lewis-1/quote/96824&quot;&gt;Quora&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Moo lets you do this cool thing where you can print a variable number of designs per order&amp;mdash;for example, if you want to have a different photograph on the back of each business card. We found that if you upload 100 different &quot;designs&quot; for 100 different cards, each card would be unique.&lt;/p&gt;

&lt;p&gt;Their &lt;a href=&quot;https://secure.moo.com/start.php?productTypeName=minicard&amp;amp;contentSourceName=textomatic&quot;&gt;Text-o-matic&lt;/a&gt; tool lets you create up to 100 &quot;designs&quot; that are text only:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/posts/discount-code-cards/moo-text-small.png' style='margin: 30px 0; border: 1px solid #eee;'&gt;&lt;/p&gt;

&lt;p&gt;I took one look at the page and realized I could easily use a script to automatically generate all of the cards (sigh of relief when I discovered the page was not written in Flash):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Create an array of the discount codes you want to use here
var texts = ['CODE1', 'CODE2', 'CODE3'];

// Click buttons on the page for each code to create the design
texts.each(function(text) {
  jQuery('#txtFrontText').val(text);
  jQuery('div#divMakeCard input').click();

  // Set color/size
  jQuery('#a_000000').click();
  jQuery('#aReverseColours').click();
  jQuery('#aZoomOut').click();
  jQuery('#aZoomOut').click();

  jQuery('#btnSaveCard').click();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Really, really simple but pretty hacky (just run this in the developer console on the web page). After this, you'll just go into their general template wizard and upload the design for the other side of the card to finish them up.&lt;/p&gt;

&lt;h2&gt;Improvements&lt;/h2&gt;

&lt;p&gt;Of course, there are several drawbacks to this approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can't really design the &quot;variable&quot; side of the card. You either need to upload the images yourself, or use Text-o-matic, which has a super limited set of options (you can't even add a new line or style separate parts of the text).&lt;/li&gt;
&lt;li&gt;You can only print 100 cards per order. Since the max number of designs you can upload is 100, if you try to double the card count to 200, you'll end up with every unique card twice.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;So what can you do?&lt;/p&gt;

&lt;p&gt;Probably the only legitimate way to do this is to generate the to-print PDF yourself, either using some kind of software (like InDesign) or hacking something in PostScript. I'll be sure to write a follow up post if I end up doing either!&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Goodbye, Wordpress!</title>
   <link href="http://amberonrails.com/goodbye-wordpress"/>
   <updated>2012-09-09T17:46:00-07:00</updated>
   <id>http://amberonrails.com/goodbye-wordpress</id>
   <content type="html">&lt;p&gt;As you may or may not have noticed, this blog has recently undergone a pretty drastic change. Aside from pure design upgrades, I've moved off Wordpress (good riddance!) and joined the geek bandwagon by writing my blog with &lt;a href=&quot;https://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt;. Here's my obligatory &quot;I moved to Jekyll&quot; blog post!&lt;/p&gt;

&lt;h2&gt;Why Jekyll?&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Wordpress is bloated.&lt;/strong&gt; I've never even used a third of the features&amp;mdash;I wanted something super simple and lightweight that I could gradually add onto (if I wanted to).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom styling.&lt;/strong&gt; Wordpress, I've found, is a nightmare to try to style. There are layers upon layers of templates, and I really hate trying to navigate through PHP code. Jekyll, by contrast, is a lot cleaner and easier to deal with.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Markdown/Vim &gt; Wordpress editor.&lt;/strong&gt; I've gotten to the point where I basically need to use Vim for everything (code, obviously, but also notes, to-do lists, etc). Markdown is great, and I like how all of my blog posts are now under version control.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Static pages.&lt;/strong&gt; Blogs are almost pure static content (with the exception of comments, search, etc), so I figured that it would be simpler (and faster) to just have an entirely static site. This makes deploys super easy as well.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;My setup&lt;/h2&gt;

&lt;p&gt;I'm not going to go through in depth how I got my Jekyll set up, because there are &lt;a href=&quot;http://paulstamatiou.com/how-to-wordpress-to-jekyll&quot;&gt;more&lt;/a&gt; &lt;a href=&quot;http://vitobotta.com/how-to-migrate-from-wordpress-to-jekyll/&quot;&gt;than&lt;/a&gt; &lt;a href=&quot;http://alexeymk.com/2012/07/01/moving-to-github-pages-and-jekyll.html&quot;&gt;enough&lt;/a&gt; of those guides out there. Here are some of the main components that I used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standard boilerplate from &lt;a href=&quot;https://github.com/mojombo/mojombo.github.com&quot;&gt;Tom Preston-Warner&lt;/a&gt; himself, with &lt;a href=&quot;https://github.com/mojombo/jekyll/wiki/Pagination&quot;&gt;pagination&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Category generation plugin from &lt;a href=&quot;http://recursive-design.com/projects/jekyll-plugins/&quot;&gt;Recursive Design&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://disqus.com/&quot;&gt;Disqus&lt;/a&gt; for comments. I don't really buy into the whole argument against using Disqus for static sites (that it defeats the purpose of having a static site).&lt;/li&gt;
&lt;li&gt;RSS feed template from &lt;a href=&quot;http://recursive-design.com/blog/2010/09/14/integrating-jekyll-with-feedburner/&quot;&gt;Recursive Design&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;All of the templates and styles are handwritten. Being able to customize all aspects of the blog is definitely one of the major perks of using Jekyll!&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Elasticsearch Space-savers</title>
   <link href="http://amberonrails.com/elasticsearch-space-savers"/>
   <updated>2012-03-18T18:13:41-07:00</updated>
   <id>http://amberonrails.com/elasticsearch-space-savers</id>
   <content type="html">&lt;p&gt;After &lt;a href=&quot;/real-time-search-with-mongodb-and-elasticsearch/&quot;&gt;setting up&lt;/a&gt; ElasticSearch, you'll be faced with the task of optimizing your index configuration for speed and for size. There are millions of documents in our index, and, for performance, it’s important that all of that be kept in memory. As a result, index size is pretty important. We spent a while tweaking ElasticSearch to minimize its index size, and it turns out that there’s a decent number of low-hanging fruit.&lt;/p&gt;

&lt;h2&gt;_source&lt;/h2&gt;

&lt;p&gt;For example, ElasticSearch &lt;a href=&quot;http://www.elasticsearch.org/guide/reference/mapping/source-field.html&quot;&gt;stores&lt;/a&gt; the original data along with the indexed data for each document and returns the full document with each search result. We just wanted ElasticSearch queries to assemble a set of document IDs to be fetched from the database, so this overhead is unnecessary. Cutting this data shrank our search index four-fold.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:_source =&amp;gt; { :enabled =&amp;gt; false }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;_all&lt;/h2&gt;

&lt;p&gt;In addition, ElasticSearch stores an aggregated &lt;a href=&quot;http://www.elasticsearch.org/guide/reference/mapping/all-field.html&quot;&gt;&lt;code&gt;_all&lt;/code&gt;&lt;/a&gt; field on each document, which contains the analyzed output from all of the other fields in the document. This doesn’t add any new information, and its purpose is just to simplify the query interface.&lt;/p&gt;

&lt;p&gt;We don’t need to be able to query all fields (for example, we only use user IDs to partition the index); setting a flag to exclude these from the &lt;code&gt;_all&lt;/code&gt; field and preventing them from being analyzed saved us another 4-5GB for ~2 million documents.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'id' =&amp;gt; { :type =&amp;gt; 'string', :include_in_all =&amp;gt; false }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Multi-field types&lt;/h2&gt;

&lt;p&gt;Other problems were a little trickier. How do we minimize the size of the email address index given that we’d like to be able to perform both prefix and substring searches on them?&lt;/p&gt;

&lt;p&gt;Email addresses may be very long and overflow our ngram tokenizer (which maxes out at fifteen characters), and so we decided to construct a &lt;a href=&quot;http://www.elasticsearch.org/guide/reference/mapping/multi-field-type.html&quot;&gt;multi-field&lt;/a&gt; tiered index for certain fields in to accommodate all of the search use cases. We don't know if this is a best practice, but it seems to work pretty well for us.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Real-time Search with MongoDB and Elasticsearch</title>
   <link href="http://amberonrails.com/real-time-search-with-mongodb-and-elasticsearch"/>
   <updated>2012-03-15T15:15:17-07:00</updated>
   <id>http://amberonrails.com/real-time-search-with-mongodb-and-elasticsearch</id>
   <content type="html">&lt;p&gt;Something I worked on a couple of weeks ago at Stripe was overhauling the entire search infrastructure. If you’ve ever used the search feature in manage, it may have appeared sluggish or may have even timed out on you - this is mostly due to the fact that our search consisted of running a query over our database (which you can imagine is very slow for full-text search).&lt;/p&gt;

&lt;p&gt;We finally decided to make the switch to a dedicated full-text search engine and chose ElasticSearch, which is a distributed RESTful search engine built on top of Apache Lucene. I won’t go into the details, but you can read about ElasticSearch on the &lt;a href=&quot;http://www.elasticsearch.org/&quot;&gt;official website&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Setting up ElasticSearch&lt;/h2&gt;

&lt;p&gt;To set up ElasticSearch, I followed a &lt;a href=&quot;http://www.elasticsearch.org/tutorials/2010/07/01/setting-up-elasticsearch.html&quot;&gt;third-party tutorial&lt;/a&gt; - it’s pretty straight forward, although you should be sure to swap in the current verison number.&lt;/p&gt;

&lt;h2&gt;Hooking up MongoDB&lt;/h2&gt;

&lt;p&gt;Assuming you’re already using MongoDB for the data that you want to index&lt;sup&gt;1&lt;/sup&gt;, you’re probably wondering how to hook it up to index documents in real-time - this is one of the major hurdles that we faced. ElasticSearch has a built in feature of Rivers, which are essentially plugins for specific services to constantly stream in new updates for indexing.&lt;/p&gt;

&lt;p&gt;Unfortunately, there’s no MongoDB River (probably due to the lack of built-in database triggers), so I did some research and realized that I could use the MongoDB oplog to continually capture updates to our main databases.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.mongodb.org/display/DOCS/Replica+Sets+-+Oplog&quot;&gt;oplog&lt;/a&gt; is a special collection held by MongoDB for replication purposes - I was able to make use of a tailable cursor (which performs similarly to the &lt;code&gt;tail -f&lt;/code&gt; command) for shipping new updates from MongoDB to our search server (we’re using &lt;a href=&quot;https://github.com/karmi/tire&quot;&gt;Tire&lt;/a&gt; as our Elasticsearch Ruby DSL).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def initialize
  @host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
  @port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT

  @db_whitelist = %w(payments customers invoices)

  @stream = Queue.new
  @max_bulk = 10000

  # Or, just set up a connection the normal way if you’re not
  # using a repl set
  @connection = ReplSetConnection.new(['database1', 27017],
                                      ['database2', 27017],
                                      ['database3', 27017],
                                      :read =&amp;gt; :secondary)

  local = @connection.db('local')

  # Change to oplog.$main if running mongod as a master instance
  oplog = local.collection('oplog.rs')

  @tail = Cursor.new(oplog,
                     :tailable =&amp;gt; true,
                     :order =&amp;gt; [['$natural', 1]])

  while true
    tailer
    indexer

    # In production, we keep this constantly running in a busy
    # loop; we constantly have new things to index
    # sleep 5
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The code here basically tails the oplog and reads off new operations, pushing them onto &lt;code&gt;@stream&lt;/code&gt;, until there are none left or we’ve reached the max number of entries that we want to batch at a time:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def tailer
  # While there are new entries
  while @tail.has_next?
    _next = @tail.next

    # We only want to index specific collections
    match = /some namespace regex/.match(_next[&quot;ns&quot;])
    if match &amp;amp;&amp;amp; @db_whitelist.include?(match[1])
      @stream &amp;lt;&amp;lt; [match[1], _next]
    end

    # Upon hitting the maximum bulk size we want to send over
    break if @stream.length &amp;gt;= @max_bulk
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Afterwards, we pull rows out of &lt;code&gt;@stream&lt;/code&gt;, transform them into hashes that we actually want to index into Elasticsearch, and bulk index them via Tire. Rinse and repeat.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def indexer
  bulk_index = []
  while !@stream.empty?
    _next = @stream.pop
    item = _next[1]
    type = _next[0]

    # Our TransformRow.transform_for method just returns a hash
    # to index. Ex. {:type =&amp;gt; “customer”, :name =&amp;gt; “Amber”}
    new_row = TransformRow.transform_for(type, item['o'])

    # Add keywords if they exist on the database object
    bulk_index &amp;lt;&amp;lt; new_row
  end

  # Bulk index the data via Tire
  if !bulk_index.empty?
    Tire.index &quot;search&quot; do
      import bulk_index
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course, this is a very basic synchronous example - you could imagine making this into a more flexible asynchronous producer-consumer model.&lt;/p&gt;

&lt;p&gt;In addition, this sort of naive first pass doesn’t save any state, so if the driver crashes due to an timeout on the database side or if the search server is down, the restarted driver will start again from the very beginning. To combat this, I simply wrote a timestamp to &lt;code&gt;/tmp&lt;/code&gt; to keep track of the last record indexed, and queried the collection to start at that specific timestamp the next time around.&lt;/p&gt;

&lt;p&gt;(&lt;strong&gt;Update&lt;/strong&gt;: I recently changed this to write to permanent storage instead; although not necessary, it's simple enough to do and is a better idea in general.)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@tail = oplog.find({
  'ts' =&amp;gt; {'$gte'=&amp;gt; BSON::Timestamp.new(@last_ts, 0) }
})
@tail.add_option(Constants::OP_QUERY_TAILABLE)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But wait, there’s more! Scanning the entire collection in most restart scenarios can be pretty expensive (by the way, the oplog doesn’t allow any indexes), especially if your oplog is large like ours, at 2GB.&lt;/p&gt;

&lt;p&gt;You can take advantage of a special flag for this kind of use only, called &lt;code&gt;OPLOG_REPLAY&lt;/code&gt;. This flag is meant for replication purposes - it first starts from the bottom of the log and searches upward for around 100MB or so, assuming that you just restarted (which is usually the case if the tailer crashes and restarts immediately). If it can’t be found, it’ll continue by traversing extents in the most efficient manner possible.&lt;/p&gt;

&lt;pre&gt;&lt;code class='ruby'&gt;@tail.add_option(Constants::OP_QUERY_OPLOG_REPLAY)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Running this tailer as a daemontools service, we were able to attain nearly real-time search latency. It takes around 3-5 seconds from the time a record is created or updated to when it gets indexed (and is searchable) in ElasticSearch - pretty cool!&lt;/p&gt;

&lt;h4&gt;Footnotes&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;It’s possible to use ElasticSearch as a data store itself (it’ll store the document data as well as the index data), but I’m not convinced this is a good idea in practice.&lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 
 
 <entry>
   <title>2012 CS Resolutions</title>
   <link href="http://amberonrails.com/2012-cs-resolutions"/>
   <updated>2012-01-03T20:43:36-08:00</updated>
   <id>http://amberonrails.com/2012-cs-resolutions</id>
   <content type="html">&lt;p&gt;Matt Might's &lt;a href=&quot;http://matt.might.net/articles/what-cs-majors-should-know/&quot;&gt;&quot;What every computer science major should know&quot; article&lt;/a&gt; is fantastic. I regret not reading this article in the beginning of the holiday break, but I guess I can use this as sort of a &quot;2012 CS Resolutions&quot; list since everyone seems to be making New Years resolutions right about now.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Master LaTex&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt; In school, I never really used LaTex for typing up assignments until last semester for our project design docs. I actually don't know how feasible this will be to do now that I'm in the &quot;real world&quot;, but I'll take any chance I can get to write up documents in pretty LaTex!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Be better at UNIX/Sysadmin-ing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;  Being traditionally a frontend person, I don't have a crazy amount of experience working with command line or doing sysadmin-y things. Sure, I know how to do some elementary things and I'm a vim fanatic (by the way, vim &gt; emacs). However, I'd like to be able to count myself as an expert at writing shell scripts or configuring a web server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learn a couple of new languages&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;  Not for the sake of &quot;adding new languages on my resume&quot;, which is absolutely useless, but for exploring and mastering new programming paradigms. A few that sparked my interest/I've been meaning to pick up: Scala, Haskell, Erlang.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&quot;Understand a computer from the transistors up&quot;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;  Being an EECS major has exposed me to all of the &quot;levels&quot; of a computer, but I never took much effort in trying to piece things together and much of my EE knowledge is long forgotten.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Get some hands-on experience with Operating Systems&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt; The semester I took it, Berkeley dramatically changed their traditional Operating Systems class into a hybrid (read: less in-depth/useful) systems class that covered minimal multi-programming and memory/scheduler topics but didn't actually give us any practical experience with how operating systems work. In particular, I'd love to learn more about file systems and possibly tinker around with the Linux kernel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Catch up on reading systems papers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt; I have a giant list of systems papers to go through/that I semi-went through during winter break courtesy of my friend &lt;a href=&quot;http://pedapudi.posterous.com/&quot;&gt;Sunil&lt;/a&gt; and the &lt;a href=&quot;http://www.cs.berkeley.edu/~istoica/classes/cs294/11/&quot;&gt;graduate cloud computing course&lt;/a&gt; at Berkeley. In addition, &lt;a href=&quot;http://www.stripe.com&quot;&gt;Stripe&lt;/a&gt; has super cute academic paper reading lunches, which I'm really excited about! I'm sure this will be an easy resolution to keep up with. (:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;After reading the article, I'm not super satisfied with what I learned in my 3.5 years as a Berkeley EECS major. I'm looking forward to filling in the gaps now that I've graduated!&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Paxos/Multi-paxos Algorithm</title>
   <link href="http://amberonrails.com/paxosmulti-paxos-algorithm"/>
   <updated>2011-12-02T12:53:33-08:00</updated>
   <id>http://amberonrails.com/paxosmulti-paxos-algorithm</id>
   <content type="html">&lt;p&gt;A &lt;a href=&quot;/eventual-consistency/&quot;&gt;couple of posts ago&lt;/a&gt;, I talked about the distributed systems programming class I was taking here in my last semester at Berkeley. Our projects are really cool - we've done everything from a quorum KVS to a distributed lock manager, and for our final project, my group chose to implement Multi-paxos. I'll start by explaining general Paxos first.&lt;/p&gt;

&lt;p&gt;Basically, Paxos is an protocol (or technically, a &quot;family&quot; of protocols, says &lt;a href=&quot;http://en.wikipedia.org/wiki/Paxos_(computer_science&quot;&gt;Wikipedia&lt;/a&gt;) that solves the problem of getting a group of nodes to agree, or reach consensus, on a single value.&lt;/p&gt;

&lt;h2&gt;Why is this important?&lt;/h2&gt;

&lt;p&gt;If there's a stable master, there's hardly any use for this, because the master can just decide and propose values itself and have the other nodes always follow it. However, what if leader election fails (and it sometimes does), and there are two nodes proposing values?&lt;/p&gt;

&lt;p&gt;The Paxos algorithm ensures that only one value is chosen out of all of the proposed values. Where this algorithm comes in handy is when you'd like your distributed system to decide on a sequence of values, or in other words, a consistent ordering over a set of values. As &lt;a href=&quot;http://ayende.com/blog/4496/paxos-enlightment&quot;&gt;Ayende Rahien&lt;/a&gt; describes, if these values are events, then you know that all of the machines in the cluster have the same state or subset of the state.&lt;/p&gt;

&lt;h2&gt;Algorithm&lt;/h2&gt;

&lt;p&gt;The Paxos algorithm is divided into two phases, the &lt;em&gt;prepare&lt;/em&gt; phase, and the &lt;em&gt;accept&lt;/em&gt; phase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: the text in this section is partially paraphrased from Leslie Lamport's excellent &lt;a href=&quot;http://research.microsoft.com/en-us/um/people/lamport/pubs/paxos-%20simple.pdf&quot;&gt;Paxos Made Simple&lt;/a&gt; paper.&lt;/p&gt;

&lt;h3&gt;Prepare Phase&lt;/h3&gt;

&lt;p&gt;In the &lt;em&gt;prepare&lt;/em&gt; phase, the proposer selects a proposal number &lt;code&gt;n&lt;/code&gt; (which is greater than any &lt;code&gt;n&lt;/code&gt; it has previously sent, and distinct from any &lt;code&gt;n&lt;/code&gt; that any other proposers' &lt;code&gt;n&lt;/code&gt; values, I'll discuss this more later) and sends a &lt;code&gt;PREPARE&lt;/code&gt; request to a majority of the acceptors.&lt;/p&gt;

&lt;p&gt;On the acceptor side, if it ever receives a &lt;code&gt;PREPARE&lt;/code&gt; request with a proposal number &lt;code&gt;n&lt;/code&gt; greater than that of any other proposal number &lt;code&gt;n&lt;/code&gt; that it has previously received, it responds with a &quot;promise&quot; to not accept any proposals with a lower numbered &lt;code&gt;n&lt;/code&gt; in the future and the value of the highest-numbered proposal that it has already accepted (if any).&lt;/p&gt;

&lt;p&gt;Starting to sound confusing? I had to read this over several times before I actually understood it, so maybe the pseudocode below will help.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Proposer
for acceptor in acceptors
  send :prepare_req, next_n()

# Acceptor
if (req.n &amp;gt; highest_proposed_n)
  highest_proposed_n = req.n
  reply :prepare_resp, {
    :n =&amp;gt; highest_acc.n,
    :value =&amp;gt; highest_acc.value
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Accept Phase&lt;/h3&gt;

&lt;p&gt;After a proposer has received a response to its &lt;code&gt;PREPARE&lt;/code&gt; requests from a majority of the acceptors, it then sends an &lt;code&gt;ACCEPT&lt;/code&gt; to those acceptors with a value &lt;code&gt;v&lt;/code&gt;, where &lt;code&gt;v&lt;/code&gt; is the value of the highest numbered proposal among the responses, or any value if the responses reported no other proposals.&lt;/p&gt;

&lt;p&gt;By contrast, when an acceptor receives an &lt;code&gt;ACCEPT&lt;/code&gt; request, it always accepts it unless it has already promised not to in the &lt;em&gt;prepare&lt;/em&gt; phase.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Proposer
for acceptor in acceptors
  send :accept_req, responses.argmax { |i| i.n }.value }

# Acceptor
if (req.n &amp;gt;= highest_proposed_n)
  highest_acc = {:n =&amp;gt; req.n, :value =&amp;gt; req.value}
  reply :accept_resp
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Multi-paxos&lt;/h2&gt;

&lt;p&gt;All this talk about Paxos. How does Multi-paxos fit in?&lt;/p&gt;

&lt;p&gt;I mentioned in the introduction that one of the main useful applications of the Paxos application is having the group of participants decide on a sequence of numbers. Since one round of Paxos results in a decision of one value, the naive way to go about finding a sequence of numbers would be to run Paxos many times, right?&lt;/p&gt;

&lt;p&gt;One optimization that can be made in this case, assuming a single stable leader, is to skip the &lt;em&gt;prepare&lt;/em&gt; phase. If we assume that the leadership will remain &quot;sticky&quot;, there is no need to continue sending out proposal numbers - the first proposal number sent out will never be &quot;overridden&quot; since there is only one leader.&lt;/p&gt;

&lt;p&gt;Thus, we only need to do the &lt;em&gt;prepare&lt;/em&gt; phase once. In subsequent rounds of Paxos, we can just send the &lt;code&gt;ACCEPT&lt;/code&gt; messages, with &lt;code&gt;n&lt;/code&gt; as the proposal number used in the original &lt;code&gt;PREPARE&lt;/code&gt; request and an additional parameter that indicates the sequence number (the current round we're in). We don't have to worry about the worst case where leadership isn't stable (or distinct), because the algorithm will degrade gracefully into the general Paxos algorithm (both &lt;em&gt;prepare&lt;/em&gt; and &lt;em&gt;accept&lt;/em&gt; phases for each round). Cool!&lt;/p&gt;

&lt;h2&gt;Other Considerations&lt;/h2&gt;

&lt;h3&gt;Persistent Storage&lt;/h3&gt;

&lt;p&gt;Machines must keep certain things in persistent storage to be able to recover from failures. In particular, acceptors need to be able to remember which &lt;code&gt;PREPARE&lt;/code&gt; requests they have promised to follow, and which &lt;code&gt;ACCEPT&lt;/code&gt; requests they have responded to in order to make decisions about which proposals to promise to and to pass necessary information back to the proposes.&lt;/p&gt;

&lt;h3&gt;Distinct Proposal Numbers &lt;code&gt;n&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;In order for the algorithm to work, each proposer must propose monotonically increasing proposal numbers &lt;code&gt;n&lt;/code&gt; that are distinct from any other proposers' numbers &lt;code&gt;n&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To achieve this, we can assign disjoint sets of numbers for each proposer and have them only choose numbers from their own set (ex. assign each node a unique prime number, they choose multiples of that prime number).&lt;/p&gt;

&lt;p&gt;Or, if we're assuming static membership of participants, assign each node a unique number &lt;code&gt;i&lt;/code&gt; between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;k&lt;/code&gt;, where &lt;code&gt;k&lt;/code&gt; is the total number of participants, and &lt;code&gt;n = i + (k * round_number)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;tl;dr&lt;/strong&gt; Paxos is for getting a group of machines to agree on a value (or more usefully, provide a consistent ordering on a sequence of values). Multi-paxos is an optimization on using Paxos for consecutive rounds, where you can skip one of the phases if you assume a stable leader.&lt;/p&gt;

&lt;p&gt;Hope this post was interesting and/or informative! Similar to the &lt;a href=&quot;/eventual-consistency/&quot;&gt;eventual consistency&lt;/a&gt; post, I don't claim to be an expert in this area, so I'd love to hear any comments or corrections.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Using Javascript Timeouts for Performance</title>
   <link href="http://amberonrails.com/using-javascript-timeouts-for-performance"/>
   <updated>2011-10-29T12:54:50-07:00</updated>
   <id>http://amberonrails.com/using-javascript-timeouts-for-performance</id>
   <content type="html">&lt;p&gt;Wait, what? Doesn't setting timeouts in Javascript delay a piece of code from being run for an X amount of time, so how could it possibly help with performance?&lt;/p&gt;

&lt;p&gt;Imagine writing a Javascript app that is doing some large, computationally-expensive task like adding a five thousand elements to the DOM:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var list = document.getElementByTagName(&quot;ul&quot;)[0];
for (var i = 0; i &amp;lt; 5000; i++) {
  var newElement = document.createElement(&quot;li&quot;);
  list.append(newElement);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since Javascript is single threaded, executing Javascript will suspend any user interface interaction and/or updates to the page - some browsers like Chrome will even try to kill the script if it's been running for too long (have you ever seen that sad face &quot;Oops&quot; page?).&lt;/p&gt;

&lt;p&gt;With the use of timers, we can split up the code into different segments (ex. 10 loops doing 500 DOM additions each):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var curr = 0; var max = 4999;
var step = 500;
var list = document.getElementByTagName(&quot;ul&quot;)[0];

setTimeout(function() {
  for (var end = curr + step; curr &amp;lt; end; curr++) {
    var newElement = document.createElement(&quot;li&quot;);
    list.append(newElement);
  }
  if (curr &amp;lt; max) { setTimeout(arguments.callee, 0); }
}, 0);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Setting the timer to 0 will tell the browser to fire off the timers as quickly as possible (in most browsers, the minimum timer delay is around 10-15ms). However, since the code is broken up into smaller pieces, it will allow the browser to do things like render updates to the page and respond to user events - basically, being more responsive (this is good!).&lt;/p&gt;
</content>
 </entry>
 
 
 
 
 
 <entry>
   <title>Eventual Consistency</title>
   <link href="http://amberonrails.com/eventual-consistency"/>
   <updated>2011-10-17T15:38:42-07:00</updated>
   <id>http://amberonrails.com/eventual-consistency</id>
   <content type="html">&lt;p&gt;I mentioned in my previous post that I was taking a &lt;a href=&quot;http://db.cs.berkeley.edu/w/cs-194-17-programming-the-cloud/&quot;&gt;Programming in the Cloud&lt;/a&gt; class on distributed systems and programming this semester, and one of the perks of this class is that we occasionally have speakers from the industry come in to talk about various topics.&lt;/p&gt;

&lt;p&gt;Last week, &lt;a href=&quot;http://research.microsoft.com/en-us/people/terry/&quot;&gt;Doug Terry&lt;/a&gt; from Microsoft Research came in to speak about eventual consistency, which I found super, super interesting. I don't claim to be an expert on the topic now, but here are my notes (more or less from memory). First, the two opposite sides of the spectrum:&lt;/p&gt;

&lt;h2&gt;Strong vs. Eventual&lt;/h2&gt;

&lt;h4&gt;Strong Consistency -  guaranteed consistency across replicas&lt;/h4&gt;

&lt;p&gt;Strong consistency guarantees, well, strong consistency. Any read always returns up-to-date data, although this may result in lower availability since you're limiting the machines that you're able to read from to keep this guarantee.&lt;/p&gt;

&lt;h4&gt;Eventual Consistency - all replicas will &quot;eventually&quot; become consistent.&lt;/h4&gt;

&lt;p&gt;Although this weaker form of consistency has better availability because you can read to/write from any machine, you can only hope that the data will be fresh (for some applications, this is enough).&lt;/p&gt;

&lt;h2&gt;And everything in between&lt;/h2&gt;

&lt;p&gt;This isn't an exhaustive list of consistency models, but a couple of other models in the middle of the spectrum that Doug went over that day:&lt;/p&gt;

&lt;h4&gt;Read My Writes - guaranteed to be able to read updates you write&lt;/h4&gt;

&lt;p&gt;In applications where you're doing some sort of read then update operations (like &lt;code&gt;x+=1&lt;/code&gt;), it's &lt;em&gt;very&lt;/em&gt; important to be able to your own writes. The example Doug gave during lecture was a baseball analogy, where a scorekeeper is keeping track of the current score of the game with operations like &lt;code&gt;homeScore +=1&lt;/code&gt; for every home run scored for the home team. It's a different story if there are multiple scorekeepers, where you might need some causal consistency guarantees, but a single scorekeeper must at minimum be able to read his own writes.&lt;/p&gt;

&lt;p&gt;Afterwards in class, we had a discussion about the various ways that this consistency model could be implemented. There needs to be some sort of versioning system for the clients to be able to compare with the machines to determine if their writes are stored there or not, or as an optimization, the client could store the writes locally and always be able to &quot;read their own writes&quot; if they take the union of their write set and any other machines' write set.&lt;/p&gt;

&lt;h4&gt;Consistent Prefix - updates returned are some prefix of all the updates, with no gaps&lt;/h4&gt;

&lt;p&gt;In case the title didn't make sense, a &quot;consistent prefix&quot; means that some prefix of all of the writes (assuming the writes have a global order) are applied such that the prefix is consistent (&quot;up to date&quot; up until the last write in the prefix, with no gaps).&lt;/p&gt;

&lt;p&gt;For example, if the writes are A, B, C, D, E, F, you will be able to read some consecutive set of these writes, starting with A. Note that the empty set is also trivially a consistent prefix.&lt;/p&gt;

&lt;p&gt;Why is this useful? Following the baseball analogy from before, if you are recording score writes of &lt;code&gt;A: 1&lt;/code&gt;, &lt;code&gt;B: 2&lt;/code&gt;, &lt;code&gt;A: 3&lt;/code&gt;, &lt;code&gt;B: 6&lt;/code&gt;, &lt;code&gt;A: 5&lt;/code&gt;, &lt;code&gt;B:7&lt;/code&gt; and you don't have a consistent prefix guarantee, you could be reading a database that only has the third and last writes applied, giving you &lt;code&gt;A: 3&lt;/code&gt; and &lt;code&gt;B: 7&lt;/code&gt; when in reality, that combination of scores never existed.&lt;/p&gt;

&lt;h4&gt;Monotonic Reads - for each client, guaranteed to read a more recent or at least the same set of updates&lt;/h4&gt;

&lt;p&gt;Monotonic reads guarantees that you'll never &quot;go back in time&quot; in terms of seeing updates - you'll always see a set of updates that is at least as new as the updates you saw the last time you read from the system. The implementation of this requires a client to keep some kind of version of when it performed its last read, and search for a machine that has at least those writes. However, like Read My Writes, we can apply the same optimization of keeping a read set on the client (and performing a union whenever reading from the system).&lt;/p&gt;

&lt;p&gt;Since we're only concerned with reading data that &lt;em&gt;at least&lt;/em&gt; as fresh as the last time we read it, we can also introduce a notion of &quot;stickiness&quot; or &quot;affinity&quot;, where a client stays with the last machine it read (until it goes down, at least) instead of re-searching for another machine that is more up-to-date. Assuming a single machine will never lose any updates it has applied, staying with the same machine is trivially monotonic.&lt;/p&gt;

&lt;h4&gt;Bounded Staleness&lt;/h4&gt;

&lt;p&gt;Last one! Hopefully you find this fascinating (like I do), and not boring. The idea of staleness allows consistency to be defined in terms of how old a replica can be compared to the most up-to-date data. In some applications, it's okay to have the data be a little stale - for example, weather reports can be a couple hours old. Strong consistency is a special case of Bounded Staleness where the amount of staleness is none.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Wow, this blog post took longer than I thought it would to write. I'm really interested in these topics (and databases/distributed systems in general), so I'm pretty excited for what the class has in store for us for the rest of the semester!&lt;/p&gt;

&lt;p&gt;Again, I don't claim to be an expert in this field (and most of these notes are from memory), so feel free to point out any mistakes/incorrect assumptions or start a discussion in the comments. Thanks for reading! (:&lt;/p&gt;
</content>
 </entry>
 
 
 
 
 
 
 
 <entry>
   <title>Sorry for the long hiatus!</title>
   <link href="http://amberonrails.com/sorry-for-the-long-hiatus"/>
   <updated>2011-10-05T22:51:57-07:00</updated>
   <id>http://amberonrails.com/sorry-for-the-long-hiatus</id>
   <content type="html">&lt;p&gt;I know I always write a post like this every couple of months or so, but I swear I'm coming back to blogging soon!&lt;/p&gt;

&lt;p&gt;It's my (probably) my last semester at Berkeley, and I'm really excited and terrified at the same time. My workload this semester is intentionally light (well, &quot;light&quot; by Berkeley EECS standards) because I want to focus more on working on awesome side projects, but I've still been bogged down with projects and interviews.&lt;/p&gt;

&lt;p&gt;I'm currently taking &lt;a href=&quot;http://inst.eecs.berkeley.edu/~cs162/fa11/&quot;&gt;CS162&lt;/a&gt;, which was originally the upper-division OS course at Berkeley but now is an &quot;introduction to systems&quot; course, and a crazy fun experimental &lt;a href=&quot;http://db.cs.berkeley.edu/w/cs-194-17-programming-the-cloud/&quot;&gt;Programming in the Cloud&lt;/a&gt; class which focuses on distributed systems programming. Both of these classes have got me thinking about what I actually want to do when I graduate, because although I've primarily been a frontend person (go look at my portfolio), I'm super interested in databases and distributed systems and would love to learn more about these topics.&lt;/p&gt;

&lt;p&gt;And speaking of graduating/jobs, I got my first ever full-time offer last week, from Google! I've also been going on a ridiculous amount of interviews with other large companies (Facebook, Microsoft, etc) and small startups trying to find a project I could be passionate about. Who knows, who knows.&lt;/p&gt;

&lt;p&gt;Also - sorry, this post seems to be very scattered; I'm tired from working on my CS162 project - I went to my last ever (tear) Yahoo hackathon a couple of weekends ago, and we had a blast building a multiplayer/realtime WebGL Bomberman game called &lt;a href=&quot;http://www.amberfeng.com/projects/bombermen&quot;&gt;Bombermen&lt;/a&gt;. We won an honorable mention and I'm currently in the process of cleaning up the code (JavaScript at 3am = messy, unorganized JavaScript), so keep a lookout for a demo on my portfolio and/or HackerNews sometime soon!&lt;/p&gt;
</content>
 </entry>
 
 
 
 
 
 <entry>
   <title>Subtle Inset Styles</title>
   <link href="http://amberonrails.com/subtle-inset-styles"/>
   <updated>2011-08-18T20:45:08-07:00</updated>
   <id>http://amberonrails.com/subtle-inset-styles</id>
   <content type="html">&lt;p&gt;It's the mark of a great designer when someone comes to your site and knows it looks good, but doesn't know why. I love using subtle styling in my designs and one of my favorites is applying inverse drop shadows to give the appearance that something is inset.&lt;/p&gt;

&lt;p&gt;Take my portfolio, for instance. If you look carefully, you'll notice that the text has a thin white outline on the top of the text to make it look carved in:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/subtle-inset-styles/inset_text.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;How do you achieve this, you ask? Simple, just add the following style to your text - you can adjust the colors, blur, and position of the shadow to your own tastes.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;p {
    text-shadow: white 0px -1px 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another type of subtle styling I love is inset styling for text fields. I don't really like the standard UI for browser text fields, so I always override it (&lt;code&gt;border: 0px; outline: none;&lt;/code&gt; for the win!) and apply my own minimalistic styling.&lt;/p&gt;

&lt;p&gt;I've always really enjoyed the subtle inset style on &lt;a href=&quot;http://www.grooveshark.com&quot;&gt;Grooveshark&lt;/a&gt;'s login fields (they use background images), but only recently discovered the CSS way of doing it, with box shadows. Well, I won't keep you in suspense any longer; here it is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;input.field {
    box-shadow: inset 0 1px 1px 1px #dedede;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Don't forget to add the &lt;code&gt;-webkit&lt;/code&gt; and &lt;code&gt;-moz&lt;/code&gt; prefixes to make sure your code is cross browser compatible! When done correctly, it should look like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/subtle-inset-styles/field_inset.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;(That's a sneak peek of something new I'm working on!)&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Ajax Partial Loading</title>
   <link href="http://amberonrails.com/ajax-partial-loading"/>
   <updated>2011-07-30T04:35:21-07:00</updated>
   <id>http://amberonrails.com/ajax-partial-loading</id>
   <content type="html">&lt;p&gt;In today's applications, it's common to use AJAX to load dynamic parts of a website without having to do a full page refresh. With Rails, it's easy to template these changes instead of using Javascript to update the DOM structure manually.&lt;/p&gt;

&lt;p&gt;Imagine you have some portion of the page (say, a list of users that already has it's own partial) that you want to dynamically update with AJAX. You could: A) In your AJAX callback, construct the DOM elements manually and append them, like so:&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;javascript&quot;&gt;var userList = $(&quot;#mylist&quot;);
$(&quot;&amp;lt;li&amp;gt;Amber Feng&amp;lt;/li&amp;gt;&quot;).appendTo(userList);&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;This works perfectly fine in simple cases. But what if you later want to update the list elements to have a class named &quot;user&quot;, and/or add a couple of spans inside of that list element to hold things like profile pictures, latest tweets, etc?&lt;/p&gt;

&lt;p&gt;You'd have to change the partial to reflect that, for when the page is first loaded, and change your Javascript callback to reflect the changes for when you use an AJAX call to append things to the list as well.&lt;/p&gt;

&lt;p&gt;This isn't DRY - and it's just plain messy to do manual DOM construction and appending. Instead, do this: B) Since you have a partial for the list of users anyway, just take advantage of this and have Rails generate the HTML for you to append. Stick a method in your controller for passing you back the html:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def render_partial
  render :json =&amp;gt; {
    :html =&amp;gt; render_to_string({
      :partial =&amp;gt; &quot;mypartial&quot;,
      :locals =&amp;gt; {:v =&amp;gt; v}
    })
  }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And just append the callback data to the container that your list is in.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$.get(&quot;/render_partial&quot;,
  {params: params},
  function(data) {
    $(&quot;#mylist&quot;).empty();
    $(&quot;#mylist&quot;).append(data.html);
  }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Voila! Now, if you ever need to change the template for what the user's list is supposed to look like, you do it in one place (the Rail's partial, in case you haven't caught on yet), and that will automatically be used every time the page is loaded and every time your AJAX needs to update the list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caution&lt;/strong&gt;: This does put somewhat of a heavier load on the server because you're hitting up the Rails application stack again every time you need to change something via AJAX on a page instead of adding it client side via Javascript.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Rails Authlogic Conditional Validations</title>
   <link href="http://amberonrails.com/rails-authlogic-conditional-validations"/>
   <updated>2011-07-10T14:25:55-07:00</updated>
   <id>http://amberonrails.com/rails-authlogic-conditional-validations</id>
   <content type="html">&lt;p&gt;When building a web app, one of the first features you usually add is the ability for users to register and log in to see their data linked with their personal account. And most of the time, you will be using validations on your User model to ensure that the email is formatted like a real email address, and password is at least characters, and so on.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Side note: If you don't know about validations, check them out at the &lt;a href=&quot;http://guides.rubyonrails.org/active_record_validations_callbacks.html&quot;&gt;official Rails guide&lt;/a&gt; - they're dead useful.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this post, I'll be referencing the authentication gem &lt;a href=&quot;https://github.com/binarylogic/authlogic&quot;&gt;Authlogic&lt;/a&gt; and the fact that it automatically handles user model validations for you. If you're using another gem/plugin or building your own authentication system, you're probably interested in the &lt;a href=&quot;http://guides.rubyonrails.org/active_record_validations_callbacks.html&quot;&gt;ActiveRecord's validation documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Gradual Engagement&lt;/h2&gt;

&lt;p&gt;Anyways, so now you have your validations in place. But what if you want to enable access for &quot;guest&quot; users, or allow users to omit information like emails or passwords under certain circumstances?&lt;/p&gt;

&lt;p&gt;Coined &lt;strong&gt;&quot;gradual engagement&quot;&lt;/strong&gt; by the Rails/Authlogic community, there's a simple way to do this. I spent a couple of frustrated hours this morning stuck on this problem and hunting through Google Groups logs, Github Gists and various blogs, so I'm happy to share. From &lt;a href=&quot;https://gist.github.com/459563&quot;&gt;Kevin Triplett's Github Gist&lt;/a&gt;, all you need to do is add certain config options to your acts_as_authentic line in your model.&lt;/p&gt;

&lt;p&gt;In my case (in &lt;code&gt;app/models/users.rb&lt;/code&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;acts_as_authentic do |c|
  c.merge_validates_format_of_login_field_options :unless =&amp;gt; :guest?
  c.merge_validates_length_of_login_field_options :unless =&amp;gt; :guest?
  c.merge_validates_length_of_password_field_options :unless =&amp;gt; :guest?
  c.merge_validates_format_of_email_field_options :unless =&amp;gt; :guest?
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Multiple validation groups&lt;/h2&gt;

&lt;p&gt;Alternatively, if you want to have finer grained control over what validations are enabled when and have multiple &quot;validation groups&quot; to turn on and off, I stumbled across another solution that might interest you: Put &lt;a href=&quot;https://github.com/railsdog/spree/blob/52105befa0c0533caa21aa81a55c897bc1c34198/lib/validation_group.rb&quot;&gt;this code&lt;/a&gt; in your &lt;code&gt;lib/&lt;/code&gt; folder. In your model of interest, add these lines to configure your validation groups (courtesy of Alan Gutierrez from the Authlogic Google Group):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class User &amp;lt; ActiveRecord::Base
  validates_presence_of :first_name, last_name, :email
  validation_group :invitation, :fields =&amp;gt; [&quot;email&quot;]
  validation_group :registration, :fields =&amp;gt; [&quot;first_name&quot;, &quot;last_name&quot;]
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@user.enable_valiation_group(:invitation)
@user.save! # Will only validate email.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Easy peasy.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Being a Designer</title>
   <link href="http://amberonrails.com/being-a-designer"/>
   <updated>2011-07-09T16:34:36-07:00</updated>
   <id>http://amberonrails.com/being-a-designer</id>
   <content type="html">&lt;blockquote&gt;&lt;p&gt;Being a designer is like being Priest in an MMO.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;This is probably the nerdiest and geekiest thing I've ever said, but it's totally true. As far as I've seen (or maybe this is just in Berkeley), there's a disproportionate ratio of designers to developers so I'm constantly being called on by startups or project teams looking for UX work.&lt;/p&gt;

&lt;p&gt;I'm definitely not complaining - this is awesome news for me. But it's a little lonely not knowing too many other designers in the area, and I'd love to be able to collaborate on projects or bounce ideas off another design-minded person. I got my first taste of this at my internship where there's an actual UX/design engineer on the team, and I have to say that I loved the experience!&lt;/p&gt;

&lt;p&gt;So if there are any budding or veteran designers who go to Berkeley or are in the area, just holler. (:&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Exporting SVN to Git</title>
   <link href="http://amberonrails.com/exporting-svn-to-git"/>
   <updated>2011-06-18T09:54:03-07:00</updated>
   <id>http://amberonrails.com/exporting-svn-to-git</id>
   <content type="html">&lt;p&gt;I love Git.&lt;/p&gt;

&lt;p&gt;So much, in fact, that when I switched web hosts last month I decided to move all of my SVN repositories and put them on &lt;a href=&quot;https://github.com/afeng&quot;&gt;Github&lt;/a&gt; or into private Git repositories. Github's SVN import utility is painfully slow (and maybe even broken, I'm not sure) - so here's how to do it yourself. First, create a mapping from all SVN authors to Git authors in a file of the format:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;amber.feng = Amber Feng &amp;lt;me@amberonrails.com&amp;gt;
(no author) = No Author &amp;lt;nothing@amberonrails.com&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Create a directory for your new Git repository and use the following git svn command to export:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git svn --authors-file=path/to/authors_file clone SVN_REPO_URL LOCAL_DIR
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should now see log message &lt;code&gt;Initializing empty Git repository ...&lt;/code&gt; followed by add, modify, and delete Git messages showing you the current status of the export.&lt;/p&gt;

&lt;p&gt;The whole process can take from seconds to hours depending on how large the SVN repository is. Once, you're finished with the export, you can push the changes a hosted Git repository of your choice (Github, private, etc).&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Paperclip + S3 with Rails</title>
   <link href="http://amberonrails.com/paperclip-s3-with-rails"/>
   <updated>2011-05-26T20:17:11-07:00</updated>
   <id>http://amberonrails.com/paperclip-s3-with-rails</id>
   <content type="html">&lt;p&gt;When I revamped my portfolio, one of the major changes I did was to change my attachment process to upload files (screenshots of my projects, etc) to Amazon S3 instead of to the local
filesystem.&lt;/p&gt;

&lt;h2&gt;Why S3?&lt;/h2&gt;

&lt;p&gt;Putting large media files on S3 (aka &quot;content storage/distribution&quot;) is a great idea because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You don't have to use up large amounts of storage on your web hosting plan, and S3 is super cheap. Even if you have an unlimited storage plan or aren't worried about using it up, this is still good idea because your files are all stored externally so you don't have to worry about backing them up or moving them if you want to switch hosts later (like I did).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amazon S3 is cheap (can you say &quot;less than five cents a month&quot;?), fast, scalable, and reliable. And probably many more nice things that I'm forgetting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rails is slow, and going through the application stack to pull images all the time is slow.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Now that I've convinced you, I'm going to show you how incredibly easy it is to have your uploads upload directly to S3 with the help of a handy plugin called &lt;a href=&quot;https://github.com/thoughtbot/paperclip&quot;&gt;Paperclip&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Uploads with Paperclip&lt;/h2&gt;

&lt;p&gt;Note, this is assuming that you are already using Paperclip in your app for your file attachment service. To do that, there's a great Quick Start guide &lt;a href=&quot;https://github.com/thoughtbot/paperclip&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, add the aws-s3 gem in your Gemfile (you are using Rails3's bundler, aren't you? If not, &lt;a href=&quot;http://gembundler.com/rails3.html&quot;&gt;get started&lt;/a&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem 'aws-s3', :require =&amp;gt; 'aws/s3'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, create a file called s3.yml in your config/ directory (where database.yml lives as well):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;access_key_id: [YOUR AWS ACCESS KEY]
secret_access_key: [YOUR AWS SECRET KEY]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In whatever model you created for the uploaded object(s), for instance mine is
Photo, add the following parameters to the usual Paperclip command like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;has_attached_file :photo,
                  :storage =&amp;gt; :s3,
                  :s3_credentials =&amp;gt; &quot;#{RAILS_ROOT}/config/s3.yml&quot;,
                  :s3_permissions =&amp;gt; &quot;public-read&quot;,
                  :path =&amp;gt; &quot;:filename&quot;,
                  :bucket =&amp;gt; [YOUR S3 BUCKET NAME]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that's it! Now whenever you upload files via Paperclip, the files will be automatically uploaded to the proper S3 bucket and the resource URL will point to the S3 static url.&lt;/p&gt;

&lt;p&gt;Have fun uploading!&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>The Boy Scout Rule</title>
   <link href="http://amberonrails.com/the-boy-scout-rule"/>
   <updated>2011-05-26T12:45:52-07:00</updated>
   <id>http://amberonrails.com/the-boy-scout-rule</id>
   <content type="html">&lt;p&gt;During the last couple of weeks I've been reading &lt;a href=&quot;http://techbus.safaribooksonline.com/book/programming/9780596809515&quot;&gt;97 Things Every Programmer Should Know&lt;/a&gt; online, it's a great book full of interesting and enlightening articles.&lt;/p&gt;

&lt;p&gt;One that stuck to me in particular was #8 - The Boy Scout Rule. From the real-life Boy Scout rule &quot;always leave a place cleaner than you found it&quot;, Robert Martin proposes a parallel to programming projects:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Always check in a module cleaner than when you checked it out.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Not making the code perfect, but taking a few moments to clean something up, whether it be abstracting a long method into several methods, documenting a line of obscure code, or changing a variable name to be more clear.&lt;/p&gt;

&lt;p&gt;This way, rather than a codebase becoming messier and more outdated over time, it would be more maintainable and lead to a team working together to help improve eachothers' code (and actually knowing how other peoples' parts are implemented).&lt;/p&gt;

&lt;p&gt;What a refreshing concept.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>A busy semester..</title>
   <link href="http://amberonrails.com/a-busy-semester"/>
   <updated>2011-05-18T12:22:04-07:00</updated>
   <id>http://amberonrails.com/a-busy-semester</id>
   <content type="html">&lt;p&gt;Abstract Syntax Trees. Target lists. Augassigns. Function types.&lt;/p&gt;

&lt;p&gt;This semester I took a compilers course with &lt;a href=&quot;http://www.cs.berkeley.edu/~hilfingr/&quot;&gt;Professor Hilfinger&lt;/a&gt;, who, despite his formidable reputation, quickly became my favorite professor at Berkeley. During the course of the semester, my group of four and I wrote a Python compiler in C++ basically from the ground up (in three parts, each around 200-300 hours each) - the reason I haven't blogged since February! I'm looking forward to learning more about compilers and now it's summer so I'll have plenty of time to blog again! (:&lt;/p&gt;

&lt;p&gt;On my todo list this summer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Fun side project: Javascript HTML5 Canvas Physics engine project (possibly to be ported later to WebGL) with my friend &lt;a href=&quot;http://thisisfranklin.com/&quot;&gt;Franklin Hu&lt;/a&gt;. We started a bit yesterday, it's pretty fun so far (until we get to the really really hard physics).&lt;/p&gt;

&lt;p&gt;Follow our &lt;a href=&quot;https://github.com/franklinhu/gohan&quot;&gt;GitHub&lt;/a&gt; if you're interested!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an undergraduate researcher in UC Berkeley's AMPLab, I'll be working on the CrowdDb project - check out their &lt;a href=&quot;http://www.cs.berkeley.edu/~franklin/Papers/CrowdDBSigmod11.pdf&quot;&gt;SIGMOD paper&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fun side project: Augmented Reality Android LaserTag/FPS game (probably too ambitious, but we'd love to give it a shot).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finish reading Javascript: The Good Parts, and Smashing Book 2 (that I got for Valentine's day!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fun side project: Some kind of Android app for my new Galaxy Tab that I got from Google IO 2011!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 
 
 
 
 <entry>
   <title>Rails exception_notification Setup</title>
   <link href="http://amberonrails.com/rails-exception_notification-setup"/>
   <updated>2011-01-31T22:39:38-08:00</updated>
   <id>http://amberonrails.com/rails-exception_notification-setup</id>
   <content type="html">&lt;p&gt;With any launched web app, it's a &lt;em&gt;very&lt;/em&gt; good idea to set up some kind of exception notification - in fact, it's on my &lt;a href=&quot;/my-launch-checklist/&quot;&gt;top 3 &quot;Launch Checklist&quot;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Exception Notification is a handy service that plugs into your existing app and sends you an email if (when) any exceptions are thrown in the course of people using your application. With Rails 3 and the &lt;a href=&quot;https://github.com/rails/exception_notification&quot;&gt;exception_notification&lt;/a&gt; gem, it's almost laughably easy to set up.&lt;/p&gt;

&lt;p&gt;First, add the following to your &lt;code&gt;Gemfile&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem &quot;exception_notification&quot;,
    :git =&amp;gt; &quot;git://github.com/rails/exception_notification.git&quot;,
    :require =&amp;gt; &quot;exception_notifier&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, insert this little snippet in &lt;code&gt;config/application.rb&lt;/code&gt;, in the config block:&lt;/p&gt;

&lt;pre&gt;
&lt;code class='ruby'&gt;# Exception Notification
config.middleware.use ExceptionNotifier, {
 :email_prefix =&gt; &quot;[Website Error] &quot;,
 :sender_address =&gt; '&quot;Notifier&quot; &lt;notifier@yourdomain.com&gt;',
 :exception_recipients =&gt; ['you@yourdomain.com']
}&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;That's it! Wasn't that easy?&lt;/p&gt;

&lt;h2&gt;Testing&lt;/h2&gt;

&lt;p&gt;If you're clicking through your application trying to get an exception thrown (but of course your application is written so well you frustratingly can't fire off an error), it might also be a good idea to create a method that tests your exception notification.&lt;/p&gt;

&lt;p&gt;Just add a method that raises an exception in your &lt;code&gt;app/controllers/application_controller.rb&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def test_exception
    raise 'Testing, 1 2 3.'
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(Don't forget to add a route to &lt;code&gt;config/routes.rb&lt;/code&gt; if you need it):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;match &quot;test_exception&quot; =&amp;gt; &quot;application#test_exception_notification&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, you can visit http://yourwebapp.com/test_exception_notification to trigger the exception notification manually and test if the emailing works.&lt;/p&gt;

&lt;p&gt;What if something goes wrong? All of the exception notification mailer's activity is logged, so go check out the relevant (development or production) log in log/&lt;/p&gt;

&lt;pre&gt;&lt;code class='bash'&gt;tail -f log/production.log&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;You also might want to turn off &lt;code&gt;ActionMailer&lt;/code&gt; from sending email notifications when you're testing things out (application-wise, not exception notification-wise) on your development server. Just stick this code in &lt;code&gt;config/environments/development.rb&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class='ruby'&gt;config.action_mailer.perform_deliveries = false&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Cool, now you've got your very own exception notification set up! Happy debugging! (:&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>JQuery Autocomplete with hidden data</title>
   <link href="http://amberonrails.com/jquery-autocomplete-with-hidden-data"/>
   <updated>2011-01-27T11:41:33-08:00</updated>
   <id>http://amberonrails.com/jquery-autocomplete-with-hidden-data</id>
   <content type="html">&lt;p&gt;This is a problem that I've encountered many times before when building Rails apps, but didn't know how to solve elegantly until one of my friends pointed out the solution was directly in the JQuery Autocomplete documentation (in my defense, it was at the &lt;em&gt;very&lt;/em&gt; bottom).&lt;/p&gt;

&lt;p&gt;Imagine you have an autocomplete field in a form that populates some Rails model, for example user's names. Naively, you would just pass an array of names to the JavaScript method like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[&quot;Amber Feng&quot;, &quot;John Doe&quot;, &quot;Harry Potter&quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and when the form is submitted, individually re-query the ID's for each of the names:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;name = params[:user]
user = User.find_by_name(name)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now this is super inefficient, if you're using some method to populate the autocomplete with User obejcts in the first place, why don't you just attach the &lt;code&gt;id&lt;/code&gt; to the autocomplete to be submitted instead of just the name?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def find_users
  render :json =&amp;gt; User.all.map {|c| c.full_name }
end

def find_users
  render :json =&amp;gt; User.all.map {|c| {:name =&amp;gt; c.full_name, :id =&amp;gt; c.id } }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, with your Javascript you can pass objects to the Autocomplete plugin (with full name AND &lt;code&gt;id&lt;/code&gt; information) instead of just name information:&lt;/p&gt;

&lt;pre&gt;
&lt;code class='javascript'&gt;// when /find_users only passes an array of names
$.ajax({
  url: '/find_users',
  success: function(data) {
      $(&quot;#user_query&quot;).autocomplete(data);
  }
});

// when /find_users returns an array of objects
$.ajax({
  url: '/find_users',
  success: function(data) {
      $(&quot;#user_query&quot;).autocomplete(data, {
          formatItem: function(item) {
              return item.name;
          }
      }).result(function(event, item) {
          $(&quot;#user_id&quot;).val(item.id);
      });
  }
});&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;You may have noticed in that last example I was doing a little something extra with the &lt;code&gt;.result()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;This function is a handler I've attached to the query field that is called whenever a user selects an option from the autocomplete. Here, I'm simply populating a hidden field I've added to the form called &lt;code&gt;#user_id&lt;/code&gt; so when the form is submitted, the id of the user is sent (instead of just the name).&lt;/p&gt;

&lt;pre&gt;
&lt;code class='ruby'&gt;
# much faster than User.find_by_name!
id = params[:id]
User.find(id)
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;If you feel like this way is too hacky or Javascript just isn't your thing, there are Rails plugins available like &lt;a href=&quot;http://agilewebdevelopment.com/plugins/model_auto_completer&quot;&gt;Model Auto Completer&lt;/a&gt;, but I haven't tried any third party plugins/widgets so I can't comment on how well they work or how easy they are to integrate into your application.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Sticky Footers</title>
   <link href="http://amberonrails.com/sticky-footers"/>
   <updated>2011-01-08T12:43:56-08:00</updated>
   <id>http://amberonrails.com/sticky-footers</id>
   <content type="html">&lt;p&gt;Sometimes, in websites that you design, you'll find that you want to implement some kind of footer (with copyright information, contact links, etc). The naive way to go about adding a footer to your design to just add a div with some fixed (or &lt;code&gt;auto&lt;/code&gt;) height at the bottom, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;div id=&quot;header&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div id=&quot;content&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div id=&quot;footer&quot;&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This should work, right? Well, this works as expected in certain cases when your content is longer than the height of your browser (figure on the left). In the case where you have very little (or no) content on one of your pages, the footer &quot;slides up&quot;, leaving an awkward looking space below your footer (figure on the right).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/sticky-footers/footers.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To force the footer to stick to the bottom, thus the name &quot;sticky footers&quot;, you need to wrap all other content in a container div, and give this &lt;code&gt;div&lt;/code&gt; a height of &lt;code&gt;100%&lt;/code&gt; and negative bottom margin of whatever the height of the footer is.&lt;/p&gt;

&lt;p&gt;This way, the footer is always forced to the bottom in cases where the content isn't long enough, and still works as before when the content is long enough. You'll notice that the negative margin causes the lower portions of your content to overlap with the footer; this can be fixed with some simple bottom padding or a &lt;code&gt;div&lt;/code&gt; fixed to the height of the footer.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;div id=&quot;container&quot;&amp;gt;
  &amp;lt;div id=&quot;header&quot;&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;div id=&quot;content&quot;&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;div id=&quot;push&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&quot;footer&quot;&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the css:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;html, body { height: 100%; margin: 0; }
#container {
  min-height: 100%;
  height: auto !important;
  height: 100%;
  margin: 0 auto [footer-height];
}
#footer, #push {
  height: [footer-height];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that's it! Simple, really!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credits&lt;/strong&gt;: I first learned how to do this from &lt;a href=&quot;http://ryanfait.com/sticky-footer/&quot;&gt;Ryan Fait&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>My Launch Checklist</title>
   <link href="http://amberonrails.com/my-launch-checklist"/>
   <updated>2010-12-24T20:20:51-08:00</updated>
   <id>http://amberonrails.com/my-launch-checklist</id>
   <content type="html">&lt;p&gt;Before you think about launching a site, make sure you have your bases covered! Here are the top three things I always have on my &quot;checklist&quot;.&lt;/p&gt;

&lt;h2&gt;Cross-browser Compatibility&lt;/h2&gt;

&lt;p&gt;This seems like a no-brainer, but I'm usually pretty bad with this because I like to test and debug all of my designs and applications in Chrome and ignore Firefox and (cringe) Internet Explorer (well, with the exception of IE9). I was brought back to my senses after I foolishly released the new version of my portfolio with a gaping Javascript bug that broke in all versions of Firefox. Ever since, I've been testing my websites in all browsers - even going to great lengths to install Internet Explorer on my Macbook Pro.&lt;/p&gt;

&lt;p&gt;There are a couple of websites I'd recommend for doing this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://browsershots.org&quot;&gt;BrowserShots&lt;/a&gt; is a website that takes a URL (mind that this doesn't work with localhost) and a list of browsers, returning a collection of screenshots taken of your site rendered in each of the different browsers. I've found this website pretty useful with making sure that my CSS styling and images are showing up correctly, but of course you can't actually play around with the website or test the Javascript. Did I mention it's free?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://browserlab.adobe.com&quot;&gt;Adobe BrowserLab&lt;/a&gt; is another super cool screenshot service with a really nice interface (what do you expect, it's Adobe) and handy features like viewing screenshots from what they call &quot;browser sets&quot; side by side and overlaying screenshots on top of each other. There are lots more features that I'm too lazy to put in this post, but you can view them &lt;a href=&quot;https://browserlab.adobe.com/en-us/features.html&quot;&gt;here&lt;/a&gt;! I don't think it's free, but I was able to sign up for a complimentary one year subscription.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you'd like to actually like to test out your application, you might consider using &lt;a href=&quot;http://crossbrowsertesting.com/&quot;&gt;CrossBrowserTesting&lt;/a&gt; (aptly named), which allows you to remote into their testing machines and actually try out your application in a bunch of different browsers and operating systems. I've never actually tried them before, but I've heard good things about the service. It's a little pricey, around $20 a month for 150 minutes of testing time a month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro Tip&lt;/strong&gt;: don't accidentally leave your session with them open on your browser.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Analytics&lt;/h2&gt;

&lt;p&gt;If you're like me, aka you take great pleasure in looking in all the page view statistics on all of your websites, you'll love having analytics installed. Make sure you install analytics BEFORE your launch, or you'll be sorry you missed out on the exciting graphs (I deeply regretted forgetting to install analytics on REOrganize before I launched).&lt;/p&gt;

&lt;p&gt;I highly, highly recommend &lt;a href=&quot;http://analytics.google.com&quot;&gt;Google Analytics&lt;/a&gt; (free, as with almost every Google product). It's really easy to set up - you just insert a Javascript snippet on the page(s) you want to be tracked, and let Google do the rest of work! There are too many cool features to name, and I won't pretend to be an analytics expert. If you're really into analytics, you should check out Avinash Kaushik, a guru over at Google who has pretty interesting analytics insights over at his &lt;a href=&quot;http://www.kaushik.net/avinash/&quot;&gt;blog&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Exception Notification&lt;/h2&gt;

&lt;p&gt;If you're launching a web application (vs. a static page), it's essential that you have exception notification. Standard exception notification services will email you if any exception is raised in your application along with a log/stack trace, and may even offer premium features. You can usually find plugins for whatever app framework you're using - for example, Rails has an &lt;a href=&quot;https://github.com/rails/exception_notification&quot;&gt;exception notification plugin&lt;/a&gt; you can install that
uses your server's mailer.&lt;/p&gt;

&lt;p&gt;(&lt;strong&gt;Update&lt;/strong&gt;: I've written a post on how to use exception_notification &lt;a href=&quot;http://www.amberonrails.com/2011/02/rails-exception_notification-setup/&quot;&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;If you don't want to worry about installing anything, you can go for one of the many web services out there. I've used &lt;a href=&quot;http://hoptoadapp.com/pages/home&quot;&gt;HopToad&lt;/a&gt; before, which offers a free &quot;Egg&quot;
plan for one application and comes packaged with a gem you can easily install in a Rails application. &lt;a href=&quot;http://www.getexceptional.com/&quot;&gt;Exceptional&lt;/a&gt; is quite good as well, but only for Rails (I basically only know about Rails services, if you haven't noticed already).&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;These are the top things that I'd recommend that most people never think to do before launching a website; maybe I'll mention some smaller (but still important!) things to check for in a future post.&lt;/p&gt;

&lt;p&gt;PS: Merry Christmas/Happy Holidays!&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Dynamic Stylesheet/Javascript Loading in Rails</title>
   <link href="http://amberonrails.com/dynamic-stylesheetjavascript-loading-in-rails"/>
   <updated>2010-12-22T21:42:00-08:00</updated>
   <id>http://amberonrails.com/dynamic-stylesheetjavascript-loading-in-rails</id>
   <content type="html">&lt;p&gt;Sometimes when I'm coding Rails applications, it's useful to split up CSS and Javascript files by controller/views to prevent loading a huge CSS or Javascript file (containing all of the styles and code for the entire application) on every single page of the application when you only really need it for a specific set of your pages.&lt;/p&gt;

&lt;p&gt;To load these dynamically (without having to include each named stylesheet by hand on each page), use the following code in the head of the main application layout:&lt;/p&gt;

&lt;pre&gt;
&lt;code class='ruby'&gt;&lt;% filename = controller.controller_name %&gt;
&lt;% if FileTest.exist?  RAILS_ROOT + &quot;/public/stylesheets/&quot; + filename %&gt;
  &lt;%= stylesheet_link_tag &quot;#{filename}&quot; %&gt;
  &lt;%= javascript_include_tag &quot;#{filename}&quot; %&gt;
&lt;% end %&gt;&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;This assumes that your stylesheets and javascript files are named according to the controller views in which they appear; if you'd just like to include javascript files of your choosing on certain views, put this in the head of the main application layout:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; &amp;lt;%= yield(:header) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And insert this code in your view with the appropriate CSS and javascript files you'd like to include:&lt;/p&gt;

&lt;pre&gt;
&lt;code class='ruby'&gt;&lt;% content_for :header do %&gt;
  &lt;%= javascript_include_tag &quot;file.js&quot; %&gt;
  &lt;%= stylesheet_link_tag &quot;file.css&quot; %&gt;
&lt;% end %&gt;&lt;/code&gt;
&lt;/pre&gt;

</content>
 </entry>
 
 
 
 <entry>
   <title>CS "Bucket List" 11/15</title>
   <link href="http://amberonrails.com/cs-bucket-list-1115"/>
   <updated>2010-11-15T23:09:41-08:00</updated>
   <id>http://amberonrails.com/cs-bucket-list-1115</id>
   <content type="html">&lt;p&gt;Wow, I haven't written in here in a loooong time (over 2 months!).&lt;/p&gt;

&lt;p&gt;School is getting crazy busy, between taking 3 upper div classes (which I love), TAing the &lt;a href=&quot;http://inst.eecs.berkeley.edu/~cs169/fa10/&quot;&gt;Software as a Service course&lt;/a&gt; here at Berkeley, co-facilitating a &lt;a href=&quot;http://decal.aw-industries.com/&quot;&gt;web design&lt;/a&gt; class, undergraduate-researching over at the &lt;a href=&quot;http://radlab.cs.berkeley.edu/&quot;&gt;RAD Lab&lt;/a&gt;, and hacking on some awesome personal projects (but that's a story for another post).&lt;/p&gt;

&lt;p&gt;Oh, and I'm flying up to Seattle next week for another Microsoft interview - exciting! After midterms have somewhat calmed down, I've decided to make a list of things that I'd like to hack on by the end of Christmas break.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Read more papers.&lt;/strong&gt; I've been inspired by my friend Sunil to read more research papers about everything.&lt;/p&gt;

&lt;p&gt;I'm feeling a little lame for not knowing too much about anything non-frontend-web-related. Currently on my list: Above the Clouds, Cassandra, BigTable, MapReduce, Spark, and Nexus (these last two and Above the Clouds are papers from the RAD Lab!).&lt;/p&gt;

&lt;p&gt;Any other suggestions?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hack on something in Python.&lt;/strong&gt; All of our projects in CS188 (Artificial Intelligence) are coded in Python, and I think I'm falling in love. I feel like I'm cheating on Ruby a little bit (this blog is even cleverly named after Ruby on Rails), but Python is pretty much the perfect combination of every programming language I've ever liked. Maybe I'll change my mind as I work with it more?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contribute to some open source project(s).&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Work on a personal project non-web-frontend-related.&lt;/strong&gt; I really need to get out of my comfort zone.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 
 
 
 
 <entry>
   <title>Fibonacci Times Three</title>
   <link href="http://amberonrails.com/fibonacci-times-three"/>
   <updated>2010-09-14T18:21:49-07:00</updated>
   <id>http://amberonrails.com/fibonacci-times-three</id>
   <content type="html">&lt;p&gt;On the first day of my Algorithms class here at school, we learned three ways to implement the well known &lt;a href=&quot;http://en.wikipedia.org/wiki/Fibonacci_number&quot;&gt;Fibonacci series&lt;/a&gt; generating algorithm.&lt;/p&gt;

&lt;h2&gt;Standard recursive&lt;/h2&gt;

&lt;p&gt;Everyone and their mom knows the recursive way to implement Fibonacci:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def fib(n)
  return 1 if n &amp;lt; 2
  fib(n-1) + fib(n-2)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is an extremely inefficient algorithm - the running time is exponential, growing almost as fast as the Fibonacci numbers themselves! For example, to find the 200th Fibonacci number, the algorithm takes 2&lt;sup&gt;138&lt;/sup&gt; steps! Obviously this is not feasible to compute even on a modern computer.&lt;/p&gt;

&lt;p&gt;What's the problem with this algorithm? We can see that we are repeatedly computing the value of each Fibonacci number (ex. for the 4th fibonacci number, we need to add the 3rd and 2nd, and to calculate the 3rd, we need to add the 2nd and 1st, and etc).&lt;/p&gt;

&lt;h2&gt;Memoization&lt;/h2&gt;

&lt;p&gt;One way we can avoid this double-counting is to remember what Fibonacci values were already computed in a hash table so we don't have to launch into another recursive call for a value we already have. We can also switch to implementing this with an iterative method:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def fib(n)
  fibHash = [1, 1]
  for i in 2..n
    fibHash.append(fibHash[i-1]+fibHash[i-2]
  return fibHash[n]
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now this is pretty clever, but who knew that there was an even MORE clever mathematical way to tackle this problem?&lt;/p&gt;

&lt;p&gt;Consider the following equations that represent the Fibonacci series:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/fibonacci-times-three/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can write the first two equations in matrix notation:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/fibonacci-times-three/2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The rest of the equations may be written in matrix notation, and if we substitute the value for [F1 F2] from the first equation, we notice a pattern:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/fibonacci-times-three/3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/fibonacci-times-three/4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now wait a minute - have we really figured out a way to make an O(1) algorithm for the Fibonacci series?&lt;/p&gt;

&lt;p&gt;Unfortunately, we need to take the multiplication and power operation runtimes into account because they are computationally more expensive than doing addition on large numbers. With the performance cost of using multiplication, we see that that runtime of this matrix implementation is actually O(n&lt;sup&gt;2&lt;/sup&gt;), which is sadly not faster than our O(n) algorithm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credit&lt;/strong&gt;: Material and screenshots taken from &lt;a href=&quot;http://www.cs.berkeley.edu/~vazirani/algorithms.html&quot;&gt;Algorithms by S. Dasgupta, C.H. Papadimitriou, and U.V. Vazirani&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Reversing Text with CSS</title>
   <link href="http://amberonrails.com/reversing-text-with-css"/>
   <updated>2010-09-02T18:55:19-07:00</updated>
   <id>http://amberonrails.com/reversing-text-with-css</id>
   <content type="html">&lt;p&gt;A couple of days ago, I saw one of the coolest CSS tricks I've seen in a really long time. You know how people usually put their email as &quot;amber DOT feng AT gmail DOT com&quot; or something to that effect in an attempt to foil bots from spamming their email? Instead, you can type your email in backwards in the code (which is what will show up in the DOM and what bots will see) like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;span class='reverse'&amp;gt;moc.liamg@gnef.rebma&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;..and apply CSS styling to reverse the text:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;.reverse{
    direction: rtl;
    unicode-bidi: bidi-override;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here's the snippet in action (try copy and pasting it somewhere!):&lt;/p&gt;

&lt;p&gt;&lt;span style='direction: rtl; unicode-bidi: bidi-override;'&gt;moc.liamg@gnef.rebma&lt;/span&gt;&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Google Code Jam: Alien Numbers</title>
   <link href="http://amberonrails.com/google-codejam-alien-numbers"/>
   <updated>2010-08-20T14:50:21-07:00</updated>
   <id>http://amberonrails.com/google-codejam-alien-numbers</id>
   <content type="html">&lt;p&gt;Lately I've been really into doing Google Codejam practice problems (aka I'm a nerd). I discovered I really need to brush up on my algorithms ):&lt;/p&gt;

&lt;h2&gt;The Problem&lt;/h2&gt;

&lt;p&gt;The decimal numeral system is composed of ten digits, which we represent as &quot;0123456789&quot; (the digits in a system are written from lowest to highest). Imagine you have discovered an alien numeral system composed of some number of digits, which may or may not be the same as those used in decimal.&lt;/p&gt;

&lt;p&gt;For example, if the alien numeral system were represented as &lt;code&gt;oF8&lt;/code&gt;, then the numbers one through ten would be &lt;code&gt;F, 8, Fo, FF, F8, 8o, 8F, 88, Foo, FoF&lt;/code&gt;. We would like to be able to work with numbers in arbitrary alien systems.&lt;/p&gt;

&lt;p&gt;More generally, we want to be able to convert an arbitrary number that's written in one alien system into a second alien system. &lt;a href=&quot;http://code.google.com/codejam/contest/dashboard?c=32003#&quot;&gt;Complete problem here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;My Solution (Ruby)&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;def hash_indexes(arr)
  hash = {}

  for i in 1..(arr.length - 1)
    hash[arr[i]] = i
  end
  return hash
end

def log(base, num)
  Math::log10(num)/Math::log10(base)
end

def to_decimal(source, num)
  num_arr = num.split(&quot;&quot;)
  hashed_source = hash_indexes(source.split(&quot;&quot;))
  dec = 0

  for i in 0..(num_arr.size - 1)
    hashed_no = hashed_source[num_arr[i]].to_i
    dec += hashed_no * (source.size ** (num_arr.size - 1 - i))
  end
  return dec
end

def to_target(target, decimal)
  final = &quot;&quot;
  target_arr = target.split(&quot;&quot;)

  i = log(target.size, decimal).to_i
  while i &amp;gt;= 0
    value = target.length ** i
    times = (decimal/value).to_i
    final &amp;lt;&amp;lt; target_arr[times]
    decimal %= value
    i -= 1
  end
  return final
end

def solve(line)
  arr = line.split(&quot; &quot;)
  to_target(arr[2], to_decimal(arr[1], arr[0]))
end

file = File.new(&quot;A-large-practice.in&quot;, &quot;r&quot;)
output = File.open(&quot;A-large-practice.out&quot;, &quot;w&quot;) do |f|
   num_lines = file.gets.to_i
   for counter in 1..num_lines
     solution = solve(file.gets)
     f.write(&quot;Case ##{counter}: #{solution}n&quot;)
     #puts &quot;Case ##{counter}: #{solution}&quot;
   end
end
file.close
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Time to solve:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;A-small-practice.in&lt;/code&gt; - 5.7ms&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;A-large-practice.in&lt;/code&gt; - 15.1ms&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 
 
 <entry>
   <title>Storing Arrays in a Database Field w/ Rails ActiveRecord</title>
   <link href="http://amberonrails.com/storing-arrays-in-a-database-field-w-rails-activerecord"/>
   <updated>2010-08-16T16:20:45-07:00</updated>
   <id>http://amberonrails.com/storing-arrays-in-a-database-field-w-rails-activerecord</id>
   <content type="html">&lt;p&gt;When I first started writing &lt;a href=&quot;http://expenses.amberfeng.com&quot;&gt;Expendite&lt;/a&gt;, an expense sharing web application targeted toward apartment-mates, I barely knew Rails. For each expense, I needed a way to record which users were involved as parties. Basically I needed a many-to-many association with a join table, though I didn't know it at the time.&lt;/p&gt;

&lt;p&gt;Embarrassingly, I chose the method of storing an array of user id's (the involved parties) in a &lt;code&gt;parties&lt;/code&gt; column in my database. Now I know better, but it still may be useful to know how to store arrays in a database that seemingly doesn't have any support for array objects.&lt;/p&gt;

&lt;p&gt;Luckily, ActiveRecord has this support built right in!&lt;/p&gt;

&lt;p&gt;First, the column in question should be changed to type &lt;code&gt;text&lt;/code&gt;. If you've already created and used your database, a simple database migration is in order. Next, serialize the column:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Expense &amp;lt; ActiveRecord::Base
    serialize :parties
    # other model code
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's literally all you need to do! Now, just save an array to the column like you would normally save a field value:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Expense.new(:parties =&amp;gt; [1, 2, 3])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And when you call the parties on an Expense again, it'll spit an array back at you. It's also worth noting that this technique may be used for hashes as well!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Storing arrays in databases is &lt;em&gt;most likely&lt;/em&gt; not what you want to do.&lt;/p&gt;

&lt;p&gt;There's probably a relationship/associations solutions (like my anecdote), or you can figure out another way to make it work with multiple columns.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>CSS Shorthand</title>
   <link href="http://amberonrails.com/css-shorthand"/>
   <updated>2010-08-10T14:25:20-07:00</updated>
   <id>http://amberonrails.com/css-shorthand</id>
   <content type="html">&lt;p&gt;For all of you CSS coders who are pretty lazy (myself included), you can use CSS shorthand to type out certain properties in one line instead of many many lines. Here's an example:&lt;/p&gt;

&lt;p&gt;Say you want to add a background image to your fancy new website using CSS. And it should not repeat. And the position should be on the top left. Oh, and you also want to add a background color because parts of your image are transparent.&lt;/p&gt;

&lt;p&gt;Instead of tediously typing this out:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;background-color: #ccc;
background-image: url('../images/background.png');
background-repeat: no-repeat;
background-position: top left;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can simply do this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;background: #ccc url('../images/background.png') no-repeat top left;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Not only does this save you from having carpal tunnel in the future, but it makes your CSS files smaller so they take less time to load as resources = less loading times for your website. It's a win-win for everyone!&lt;/p&gt;

&lt;h2&gt;Background&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;background:
     [background-color]
     [background-image]
     [background-repeat]
     [background-position];

background: #ccc url('background.png') no-repeat left top;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Be careful -- these need to be in the correct order and if you omit any, the browser will use the default values for each property which may not be what you were expecting.&lt;/p&gt;

&lt;h2&gt;Font&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;font:
     [font-style]
     [font-variant]
     [font-weight]
     [font-size]/[line-height]
     [font-family]

/* These two are equivalent */
font: normal normal bold 13px/11px Helvetica, serif;
font: bold 13px/11px Helvetica, serif;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Same deal as for backgrounds -- anything that is omitted gets applied the default property value. When in doubt, specify those values! There's another handy CSS shorthand guide &lt;a href=&quot;http://www.dustindiaz.com/css-shorthand/&quot;&gt;here&lt;/a&gt; that lists various default values for different shorthand properties as well.&lt;/p&gt;

&lt;p&gt;These next couple are pretty straight forward:&lt;/p&gt;

&lt;h2&gt;Margin/Padding&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;/* Remember this as clockwise from the top */
margin:
     [margin-top]
     [margin-right]
     [margin-bottom]
     [margin-left];

margin: 1px 2px 3px 4px;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OR&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;margin:
     [margin-top]
     [margin-right AND margin-left]
     [margin-bottom];

margin: 1px 2px 3px;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OR&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;margin:
     [margin-top AND margin-bottom]
     [margin-right AND margin-left];

margin: 1px 2px;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OR&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;margin: [margin for all sides];

margin: 1px;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The same goes for padding properties.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;padding: 1px 2px 3px 4px;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Border&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;border:
     [border-width]
     [border-color]
     [border-style];

border: 1px red solid;
&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>JQuery Draggable and Droppable</title>
   <link href="http://amberonrails.com/jquery-draggable-and-droppable"/>
   <updated>2010-08-03T12:56:15-07:00</updated>
   <id>http://amberonrails.com/jquery-draggable-and-droppable</id>
   <content type="html">&lt;p&gt;On a whim, I recently whipped together and launched &lt;a href=&quot;http://reorganize.amberfeng.com&quot;&gt;REOrganize&lt;/a&gt;, a small JavaScript application that lets users simulate arranging furniture around in a room via dragging and dropping.&lt;/p&gt;

&lt;p&gt;To build this quickly, I utilized &lt;a href=&quot;http://jqueryui.com/&quot;&gt;JQuery's fantastic UI library&lt;/a&gt; full of ready-made effects and widgets. To take advantage of these effects for yourself, go ahead and &lt;a href=&quot;http://jqueryui.com/download&quot;&gt;do&lt;/a&gt;&lt;a href=&quot;http://jqueryui.com/download&quot;&gt;wnload JQuery UI&lt;/a&gt; -- you can even create your own custom build to strip out libraries you don't need and save space.&lt;/p&gt;

&lt;h2&gt;Draggable&lt;/h2&gt;

&lt;p&gt;JQuery UI makes adding effects absolutely painless. All you need to do is use a JQuery selector (I've written a quick cheatsheet on JQuery selectors &lt;a href=&quot;http://www.amberonrails.com/2010/07/basic-css-jquery-selectors/&quot;&gt;back here&lt;/a&gt; if you need some refreshing) to select the elements you would like to be made draggable, and call the &lt;code&gt;.draggable()&lt;/code&gt; method.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$('.class-to-drag').draggable();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's the most basic implementation that will allow you the element to be made 'draggable'. Of course, you can add all sorts of extra options for more complex functionality:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;currRect.draggable({
  containment: 'parent',
  grid: [factor, factor],
  snap: true,
  snapMode: 'outer',
  stack: '.rect-margin'
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here's some code from REOrganize.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;containment&lt;/code&gt; property allows you to specify if the element should be contained (ie. should not allow dragging outside of some container) -- for example, in REOrganize, each desk/bed rectangle cannot be
dragged outside of the room container.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid&lt;/code&gt; allows you to specify a grid for the elements to snap-to, otherwise they can be dragged pixel by pixel.&lt;/p&gt;

&lt;p&gt;Similarly, &lt;code&gt;snap&lt;/code&gt; allows elements to snap-to other elements (handy for users to line things up easily). You can also attach event listeners/callbacks for drag &lt;code&gt;start&lt;/code&gt;, drag &lt;code&gt;stop&lt;/code&gt;, and during drags like I did here to reset icon positions during/after drags:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;currDoor.draggable({
  containment: 'parent',
  grid: [factor, factor],
  axis: 'x',
  drag: function() {
  resetInfoPosition($(this), wall);
  },
  stop: function() {
  resetInfoPosition($(this), wall);
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Be sure to check out more of these options and events on the &lt;a href=&quot;http://jqueryui.com/demos/draggable/&quot;&gt;Draggable API&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;Droppable&lt;/h2&gt;

&lt;p&gt;Last year I participated in the Zynga Hackathon at UC Berkeley, an 18 hour overnight coding competition (we won Honorable Mention!).&lt;/p&gt;

&lt;p&gt;One of the wow factors of our application was how we opened new content - a user would be able to select from a top menu of icons, drag and drop the icon into the open space, and a new window would blossom open.&lt;/p&gt;

&lt;p&gt;How did we achieve this? With the help of JQuery, of course. Almost exactly like Draggable, you use JQuery selectors and the method &lt;code&gt;.droppable()&lt;/code&gt; to assign droppable properties to an element:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$('.class-to-drop-on').droppable();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are some helpful options you can include in the method arguments, but the real power comes from the event callbacks. You can detect if a draggable element is dragged over, dragged out, or dropped on the droppable element:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$( &quot;.class-to-drop-on&quot; ).droppable({
   drop: function() {
     //do something interesting
   }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;More information can be found on the &lt;a href=&quot;http://jqueryui.com/demos/droppable/&quot;&gt;Droppable API&lt;/a&gt;. Go crazy!&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Setting Cookies with JQuery</title>
   <link href="http://amberonrails.com/setting-cookies-with-jquery"/>
   <updated>2010-07-23T15:11:23-07:00</updated>
   <id>http://amberonrails.com/setting-cookies-with-jquery</id>
   <content type="html">&lt;p&gt;I've never really used or dealt with browser cookies before because I felt like it was some complicated, advanced technique that required intricate knowledge of how browsers and sessions work.&lt;/p&gt;

&lt;p&gt;Today at work, I was given a task that involved setting, checking, and removing cookies for our web application, but I pleasantly found that it was an almost laughably easy task with my best friend JQuery.&lt;/p&gt;

&lt;h2&gt;Download the Plugin&lt;/h2&gt;

&lt;p&gt;First, you need to download the handy JQuery cookie plugin here: &lt;a href=&quot;http://plugins.jquery.com/project/cookie&quot;&gt;JQuery Cookie Plugin&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;Setting Cookies&lt;/h2&gt;

&lt;p&gt;To set cookies, all you need to do is type in the following in Javascript:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$.cookie(&quot;cookieName&quot;, &quot;cookieValue&quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This default cookie creation links this particular cookie to the session and it will be deleted at the end of some amount of time or if the user closes the browser, etc. If you want to have a cookie stay for a defined amount of time instead of linking it to the session, you can do something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$.cookie(&quot;cookieName&quot;, &quot;cookieValue&quot;, { expires: 1 }); // 1 day
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The expiration parameter's unit is in days so if you want to, say, set a cookie for only 30 minutes you'll have to do something a little tricker (I found this cool tip on Stack Overflow):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var date = new Date();
date.setTime(date.getTime() + (30 * 60 * 1000));
$.cookie(&quot;example&quot;, &quot;foo&quot;, { expires: date });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can also set the path and domain of the cookie (default is the current path and current domain):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$.cookie(&quot;cookie&quot;, &quot;1&quot;, { domain: &quot;domain.com&quot;, path: &quot;/&quot; });
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Reading Cookies&lt;/h2&gt;

&lt;p&gt;It's really easy to read back a cookie's value:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$.cookie(&quot;cookieName&quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Really, that's it!&lt;/p&gt;

&lt;h2&gt;Deleting Cookies&lt;/h2&gt;

&lt;p&gt;Finally, to delete a cookie just set it to &lt;code&gt;null&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$.cookie(&quot;cookieName&quot;, null);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that by default, this plugin won't let you delete a cookie from another domain so you'll have to explicitly specify the domain and path:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$.cookie(&quot;cookieName&quot;, null, { domain: &quot;domain.com&quot;, path:&quot;/&quot;);
&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Detecting Mobile Devices for Web Applications</title>
   <link href="http://amberonrails.com/detecting-mobile-devices-for-web-applications"/>
   <updated>2010-07-22T11:18:42-07:00</updated>
   <id>http://amberonrails.com/detecting-mobile-devices-for-web-applications</id>
   <content type="html">&lt;p&gt;As mobile devices become a bigger and bigger platform for viewing web pages, web application developers need to start paying attention to making their websites mobile-friendly. Have you ever visited a website from a smartphone that was obviously not mobile optimized?&lt;/p&gt;

&lt;p&gt;It's not a great experience, having to zoom in because the text is too small and scroll back and forth to read the information on the page. Some websites become all squished inside a mobile browser, obstructing important parts of the page and making it near impossible to use the application -- I had this experience recently with the Yelp on an Android phone.&lt;/p&gt;

&lt;p&gt;One simple way to combat this issue is to have multiple stylesheets, and switch them based on which device is being used to view the web page.&lt;/p&gt;

&lt;p&gt;For example, you can have a regular stylesheet named &lt;code&gt;style.css&lt;/code&gt;, a stylesheet optimized for iPhones named &lt;code&gt;iphone.css&lt;/code&gt;, and a stylesheet optimized for Android phones named &lt;code&gt;android.css&lt;/code&gt;. Then, with little effort, you can detect the client and apply the appropriate stylesheet so the user gets a nice, optimized web experience no matter what platform they are using.&lt;/p&gt;

&lt;p&gt;There are two relatively simple ways to do this: the Javascript way, and the CSS way.&lt;/p&gt;

&lt;h2&gt;The Javascript Way&lt;/h2&gt;

&lt;p&gt;You can use Javascript to check the current useragent variable for keywords like &lt;code&gt;iphone&lt;/code&gt;, &lt;code&gt;android&lt;/code&gt;, etc.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;uagent = navigator.userAgent.toLowerCase();
if(uagent.indexOf('iPhone') != -1){ // iPhone device
  document.write('&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;style/iphone.css&quot;&amp;gt;');
} else if(uagent.indexOf('Android') != -1){ // Android device
  document.write('&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;style/android.css&quot;&amp;gt;');
} else{ // Default to desktop version
  document.write('&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;style/style.css&quot;&amp;gt;');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wasn't that easy? Just stick that Javascript in the head tag and it should apply the correct stylesheet.&lt;/p&gt;

&lt;p&gt;Want more options? There are many different keywords to check for, here are a few examples:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'webkit' // client is using a webkit browser
'blackberry' // Blackberry device
'palm' // Palm OS device
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course, nothing in the world of cross-browser web application development
is perfect (I wish!). If Javascript is not supported on the browser (which may
be quite common in older mobile devices) or if the user turns off Javascript,
this method will not work at all. Also, you're depending solely on the
contents of the useragent variable, which may or may not be entirely accurate
100% of the time. But, there's another way!&lt;/p&gt;

&lt;h2&gt;The CSS Way&lt;/h2&gt;

&lt;p&gt;This method doesn't target specific devices, but instead uses their screen width as the independent variable. In your CSS link, you can add what are called &lt;a href=&quot;http://www.w3.org/TR/css3-mediaqueries/#media0&quot;&gt;CSS media queries&lt;/a&gt; (not supported by all browsers, unfortunately):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=”stylesheet” href=”style/style_320.css” type=”text/css” media=”screen and (min-device-width: 320px)”&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This way, you're not checking to see if a device is an iPhone or Android, but rather if it has a screen width of 320px or greater (or less, with &lt;code&gt;max-device-width&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Of course, this has its share of issues as well -- Dean Hamack over at Bushido Designs has written a fantastic article on &lt;a href=&quot;http://www.bushidodesigns.net/blog/mobile-device-detection-css-%20without-user-agent/&quot;&gt;Bulletproof Mobile Detection and Stylesheets without User Agent Detection or Server-side Scripting&lt;/a&gt; that addresses many of these.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>IDs vs. Classes?</title>
   <link href="http://amberonrails.com/ids-vs-classes"/>
   <updated>2010-07-21T16:53:18-07:00</updated>
   <id>http://amberonrails.com/ids-vs-classes</id>
   <content type="html">&lt;p&gt;IDs should generally be used when the element is unique, whereas classes should be used when there are a lot of similar elements that need the same styling. It would be perfectly legal to use IDs for every single element on a page (if they are unique, of course), but this would be terribly bad style for
two reasons.&lt;/p&gt;

&lt;p&gt;One, your ID names will start to get pretty long and complicated.&lt;/p&gt;

&lt;p&gt;Two, if there are certain elements that share the same styling, you'll have to duplicate code! Why not just label them as the same class, type out a class styling once and apply it to both of them?&lt;/p&gt;

&lt;p&gt;For example, you could have many articles labeled with separate, unique IDs.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;div id='article1'&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div id='article2'&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div id='article3'&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you want to apply some styling, your CSS would look unnecessarily long and not DRY (don't repeat yourself) at all!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#article1{
color: blue;
padding: 2em;
}
#article2{
color: blue;
padding: 2em;
}
#article3{
color: blue;
padding: 2em;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What if you just had some class &lt;code&gt;article&lt;/code&gt;, and applied a class styling to all of the articles?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;div class='article'&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div class='article'&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div class='article'&amp;gt;&amp;lt;/div&amp;gt;

.article{
color: blue;
padding: 2em;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There, that's better. And of course, if you need each article to have a specific ID for some javascript effect purposes, you can include both a class and an ID:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;div id='article1' class='article'&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div id='article2' class='article'&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div id='article3' class='article'&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 
 
 
 
 <entry>
   <title>CSS/Javascript Summer Reading List</title>
   <link href="http://amberonrails.com/cssjavascript-summer-reading-list"/>
   <updated>2010-07-15T11:20:05-07:00</updated>
   <id>http://amberonrails.com/cssjavascript-summer-reading-list</id>
   <content type="html">&lt;p&gt;Although I've been working with CSS and Javascript for quite some time, I still regard myself as a semi-beginner in terms of deeply understanding the foundations of these two languages.&lt;/p&gt;

&lt;p&gt;Therefore, I've taken it upon myself to learn as much as I can this summer (as long as I have a free &lt;a href=&quot;http://techbus.safaribooksonline.com/home&quot;&gt;Safari Books Online&lt;/a&gt; subscription from my internship, haha)! I did a brief Google search and found an almost unanimous agreement on which are the &quot;best&quot; books to read on these topics:&lt;/p&gt;

&lt;h2&gt;CSS&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.com/CSS-Definitive-Guide-Eric-Meyer/dp/0596527330&quot;&gt;CSS: The Definitive Guide&lt;/a&gt; by Eric Meyer&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.com/Pro-CSS-HTML-Design-Patterns/dp/1590598040&quot;&gt;Pro HTML/CSS Design Pattern&lt;/a&gt;s by Michael Bowers&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cssmastery.com/&quot;&gt;CSS Mastery&lt;/a&gt; by Andy Budd&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.com/Bulletproof-Web-Design-flexibility-protecting/dp/0321346939&quot;&gt;Bulletproof Web Design&lt;/a&gt; by Dan Cederholm&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Javascript&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X&quot;&gt;Pro Javascript Design Patterns&lt;/a&gt; by Ross Harmes and Dustin Diaz&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://oreilly.com/catalog/9780596517748&quot;&gt;Javascript: The Good Parts&lt;/a&gt; by Douglas Crockford&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.com/JavaScript-Definitive-Guide-David-Flanagan/dp/0596000480&quot;&gt;Javascript: The Definitive Guide&lt;/a&gt; by David Flanagan&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Have your own favorite CSS/Javascript books? Or even just fantastic general web design books, guides or tutorials? I'd love to hear about them!&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>SVN Ignoring Files/Directories</title>
   <link href="http://amberonrails.com/svn-ignoring-filesdirectories"/>
   <updated>2010-07-14T17:47:24-07:00</updated>
   <id>http://amberonrails.com/svn-ignoring-filesdirectories</id>
   <content type="html">&lt;p&gt;I've been trying to learn more about using command line SVN because I'm not terribly familiar with it, here is a super quick reference guide to the most common/useful SVN commands.&lt;/p&gt;

&lt;h3&gt;Checking out a repository (with optional username/password flags):&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;svn checkout [SVN REPO] [LOCAL DIR] --username [USER] --password [PASS]
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Copying a clean directory tree (no svn config files or folders):&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;svn export [PATH FROM] [PATH TO]
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Updating/Committing local copy:&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;svn update
svn commit -m &quot;[MESSAGE]&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Recently, I've also had to figure out how to ignore folders and files that I don't want committed to my repository (ex. local performance profiling data). I found the following useful commands in the &lt;a href=&quot;http://svnbook.red-bean.com/en/1.0/&quot;&gt;SVN Book&lt;/a&gt;:&lt;/p&gt;

&lt;h3&gt;Ignoring files/folders&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;svn propset svn:ignore bin .
svn propset svn:ignore hello.gif .
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Un-ignoring files/folders&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;svn propdel svn:ignore bin .
svn propdel svn:ignore hello.gif .
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Viewing ignored files/folders (and/or editing in an editor of your choice)&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;svn propget svn:ignore .
svn propedit svn:ignore . --editor-cmd vim
&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Automatically Capturing Website Screenshots</title>
   <link href="http://amberonrails.com/automatically-capturing-website-screenshots"/>
   <updated>2010-07-14T11:20:53-07:00</updated>
   <id>http://amberonrails.com/automatically-capturing-website-screenshots</id>
   <content type="html">&lt;p&gt;I've recently had inspiration for a new web application that fits my needs as a web designer (it's a secret for now), but it's not a standard CRUD web app so it requires a fair amount of new programming/customization that I'm struggling with.&lt;/p&gt;

&lt;p&gt;One thing the application requires that I'm not sure how to do is automatically capturing website screenshots. I'd like some sort of service where I feed in a URL and it spits out an screenshot of the website at that URL. Researching on Google, I've found many commercial types of software that can accomplish this but I'd like to use some type of open source plugin or web service.&lt;/p&gt;

&lt;p&gt;Furthermore, I'm planning on using this for my own web application so I'm not sure what the legal implications are. I'd like to write my own software for this, but I'm not quite sure how to start or what this would entail.&lt;/p&gt;

&lt;p&gt;So far, I've found some interesting links that are almost exactly what I'm looking for.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Binary Moon found a that Wordpress had their own service for doing &lt;a href=&quot;http://www.binarymoon.co.uk/2010/02/automated-take-screenshots-website-free/&quot;&gt;automated screenshots&lt;/a&gt; (ex. for theme galleries) with dynamic URLs, but I'm not sure Wordpress would be too happy if I spammed their servers with something non-Wordpress related.&lt;/li&gt;
&lt;li&gt;I've also found this website called &lt;a href=&quot;http://translate.google.com/translate?js=y&amp;amp;prev=_t&amp;amp;hl=en&amp;amp;ie=UTF-8&amp;amp;layout=1&amp;amp;eotf=1&amp;amp;u=http://thumbs.miwim.fr/install.php&amp;amp;sl=auto&amp;amp;tl=en&quot;&gt;Miwim&lt;/a&gt; (it's in French, but I've applied a Google Translate) that offers a similar service. The only downside is you have to link back to the service -- which I'm sure I'd do, anyway.&lt;/li&gt;
&lt;li&gt;Paul Hammond has also written a command line tool called &lt;a href=&quot;http://www.paulhammond.org/webkit2png/&quot;&gt;webkit2png&lt;/a&gt; that accomplishes the same thing, but I'm not sure how to run terminal commands from a web application.&lt;/li&gt;
&lt;li&gt;Here's another &lt;a href=&quot;http://www.fluther.com/17263/take-web-screenshots-for-a-website/&quot;&gt;forum&lt;/a&gt; that offers some alternatives, though some of the links are long dead.
I'm still searching for other services/ways to do it myself..if you have any
ideas I'd love to hear them!&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 
 
 <entry>
   <title>Basic (CSS) JQuery Selectors</title>
   <link href="http://amberonrails.com/basic-css-jquery-selectors"/>
   <updated>2010-07-13T11:49:16-07:00</updated>
   <id>http://amberonrails.com/basic-css-jquery-selectors</id>
   <content type="html">&lt;p&gt;I love JQuery. Oh so easy to use, excellent documentation, and an abundance of third-party plugins and widgets ready made for almost anything you could ever need. Of course, one of the most important parts of the library are JQuery's selectors, easy CSS-like syntax to select specific DOM elements to manipulate. Here is my personal JQuery selector reference sheet, drawn from the JQuery API, the web, and other JQuery books/reference sheets I've read. These selectors use near-CSS syntax, they should be relatively easy to understand.&lt;/p&gt;

&lt;h3&gt;Matches anything&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;$('*')
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Matches element with tagName (ex. a, span, etc)&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;$('tagName')

$('a') //matches all links
$('span') //matches all spans
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Matches element with id elementId (with optional tagName)&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;$('#elementId')
$('tagName#elementId')

$('div#header') //matches div element with id = header
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Matches element with class elementClass (with optional tagName)&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;$('.elementClass')
$('tagName.elementClass')

$('a.menu-link') //matches links with class = menu-link
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Matches CSS family/descendent patterns&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;$('A B') //B elements that are a descendant of A
$('A &amp;gt; B') //B elements that are direct children of A
$('A:has(B)') //A elements that have B as a descendant

$('#header a') //matches links inside element id=header
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Matching attributes&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;$('tagA[attr]') //tagA elements with an attr attribute
$('tagA[attr=value]') //tagA elements with attr is equal to value
$('tagA[attr^=startsWith]') //tagA elements with attr starts with startsWith
$('tagA[attr$=endsWith]') //tagA elements with attr ends with endsWith
$('tagA[attr*=containsThis]') //tagA elements with attr contains containsThis

$('img[alt]') //matches img elements with an alt attribute
//matches checkboxes whose names start with ch_ (ex. ch_1, ch_2,...) 
$('checkbox[name^=ch_]')
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's it for now, I'll post again soon with JQuery custom selectors (things like &lt;code&gt;:disabled&lt;/code&gt;, &lt;code&gt;:hidden&lt;/code&gt;, etc. that jQuery has added to its library to make things easier on developers) !&lt;/p&gt;
</content>
 </entry>
 
 
 
 
 
 <entry>
   <title>Color Scheme Designer</title>
   <link href="http://amberonrails.com/color-scheme-designer"/>
   <updated>2010-07-01T13:24:50-07:00</updated>
   <id>http://amberonrails.com/color-scheme-designer</id>
   <content type="html">&lt;p&gt;Recently, I re-stumbled upon a website that I absolutely love using for choosing or playing around with different color schemes, &lt;a href=&quot;http://colorschemedesigner.com/&quot;&gt;Color Scheme Designer&lt;/a&gt;. Visually stunning, this online tool includes a color wheel where users can intuitively drag around color selectors and a number of scheme types such as &quot;Mono&quot;, &quot;Complement&quot;, &quot;Tetrad&quot; that automatically show schemes for real-time color selections.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/color-scheme-designer/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Color Scheme Designer also provides random presets (in case you're lacking inspiration), advanced color customization, and handy hover-over hex codes for any desired colors.&lt;/p&gt;

&lt;p&gt;There is even a &quot;vision simulation&quot; to show you how the colors would look from the view of someone with visual impairments! And &quot;scheme previews&quot; to show you how your color scheme would look on a basic table-based layout! Amazing -- definitely a find worth sharing.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/color-scheme-designer/2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>JQTouch Animation Flicker Bug Fix</title>
   <link href="http://amberonrails.com/jqtouch-animation-flicker-bug-fix"/>
   <updated>2010-06-29T17:54:02-07:00</updated>
   <id>http://amberonrails.com/jqtouch-animation-flicker-bug-fix</id>
   <content type="html">&lt;p&gt;I've been working with the &lt;a href=&quot;http://www.jqtouch.com/&quot;&gt;jQTouch&lt;/a&gt; (a jQuery plugin for mobile development that imitates much of iPhone's UI and animation features) for quite some time now at work. It's pretty great, but I've been running into small little glitches like animation flickering for 'slide' animations that do not have fantastic documentation.&lt;/p&gt;

&lt;p&gt;There's no official patch/solution yet, but I've found a quick code hack that will fix some of the flickering problems. (For the iPhone/simulators I've tested on, at least). Taken from the &lt;a href=&quot;http://code.google.com/p/jqtouch/issues/detail?id=301&quot;&gt;Google Code issue tracker&lt;/a&gt;, just enter in this code snippet (the code marked //HACK) into the appropriate places in your &lt;code&gt;jQTouch.js&lt;/code&gt; file.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;...
scrollTo(0, 0);

// HACK
var backwardsSign = (backwards ? '-' : '')
var toStart = 'translateX(' + backwardsSign + window.innerWidth + 'px)';
fromPage.css( 'webkitTransform', toStart );
// /HACK

// Define callback to run after animation completes
var callback = function(event){
  // HACK
  fromPage.css( 'webkitTransform', '');
  // /HACK
  ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As one other person noted, you might also want to wrap these statements in &lt;code&gt;if&lt;/code&gt; statements so it doesn't affect other types of animations, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// HACK
if (animation.name === &quot;slide&quot;) {
  var backwardsSign = (backwards ? '-' : '')
  var toStart = 'translateX(' + backwardsSign + window.innerWidth + 'px)';
  fromPage.css('webkitTransform', toStart);
}
// /HACK

...

// HACK
if (animation.name === &quot;slide&quot;) {
  fromPage.css('webkitTransform', '');
}
// /HACK
&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Rails: Starting RSpec</title>
   <link href="http://amberonrails.com/rails-starting-rspec"/>
   <updated>2010-05-24T19:40:15-07:00</updated>
   <id>http://amberonrails.com/rails-starting-rspec</id>
   <content type="html">&lt;p&gt;This is basically the same deal as the Restful Authentication post below. I've used RSpec in the past (these quick start-up guides are not for beginners), I just need somewhere to quickly reference the beginning commands/code snippets to start my Rails applications.&lt;/p&gt;

&lt;p&gt;Here it goes!&lt;/p&gt;

&lt;h2&gt;Installing RSpec and RSpec for Rails&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;sudo gem install rspec
sudo gem install rspec-rails
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Generate RSpec subdirectory for tests&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;script/generate rspec
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Use RSpec scaffolding tool instead of regular scaffold! This way, you get the basic tests for each new controller/model/view you are creating.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;script/generate rspec_scaffold model_name ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you're looking to learn RSpec, &lt;a href=&quot;http://www.pragprog.com/titles/achbd/the-rspec-book&quot;&gt;The RSpec Book&lt;/a&gt; is an excellent reference.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Rails: Restful Authentication Quick Start</title>
   <link href="http://amberonrails.com/rails-restful-authentication-quick-start"/>
   <updated>2010-05-23T17:26:20-07:00</updated>
   <id>http://amberonrails.com/rails-restful-authentication-quick-start</id>
   <content type="html">&lt;p&gt;I almost always use Restful Authentication for my Rails applications. (For those of you who don't know what Restful Authentication is, it's a widely used Rails plugin for managing user authentication. In short, it's a plugin/gem that easily allows you to
have users logins/etc on your application without the hassle of coding and debugging the entire thing yourself. The source code can be found on technoweenie's GitHub &lt;a href=&quot;http://github.com/technoweenie/restful-authentication&quot;&gt;here&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;What's annoying to me is that I always forget how to set it up, and I hate going through loooong Restful Auth tutorial sites to find the specific commands/code snippets that I need. So here's what you need to set it up, short and sweet!&lt;/p&gt;

&lt;h2&gt;Installing the plugin&lt;/h2&gt;

&lt;p&gt;If this doesn't work, just download straight from the GitHub (link above) and include it in your &lt;code&gt;vendor/plugins&lt;/code&gt; folder&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ruby script/plugin install http://github.com/technoweenie/restful-authentication.git restful_authentication
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Generation&lt;/h2&gt;

&lt;p&gt;Generate all necessary files. Skip the &lt;code&gt;--include-activation&lt;/code&gt; part if you doesn't want users to have to &quot;activate&quot; their accounts via email.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ruby script/generate authenticated user sessions --include-activation
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;My generator fills in all the necessary routes automatically, but here they are just in case.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;map.activate '/activate/:activation_code', :controller =&amp;gt; 'users', :action =&amp;gt; 'activate'
map.signup '/signup', :controller =&amp;gt; 'users', :action =&amp;gt; 'new'
map.login '/login', :controller =&amp;gt; 'sessions', :action =&amp;gt; 'new'
map.logout '/logout', :controller =&amp;gt; 'sessions', :action =&amp;gt; 'destroy'
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;How to use&lt;/h2&gt;

&lt;p&gt;Include this line in your &lt;code&gt;ApplicationController&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;include AuthenticatedSystem
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Include this filter in any controller where you want users to log in before they see content. You can selectively filter certain methods with the &lt;code&gt;only&lt;/code&gt; keyword.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;before_filter :login_required
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Up to this point, the application should work for simple user authentication without activation by email (let me know if I'm missing anything!). I'll be writing more on activation as soon as I remember how I did it before.&lt;/p&gt;
</content>
 </entry>
 
 
 
</feed>
