Skip to content

Commit

Permalink
Updating posts.
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Bleigh committed Mar 29, 2010
1 parent 71e25c8 commit 6f5c7dd
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 0 deletions.
84 changes: 84 additions & 0 deletions _posts/2009-11-18-compiling-mustache-views-for-mustache-js.textile
@@ -0,0 +1,84 @@
---
layout: post
title: Compiling Mustache Views for Mustache.js
---

I've been investigating the usage of "Mustache":http://github.com/defunkt/mustache, the dead-simple templating language with the funny name, and one very enticing aspect of Mustache is that it's so simple it can easily be ported across languages. "Mustache.js":http://github.com/janl/mustache.js is a Javascript implementation of Mustache that works based on a simple JSON hash and a string template. Wouldn't it be awesome if we could use the same Mustache template on the server side and in Javscript without having to construct two sets of logic? Yes it would, and here's how.

h3. Creating a Serializable Mustache

Mustache works by calling methods from the template on the Mustache view object. There are no arguments, no filters, just plain old Ruby methods. Mustache.js works by reading values from a Javascript object or evaluating functions on
that object. So, if we want to use the same logic to power both our Ruby-built Mustaches and our Javascript-built Mustaches, all we need to do is convert that logic to JSON!

Now, you could write a @#to_json@ method for each of your Mustache views, but where's the DRYness in that? Instead let's create a Serializable Mustache that automatically catalogs the methods that need to be serialized to JSON:

{% highlight ruby %}
module Mustache::Serializable
def self.included(base)
base.extend ClassMethods
end

module ClassMethods
def serializable_methods
public_instance_methods(false)
end
end

def serializable_hash
hash = self.class.serializable_methods.inject({}) do |result, method|
# Symbolize the method to work better with the Mustache Context.
result[method.to_sym] = self.send(method)
result
end

hash.merge!(self.context)
end

def to_json
serializable_hash.to_json
end
end
{% endhighlight %}

That was easy enough! What we're doing is compiling a list of methods that we want to serialize by saying 'any public method that is declared in *this specific Mustache class* should be serialized', constructing a hash from those methods, merging in the Mustache's context, and providing a JSON representation of that hash.

h3. Rendering in Ruby

Now that you have a simple way to serialize to JSON, we need to actually be able to render this Mustache in it's server-side native form: Ruby. Here let's say we're working on a Sinatra application since it has probably the simplest setup. We're not going to use the built-in Sinatra support from Mustache because it will be clearer in the code if we don't. Here's the entire application (make sure you somehow include the serializable code from above):

{% highlight ruby %}
require 'rubygems'
require 'sinatra'
require 'mustache'

class Person < Mustache
include Mustache::Serializable

def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end

def formal_name
"#{@last_name}, #{@first_name}"
end

def initials
"#{@first_name[0..0]}.#{@last_name[0..0]}"
end

template = <<-HTML
<dl>
<dt>Formal Name:</dt> <dd>{{ formal_name }}</dd>
<dt>Initials:</dt> <dd>{{initials}}</dd>
</dl>
HTML
end

get '/person/:last_name/:first_name.:format' do
@mustache = Person.new(params[:first_name], params[:last_name])
@mustache.to_html
end
{% endhighlight %}

h3. Rendering in Javascript
51 changes: 51 additions & 0 deletions _posts/2010-02-12-redfinger-a-ruby-webfinger-gem.textile
@@ -0,0 +1,51 @@
---
layout: post
title: "Redfinger: A Ruby WebFinger Gem"
---

Just yesterday, Google "turned on webfinger for all GMail accounts":http://www.readwriteweb.com/archives/google_enables_webfinger_for_google_profiles_email_as_identity.php. Today, I'm releasing a RubyGem to help you use the new protocol!

h3. What's a WebFinger?

"WebFinger":http://code.google.com/p/webfinger/ is a new protocol for extracting public information about a person via their e-mail address. It is meant to complement systems such as OpenID as well as give a simple way to get basic information about a user without having to ask them for it.

E-Mail providers can implement WebFinger by creating a special URL (specifically at @/.well-known/host-meta@) that is an XRD XML document telling the requester a URL at which they can find out more about e-mail addresses on their domain. Google's, for example, is @http://www.google.com/s2/webfinger/?q={uri}@. When the WebFinger endpoint is requested with an e-mail address in place of @{uri}@, Google looks up information about that e-mail's public profile and provides it in a standardized XRD XML format.

So why WebFinger when OpenID already exists? Users are used to associating their e-mail address with their identity. It's natural since an e-mail address is (usually) for a specific person. By putting a protocol in place to find out more about an e-mail address without requiring additional input from the user, a host of options become available.

For instance, if I'm an application looking to authenticate using OpenID, I can ask a user for their e-mail address instead of their OpenID URL (something that will confuse mainstream users to no end). Or, if I want to automatcially fill in basic profile information, I can check to see if a parseable profile page is available in a format such as hCard.

h3. Enter Redfinger

Redfinger is a library built to easily consume the WebFinger protocol. Installing it is simple:

<pre>gem install redfinger</pre>

Using it is just as simple:

{% highlight ruby %}
require 'rubygems'
require 'redfinger'

finger = Redfinger.finger('youraccount@gmail.com')
finger.open_id.first.to_s # => "http://www.google.com/profiles/youraccount"
{% endhighlight %}

Redfinger will query the host of the e-mail domain specified, and, if the Webfinger protocol is supported, retrieve information about that e-mail address including such links as OpenID Provider, hCard URL, and more.

How can you use this today? Well, if you're an OpenID consumer you can use the above code to try to "intelligently find" an OpenID endpoint from an e-mail address. Of course, it will just about only work with Google at the moment (this is an alpha protocol, after all). Or, you could install the @mofo@ gem (a gem for parsing microformats for web pages) and do some neat things with microformats:

{% highlight ruby %}
require 'rubygems'
require 'mofo'
require 'redfinger'

finger = Redfinger.finger('account@gmai.com')
card = hCard.find(finger.hcard.first.to_s)
card.fn # => "That GMail user's full name"
card.title # => "The title he/she entered on Google Profile"
{% endhighlight%}

Here Redfinger determines a URL that will have hCard information about the e-mail address specified, and the Mofo gem goes out and fetches that address, parsing out the information.

WebFinger is still brand new (Google calls it "alpha") but it shows some promise for being a great way to make the open web more seamless for users. As always, "the Redfinger source code is available on GitHub":http://github.com/intridea/redfinger and "RDoc Documentation":http://rdoc.info/projects/intridea/redfinger is available. Check it out!
30 changes: 30 additions & 0 deletions _posts/2010-03-05-hashie-gains-a-chainable-hash.textile
@@ -0,0 +1,30 @@
---
layout: post
title: "Hashie Gains a Chainable Hash"
---

"Hashie":http://intridea.com/2009/11/12/hashie-the-hash-toolkit, Intridea's Hash Toolkit, is today with version 0.2.0 gaining a new member: the Clash.

A Clash is a "Chainable Lazy Hash" that allows you to construct a hash using method syntax. It is meant to be used in a similar way to the way that Rails 2.x's @named_scope@ or Arel's query building work. Let's start with an example:

{% highlight ruby %}
require 'hashie/clash'

c = Hashie::Clash.new
c.where(:abc => 'def').order(:created_at)

c == {:where => {:abc => 'def'}, :order => :created_at}
{% endhighlight%}

Pretty neat, right? But you can go beyond that. Clash also allows you to use bang method notation to create, dive into, and return from sub-hashes. Let me show you what I mean:

{% highlight ruby %}
c = Hashie::Clash.new
c.where!.abc('def').ghi(123)._end!.order(:created_at)

c == {:where => {:abc => 'def', :ghi => 123}, :order => :created_at}
{% endhighlight %}

By using a bang method, you automatically create a subhash that is then the subject of the chain, allowing you to create more keys on that subhash. Then, if you want to jump back up to the top-level hash, you simply call the @_end!@ method to return up one level in the stack (thanks to jQuery for that particular inspiration).

While Clash is a very simple tool, we hope that it could eventually make its way into some of the new ORMs that are cropping up around NoSQL systems (such as "MongoMapper":http://github.com/jnunemaker/mongomapper) to provide the same kind of effortless chaining that has made ActiveRecord so easy to work with.
@@ -0,0 +1,51 @@
---
layout: post
title: "Ruby Quick Tip: Regular Expressions in Case Statements"
---

Did you know that you can use regular expressions in @case@ statements in Ruby to check for a match? For instance, if I'm implementing some @method_missing@ functionality and I want to check for bang or question methods, I might be tempted to do something like this:

{% highlight ruby %}
def method_missing(name, *args)
name = name.to_s
if name.match(/!$/)
puts "Bang Method!"
elsif name.match(/\?$/)
puts "Query Method?"
else
super
end
end
{% endhighlight %}

But it'd be much cleaner if instead it looked like this:

{% highlight ruby %}
def method_missing(name, *args)
case name.to_s
when /!$/
puts "Bang Method!"
when /\?$/
puts "Query Method?"
else
super
end
end
{% endhighlight %}

This is great, but now what if we want to call out a method for bang and question methods? Thankfully Ruby has us covered there as well:

{% highlight ruby %}
def method_missing(name, *args)
case name.to_s
when /^(.*)!$/
bang_method($1)
when /^(.*)\?$/
question_method($1)
else
super
end
end
{% endhighlight%}

By using the @$1@ global variable we can access the last regular expression match performed by ruby. This is just one of those little details that makes working with Ruby such a joy.

0 comments on commit 6f5c7dd

Please sign in to comment.