Source: http://railstips.org/2009/4/20/how-to-add-simple-permissions-into-your-simple-app-also-thoughtbot-rules

Last week, in a few hours, I whipped together flightcontrolled.com for Flight Control, a super fun iPhone game. The site allows users to upload screenshots of their high scores. I thought I would provide a few details here as some may find it interesting.

It is a pretty straightforward and simple site, but it did need a few permissions. I wanted users to be able to update their own profile, scores and photos, but not anyone else’s. On top of that, I, as an admin, should be able to update anything on the site. I’m sure there is a better way, but this is what I did and it is working just fine.

Add admin to users

I added an admin boolean to the users table. You may or may not know this, but Active Record adds handy boolean methods for all your columns. For example, if the user model has an email column and an admin column, you can do the following.

user = User.new
user.email? # => false
user.email = 'foobar@foobar.com'
user.email? # => true

user.admin? # => false
user.admin = true
user.admin? # => true

Simple permissions module

Next up, I created a module called permissions, that looks something like this:

module Permissions
  def changeable_by?(other_user)
    return false if other_user.nil?
    user == other_user || other_user.admin?
  end
end

I put this in app/concerns/ and added that directory to the load path, but it will work just fine in lib/.

Mixin the permission module

Then in the user, score and photo models, I just include that permission module.

class Score < ActiveRecord::Base
  include Permissions
end

class Photo < ActiveRecord::Base
  include Permissions
end

class User < ActiveRecord::Base
  include Permissions
end

Add checks in controllers/views

Now, in the view I can check if a user has permission before showing the edit and delete links.

<%- if score.changeable_by?(current_user) -%>
  <li class="actions">
    <%= link_to 'Edit', edit_score_url(score) %>
    <%= link_to 'Delete', score, :method => :delete %>
  </li>
<%- end -%>

And in the controller, I can do the same.

class ScoresController < ApplicationController
  before_filter :authorize, :only => [:edit, :update, :destroy]

  private
    def authorize
      unless @score.changeable_by?(current_user)
        render :text => 'Unauthorized', :status => :unauthorized
      end
    end
end

Macro for model tests

I didn’t forget about testing either. I created a quick macro for shoulda like this (also uses factory girl and matchy):

class ActiveSupport::TestCase
  def self.should_have_permissions(factory)
    should "know who has permission to change it" do
      object     = Factory(factory)
      admin      = Factory(:admin)
      other_user = Factory(:user)
      object.changeable_by?(other_user).should be(false)
      object.changeable_by?(object.user).should be(true)
      object.changeable_by?(admin).should be(true)
      object.changeable_by?(nil).should be(false)
    end
  end
end

Which I can then call from my various model tests:

class ScoreTest < ActiveSupport::TestCase
  should_have_permissions :score
end

Looking at it now, I probably could just infer the score factory as I’m in the ScoreTest, but for whatever reason, I didn’t go that far.

A sprinkle of controller tests

I also did something like the following to test the controllers:

class ScoresControllerTest < ActionController::TestCase  
  context "A regular user" do
    setup do
      @user = Factory(:email_confirmed_user)
      sign_in_as @user
    end

    context "on GET to :edit" do
      context "for own score" do
        setup do
          @score = Factory(:score, :user => @user)
          get :edit, :id => @score.id
        end

        should_respond_with :success
      end

      context "for another user's score" do
        setup do
          @score = Factory(:score)
          get :edit, :id => @score.id
        end

        should_respond_with :unauthorized
      end
    end
  end

  context "An admin user" do
    setup do
      @admin = Factory(:admin)
      sign_in_as @admin
    end

    context "on GET to :edit" do
      context "for own score" do
        setup do
          @score = Factory(:score, :user => @admin)
          get :edit, :id => @score.id
        end

        should_respond_with :success
      end

      context "for another user's score" do
        setup do
          @score = Factory(:score)
          get :edit, :id => @score.id
        end

        should_respond_with :success
      end
    end
  end
end

Summary of Tools

I should call flightcontrolled, the thoughtbot project as I used several of their awesome tools. I used clearance for authentication, shoulda and factory girl for testing, and paperclip for file uploads. This was the first project that I used factory girl on and I really like it. Again, I didn’t get the fuss until I used it, and then I was like “Oooooh! Sweet!”.

One of the cool things about paperclip is you can pass straight up convert options to imagemagick. Flight Control is a game that is played horizontally, so I knew all screenshots would need to be rotated 270 degress. I just added the following convert options (along with strip) to the paperclip call:

has_attached_file :image, 
  :styles => {:thumb => '100>', :full => '480>'},
  :default_style => :full,
  :convert_options => {:all => '-rotate 270 -strip'}

Conclusion

You don’t need some fancy plugin or a lot of code to add some basic permissions into your application. A simple module can go a long way. Also, start using Thoughtbot’s projects. I’m really impressed with the developer tools they have created thus far.

Advertisements

Include vs Extend in Ruby

Tháng Năm 20, 2009

Source: http://railstips.org/2009/5/15/include-verse-extend-in-ruby

Now that we know the difference between an instance method and a class method, let’s cover the difference between include and extend in regards to modules. Include is for adding methods to an instance of a class and extend is for adding class methods. Let’s take a look at a small example.

module Foo
  def foo
    puts 'heyyyyoooo!'
  end
end

class Bar
  include Foo
end

Bar.new.foo # heyyyyoooo!
Bar.foo # NoMethodError: undefined method ‘foo’ for Bar:Class

class Baz
  extend Foo
end

Baz.foo # heyyyyoooo!
Baz.new.foo # NoMethodError: undefined method ‘foo’ for #<Baz:0x1e708>

As you can see, include makes the foo method available to an instance of a class and extend makes the foo method available to the class itself.

Include Example

If you want to see more examples of using include to share methods among models, you can read my article on how I added simple permissions to an app. The permissions module in that article is then included in a few models thus sharing the methods in it. That is all I’ll say here, so if you want to see more check out that article.

Extend Example

I’ve also got a simple example of using extend that I’ve plucked from the Twitter gem. Basically, Twitter supports two methods for authentication—httpauth and oauth. In order to share the maximum amount of code when using these two different authentication methods, I use a lot of delegation. Basically, the Twitter::Base class takes an instance of a “client”. A client is an instance of either Twitter::HTTPAuth or Twitter::OAuth.

Anytime a request is made from the Twitter::Base object, either get or post is called on the client. The Twitter::HTTPAuth client defines the get and post methods, but the Twitter::OAuth client does not. Twitter::OAuth is just a thin wrapper around the OAuth gem and the OAuth gem actually provides get and post methods on the access token, which automatically handles passing the OAuth information around with each request.

The implementation looks something like this (full file on github):

module Twitter
  class OAuth
    extend Forwardable
    def_delegators :access_token, :get, :post

    # a bunch of code removed for clarity
  end
end

Rather than define get and post, I simply delegate the get and post instance methods to the access token, which already has them defined. I do that by extending the Forwardable module onto the Twitter::OAuth class and then using the def_delegators class method that it provides. This may not be the most clear example, but it was the first that came to mind so I hope it is understandable.

A Common Idiom

Even though include is for adding instance methods, a common idiom you’ll see in Ruby is to use include to append both class and instance methods. The reason for this is that include has a self.included hook you can use to modify the class that is including a module and, to my knowledge, extend does not have a hook. It’s highly debatable, but often used so I figured I would mention it. Let’s look at an example.

module Foo
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def bar
      puts 'class method'
    end
  end

  def foo
    puts 'instance method'
  end
end

class Baz
  include Foo
end

Baz.bar # class method
Baz.new.foo # instance method
Baz.foo # NoMethodError: undefined method ‘foo’ for Baz:Class
Baz.new.bar # NoMethodError: undefined method ‘bar’ for #<Baz:0x1e3d4>

There are a ton of projects that use this idiom, including Rails, DataMapper, HTTParty, and HappyMapper. For example, when you use HTTParty, you do something like this.

class FetchyMcfetcherson
  include HTTParty
end

FetchyMcfetcherson.get('http://foobar.com')

When you add the include to your class, HTTParty appends class methods, such as get, post, put, delete, base_uri, default_options and format. I think this idiom is what causes a lot of confusion in the include verse extend understanding. Because you are using include it seems like the HTTParty methods would be added to an instance of the FetchyMcfetcherson class, but they are actually added to the class itself.

Conclusion

Hope this helps those struggling with include verse extend. Use include for instance methods and extend for class methods. Also, it is sometimes ok to use include to add both instance and class methods. Both are really handy and allow for a great amount of code reuse. They also allow you to avoid deep inheritance, and instead just modularize code and include it where needed, which is much more the ruby way.

Fixing The Web With Stylish

Tháng Năm 20, 2009

Source: http://blog.new-bamboo.co.uk/2009/2/27/fixing-the-web-with-stylish
Design becomes beautiful when there’s nothing left to take away. Google understands this; too many other web applications don’t.

Many apps grow new features simply to differentiate themselves from the competition, or to increase their target market by supporting multiple conflicting workflows. But every single thing I don’t need detracts from the usability of the things I do. In the past I’ve had to abandon apps that do more than I need, but not any more.

Now I can fix them.

Stylish is a Firefox plugin that lets you write your own css per-site, overriding the existing css. This means you can set display:none on everything unnecessary.

It’s a one-click install. You’ll also need Firebug to assist in identifying elements you want to block.

Once it’s installed, open firebug and point to the offending feature. Figure out a way to identify it with a CSS selector. In some cases this’ll be easy – it might have a classname like AnnoyingFeature. In others you’ll have to use CSS3 selectors. For example, you can do:

label[id*="requested_by_id"] {display:none}
view raw This Gist brought to you by GitHub.

This matches every Label element with an ‘id’ attribute containing ‘requested_by_id’. This is helpful if the site’s using ids like ‘story_34524_requested_by_id’.

But what about if you had this?

<div>
  <span class='annoying'>annoyance 1</span>
  <span>annoyance 2</span>
</div>
view raw This Gist brought to you by GitHub.

It’d be nice to block the parent div, thereby taking out ‘annoyance 2’, but you can’t; there’s no “parent selector” even in CSS3. Greasemonkey could fix this; Stylish can’t.

While you’re there, you can also fix other usability issues like textboxes being too small – it’s as simple as ‘textarea {height:300px}’.

Stylish has a live preview, and it’s only one click to turn off custom styles, so you can afford to be both aggressive and experimental.

You can share custom styles. I’d like to suggest that styles solely designed to remove distractions, rather than ‘re-skin’ sites, include ‘Simplify’ in the name to make them easy to find. Over the next few days I’ll be redesigning some of the web tools I use frequently to make them more of a joy to work with.

Source: http://ruby-toolbox.com/

Toolbox_red-256x256

Know your options!

Ruby developers can choose from a variety of tools to get their job done.

The Ruby Toolbox gives you an overview of these tools, sorted in categories and rated by the amount of watchers and forks in the corresponding source code repository on GitHub so you can find out easily what options you have and which are the most common ones in the Ruby community.

Want to know the best tools of choices? Check out http://ruby-toolbox.com/

Pacecar & automatic named scopes

Tháng Năm 18, 2009

Source: http://github.com/thoughtbot/pacecar/tree/master

Pacecar

Pacecar adds named_scope methods and other common functionality to ActiveRecord classes via database column introspection.

Pacecar automatically includes the Pacecar::Helpers module into all ActiveRecord::Base classes.

To get all Pacecar functionality, you need to “include Pacecar” in your class.

To get some subset (for example, only the state functionality), you can do something like “include Pacecar::State” to get only the module(s) you want.

Usage

Assuming a database schema…

  class CreateSchema < ActiveRecord::Migration
    def self.up
      create_table :users, :force => true do |t|
        t.boolean :admin, :default => false, :null => false
        t.datetime :approved_at
        t.datetime :rejected_at
        t.string :first_name
        t.string :last_name
        t.text :description
        t.timestamps
      end
      create_table :posts, :force => true do |t|
        t.string :owner_type
        t.integer :owner_id
        t.string :publication_state
        t.string :post_type
        t.timestamps
      end
      create_table :comments, :force => true do |t|
        t.integer :user_id
        t.text :description
        t.timestamps
      end
    end
  end

And some basic model declarations…

  class User < ActiveRecord::Base
    include Pacecar
    has_many :posts, :as => :owner
    has_many :comments
    has_many :articles
    has_ranking :comments
    has_recent_records :comments
    has_recent_records :articles, :comments
  end

  class Post < ActiveRecord::Base
    include Pacecar
    PUBLICATION_STATES = %w(Draft Submitted Rejected Accepted)
    TYPES = %w(Free Open Private Anonymous PostModern)
    belongs_to :owner, :polymorphic => true
    has_state :publication_state
    has_state :post_type, :with => TYPES
    has_polymorph :owner
  end

  class Comment < ActiveRecord::Base
    include Pacecar
    belongs_to :user
  end

  class Article < ActiveRecord::Base
    belongs_to :user
  end

All columns

Records where approved_at is not null, or where it is null…

  User.approved_at_present
  User.approved_at_missing

Records where first_name is not null, or where it is null…

  User.first_name_present
  User.first_name_missing

Records ordered by first_name (default to ‘asc’, can specify to override)…

  User.by_first_name
  User.by_first_name(:asc)
  User.by_first_name(:desc)

Records where an attribute matches a search term (column LIKE “%term%”)…

  User.first_name_matches('John')

Records where an attribute starts or ends with a search term…

  User.first_name_starts_with('A')
  User.first_name_ends_with('a')

Records where any non-state text or string column matches term…

  User.search_for('test')

Records where any of a list of columns match the term…

  User.search_for 'test', :on => [:first_name, :last_name]

Records where all of a list of columns match the term…

  User.search_for 'test', :on => [:first_name, :last_name], :require => :all

Boolean columns

Records that are all admins or non-admins…

  User.admin
  User.not_admin

The “balance” (count of true minus false for column in question)…

  User.admin_balance

Datetime columns

Records approved before or after certain times…

  User.approved_at_before(5.days.ago)
  User.approved_at_after(4.weeks.ago)

Records with approved_at in the past or future…

  User.approved_at_in_past
  User.approved_at_in_future

Records with approved_at inside or outside of two times…

  User.approved_at_inside(10.days.ago, 1.day.ago)
  User.approved_at_outside(2.days.ago, 1.day.ago)

Records with certain year, month or day…

  User.approved_at_in_year(2000)
  User.approved_at_in_month(01)
  User.approved_at_in_day(01)

Records with a duration (time delta between two columns) of, over or under a certain number of days…

  User.with_duration_of(14, :approved_at, :rejected_at)
  User.with_duration_over(14, :approved_at, :rejected_at)
  User.with_duration_under(14, :approved_at, :rejected_at)

Polymorphic relationships

Records which have an owner_type of User…

  Post.for_owner_type(User)

Associations

Records with the most and least associated records…

  User.maximum_comments
  User.minimum_comments

Records with associated records since a certain time…

  User.recent_comments_since(2.days.ago)
  User.recent_comments_and_posts_since(3.days.ago)
  User.recent_comments_or_posts_since(4.days.ago)

State columns

Records which are in a particular state, or not in a state…

  Post.publication_state_draft
  Post.post_type_not_open

Query methods on instances to check state…

  Post.first.publication_state_draft?
  Post.last.post_type_not_open?

Limits

First x records…

  User.limited(10)

Named scopes

Because these are all named_scope, you can combine them.

To get all users that have a first_name set, who are admins and approved more than 2 weeks ago, ordered by their first name…

  User.first_name_present.admin.approved_at_before(2.weeks.ago).by_first_name

To get the top 10 commenters…

  User.maximim_comments.limited(10)

Rails & named_scope

Tháng Năm 18, 2009

Source: http://mattpayne.ca/blog/post/named-scope

Lately everyone has been going mad over a relatively new addition to rails: named_scope. Up until now, I hadn’t had the chance to try it out. I always just assumed that it was more syntactic fluff that seems to accumulate. Wow, was I wrong! It’s an unbelievably cool and useful idea. Here’s a really simple example. Say I have 2 models: Country and Region. They are as you would expect. A Region belongs to a Country and a Country has many Regions, etc. I use them pretty much for dropdown lists and things like that. Here’s some code:

  1. class Region < ActiveRecord::Base
  2. belongs_to :country
  3. end
  4. class Country < ActiveRecord::Base
  5. has_many :regions
  6. end

Prior to named_scope, if you wanted to get all Regions in alphabetical order (as an example), you’d have to do something like:

  1. class Region < ActiveRecord::Base
  2. #other code
  3. def self.ordered
  4. find(:all, :order => “name ASC”)
  5. end
  6. end

Which was ok, but this is nicer:

  1. class Region < ActiveRecord::Base
  2. named_scope :ordered, :order => “name ASC”
  3. #other code
  4. end

This creates a method on the Region class called ordered that can simply be called.

OK, so that’s cool and all, but really not that big a deal, right? Well, no – until you consider that you can chain calls to named_scope, thus adding more and more constraints. For example:

  1. class Region < ActiveRecord::Base
  2. belongs_to :country
  3. named_scope :ordered, :order => “name ASC”
  4. named_scope :by_country, lambda { |c| { :conditions => [“country_id = ?”, c.id] } }
  5. named_scope :containing, lambda { |s| { :conditions => [“name like ?”, “%#{s}%”] } }
  6. end
  7. class Runner
  8. c = Country.find_by_name(“Canada”)
  9. regions = Region.by_country(c).containing(“A”).ordered
  10. puts “Provinces in Canada containing the letter A in ascending order: #{regions.inspect}”
  11. end

This generates SQL that looks like this:

SELECT * FROM `regions` WHERE ((name like ‘%A%’) AND (country_id = 1)) ORDER BY name ASC

Another reason that I like name_scope is that because models such as these are frequently eused in dropdowns, etc, you can use named scope to return a very lightweight version of the class, while excluding attributes that are unnecessary for a simple dropdown. For example:

  1. class Region < ActiveRecord::Base
  2. belongs_to :country
  3. named_scope :ordered, :order => “name ASC”
  4. named_scope :by_country, lambda { |c| { :conditions => [“country_id = ?”, c.id] } }
  5. named_scope :containing, lambda { |s| { :conditions => [“name like ?”, “%#{s}%”] } }
  6. named_scope :simple, :select => “id, name”
  7. end

This allows me to only bring back the attributes that I need. And again, it could be chained with other named scopes

I think that this is a very powerful concept that allows developers to write more DRY and readable code.

Source: http://www.rubyinside.com/19-rails-tricks-most-rails-coders-dont-know-131.html

When looking at my own Rails code and that of the community as a whole, I often see places where certain Rails techniques could have been used, but weren’t. As much for my own memory as yours, I thought I’d list down some Rails tricks and tips that can make your application or code more efficient:

Benchmark logic in your controller actions – It’s really easy. Use the benchmark class method available on all your models like this:

User.benchmark("adding and deleting 1000 users") do
	1000.times do
		User.create(:name => 'something')
		x = User.find_by_name('something')
		x.destroy
	end
end

Of course, your code would be a lot better ;-) The regular SQL logs are not shown when within the benchmark sections. Only the benchmark results are shown.

Nested-Set

acts_as_nested_set
– Almost everyone is familiar with acts_as_tree, but acts_as_nested_set snuck into Rails quietly. It’s much like acts_as_tree, but with the added benefit that you can select all of the children (and their own descendants) of a node with a single query. A list of the instance methods is available.

Easier collections with to_proc – Sick of writing things like post.collect { |p| p.title } or post.select { |p| p.activated? }.collect{ |p| p.title} ? A little Ruby hackery that allows you to convert symbols into proc references makes it easy. You can write post.collect(&:title) or post.select(&:activated?).collect(&:title) instead! Learn a lot more about this.

Convert arrays to sentences in views – If you were collecting a bunch of names to be shown in a view, you might end up with an array like [‘Peter’, ‘Fred’, ‘Chris’], and joining these with commas and inserting ‘and’ before the final one is a common pain. Not so, if you use the array method to_sentence as provided in Rails. names.to_sentence would return Peter, Fred, and Chris.

Send files back to the user – Usually, static files can be retrieved by using the direct URL and circumventing your Rails application. In some situations, however, it can be useful to hide the true location of files, particularly if you’re sending something of value (e-books, for example). It may be essential to only send files to logged in users too. send_file makes it possible. It sends files in 4096 byte chunks, so even large files can be sent without slowing the system down.

Iterating through page elements with RJS – Changing page elements with RJS is easy, but what if you don’t know exactly which elements you want to change, and would instead prefer to address them with CSS queries? You can with RJS’s select method. For example: page.select(‘#items li’).each { |item| item.hide } . Powerful stuff!

Check for existence – When doing a Model.find(id), an exception can be returned if the item with an id of ‘id’ doesn’t exist. If you want to avoid this, use Model.exists?(id) first to get a true or false for whether that item exists or not.

Number helpers for common number tasks – All of these number helpers aren’t commonly used but provide great shortcuts: number_to_currency(1234567.948) # => $1,234,567.95 or human_size(1234567890) # => 1.1GB or number_with_delimiter(999999999) # => 999,999,999. There are others.

Testing different route configurations easilywith_routing is a test helper that allows you to temporarily override the default ‘routes’ in routes.rb for test purposes. Demonstration:

with_routing do |set|
  set.draw { set.connect ':controller/:id/:action' }
  assert_equal(
     ['/content/10/show', {}],
     set.generate(:controller => 'content', :id => 10, :action => 'show')
  )
end

You can learn a little more here.

Get lots of info about requests – Checking request.post? and request.xhr? are popular ways to look for POST and AJAX requests, but some of the other request methods are lesser used. For example: request.subdomains can return an array of subdomains that you could use as part of your authentication scheme, request.request_uri returns the full local request URL, request.host returns the full hostname, request.method returns the HTTP method as a lowercase symbol, and request.ssl? returns true if it’s an HTTPS / SSL request.

Improving session performance even more than with ActiveRecord – By default, Rails stores sessions on the local file system. Many users change this to using ActiveRecordStore to store sessions in the database. An even faster alternative is to use Memcached to store sessions, but that takes a lot to set up (and isn’t available unless you run your own servers, etc). But you can get faster than ActiveRecordStore by using Stefan Kaes’ SQLSessionStore. It circumvents the inefficiencies of ActiveRecordStore using his own direct SQL technique to store sessions.

Caching unchanging data at application startup – If you have data that doesn’t change between application restarts, cache it in a constant somewhere. For example, you might have a YAML or XML file in /config that stores application configuration data, and you could load it into a constant in environment.rb, making lookups quick and easy application-wide.

Check your views are rendering valid HTML / XHTML – It’s not for everyone, but if your output validates as correct HTML / XHTML, it’s a sign your views are going to render properly. Scott Raymond has developed a assert_valid_markup test helper that you can use from your functional tests.

Cleaner HTML output testing – Combine why’s Hpricot HTML parser and a special test extension, and you can have powerful tests like so: assert_equal “My title”, tag(‘title’) or assert element(‘body’).should_contain(‘something’). This might be ideal for developing tests to test user built templates. In any case, it’s nicer than assert_tag!

Run long-running tasks separately in the backgroundBackgrounDRb is a small framework, by Ezra Zygmuntowicz, that runs as a daemon in the background that can accept tasks your Rails application sends to it, and whose execution is totally separate to your Rails app. It’s extremely powerful, and useful for many tasks such as sending hundreds of e-mails, fetching URLs, and other things you don’t want to slow down the request times for your main app. One great demo is to develop a task that increments a variable by 1 and sleeps for 1 second. You can then make a Rails method that queries the variable, and see the distinct separation. Learn more.

Make ids in URLs more user friendly – Override the to_param method on your model and return something like “#{id}-#{title.gsub(/[^a-z0-9]+/i, ‘-‘)}” to get URLs like so: http://yoursite.com/posts/show/123-post-title-goes-here .. Much nicer for users, and you don’t need to change anything with Post.find(params[:id]) as the non numeric characters will be stripped automagically! Get a full explanation here.

Separate out slices of functionality into Engines – Everyone’s heard of Rails’ plugins, but pitifully few are using Rails Engines! Rails Engines are like plugins on steroids. They can contain their own models, controllers, and views, and integrate with any applications you run them under. This allows you to split out common fragments of functionality (login, user management, content management, etc.) into separate ‘engines’ to use in your different projects within minutes. No more writing dull login code! Rails Engines is a big deal, but it should be a far bigger deal.

Calculations – Do you want to get maximums, minimums, averages, or sums for data in your tables? ActiveRecord’s Calculations make these all possible. Person.average(‘age’), Person.maximum(:age, :group => ‘last_name’), and Order.sum(‘total’) all become a reality. Most can be customized pretty deeply with extra options, so go read about them if they’re not already part of your code.

XML or YAML output of your data – It’s not necessarily to create a Builder .rxml template for all XML output. ActiveRecord has a to_xml method that will output the object or result set in XML format. It works with simple objects, to complete tables (like User.find(:all).to_xml). Using includes works too, as with Post.find(:all, :include => [:comments]).to_xml. YAML is also supported, by using to_yaml instead.

Source: http://pablotron.org/software/wirble/

Wirble is a set of enhancements for Irb. Wirble enables several items mentioned on the RubyGarden “Irb Tips and Tricks” page, including tab-completion, history, and a built-in ri command, as well as colorized results and a couple other goodies. The idea, of course, is to fill Irb with useful features without turning your ~/.irbrc file into swiss cheese. Using Wirble is simple, too. Here’s what a standard Wirble-enabled ~/.irbrc looks like:

# load libraries
require 'rubygems'
require 'wirble'

# start wirble (with color)
Wirble.init
Wirble.colorize

Don’t like the defaults? Wirble is configurable. For documentation on enabling specific features or tweaking the color settings. take a look at the excessively-verbose Wirble README. Finally, here’s a screenshot of Wirble-enabled Irb:

Wirble Screenshot
Obligatory Wirble Screenshot

Latest:
Download Wirble 0.1.2 Tarball (Signature)
Download Wirble 0.1.2 Gem (Signature)
Read the Wirble 0.1.2 README
Read the ChangeLog

Source: http://www.pauldix.net/2009/05/breath-fire-over-http-in-ruby-with-typhoeus.html

Typhoeus is a mythical greek god with 100 fire breathing serpent heads. He’s also the father of the more well known Hydra. Like the fearsome beast, Typhoeus is a fearsome Ruby library that enables parallel HTTP requests while cleanly encapsulating handling logic. Specifically, it uses libcurl and libcurl-multi to run HTTP really fast. Further, it’s designed with the focus of creating client libraries that work with web services. These could be external services like Twitter or systems like CouchDB and SimpleDB or custom web services that you write yourself.

The libcurl interface is contained within the library. Rather than trying to get Curb to do what I wanted, I decided to start with a clean slate and write the c bindings myself. Other than the libcurl interface, it has a nice DSL for creating classes and client libraries for web services.

The inspiration for the library came from an interview with Amazon CTO Werner Vogels. In the interview he states that when a user visits the Amazon.com home page it calls out to up to 100 different services to construct the single page before returning it to the user. I like Amazon’s approach of a services architecture, specially AWS, and wondered if I could do the same thing in Ruby. Typhoeus is the result of that effort.

I set up a benchmark to test how the parallel performance works vs Ruby’s built in NET::HTTP. The setup was a local evented HTTP server that would take a request, sleep for 500 milliseconds and then issued a blank response. I set up the client to call this 20 times. Here are the results:

 net::http 0.030000 0.010000 0.040000 ( 10.054327)
 typhoeus 0.020000 0.070000 0.090000 ( 0.508817)

We can see from this that NET::HTTP performs as expected, taking 10 seconds to run 20 500ms requests. Typhoeus only takes 500ms (the time of the response that took the longest.)

Hopefully I’ve whetted your appetite. Before I get to the code examples and the API, I’d like to put in a plug for my employer kgb. They were nice enough to let me release this library as open source. We’re also hiring for good front end rails developers, designers, and anyone with experience in search, information retrieval, and machine learning. Please drop me a line if you dominate code and if you’re interested in joining an awesome team.

Finally, on the the codez. Here are some usage examples and notes from the readme (gist for easier reading).

# here's an example for twitter search
# Including Typhoeus adds http methods like get, put, post, and delete.
# What's more interesting though is the stuff to build up what I call
# remote_methods.
class Twitter
 include Typhoeus
 remote_defaults :on_success => lambda {|response| JSON.parse(response.body)},
 :on_failure => lambda {|response| puts "error code: #{response.code}"},
 :base_uri => "http://search.twitter.com"

 define_remote_method :search, :path => '/search.json'
 define_remote_method :trends, :path => '/trends/:time_frame.json'
end

tweets = Twitter.search(:params => {:q => "railsconf"})

# if you look at the path argument for the :trends method, it has :time_frame.
# this tells it to add in a parameter called :time_frame that gets interpolated
# and inserted.
trends = Twitter.trends(:time_frame => :current)

# and then the calls don't actually happen until the first time you
# call a method on one of the objects returned from the remote_method
puts tweets.keys # it's a hash from parsed JSON

# you can also do things like override any of the default parameters
Twitter.search(:params => {:q => "hi"}, :on_success => lambda {|response| puts response.body})

# on_success and on_failure lambdas take a response object. 
# It has four accesssors: code, body, headers, and time

# here's and example of memoization
twitter_searches = []
10.times do
 twitter_searches << Twitter.search(:params => {:q => "railsconf"})
end

# this next part will actually make the call. However, it only makes one
# http request and parses the response once. The rest are memoized.
twitter_searches.each {|s| puts s.keys}

# you can also have it cache responses and do gets automatically
# here we define a remote method that caches the responses for 60 seconds
klass = Class.new do
 include Typhoeus

 define_remote_method :foo, :base_uri => "http://localhost:3001", :cache_responses => 60
end

klass.cache = some_memcached_instance_or_whatever
response = klass.foo 
puts response.body # makes the request

second_response = klass.foo
puts response.body # pulls from the cache without making a request

# you can also pass timeouts on the define_remote_method or as a parameter
# Note that timeouts are in milliseconds.
Twitter.trends(:time_frame => :current, :timeout => 2000)

# you also get the normal get, put, post, and delete methods
class Remote
 include Typhoeus
end

Remote.get("http://www.pauldix.net")
Remote.put("http://", :body => "this is a request body")
Remote.post("http://localhost:3001/posts.xml", 
 {:params => {:post => {:author => "paul", :title => "a title", :body => "a body"}}})
Remote.delete("http://localhost:3001/posts/1")

Important Update:I should have mentioned that some bits of C were pulled from Todd Fisher’s update to curb for the multi interface. The easy code is completely different and some of the C stuff in Multi has changed. However, a good chunk of the multi code comes straight from there. Thanks Todd. Sorry for not mentioning it earlier.

Source: http://www.thoughtbot.com/projects/shoulda/

Making Tests Easy on the Fingers and Eyes

The Shoulda gem makes it easy to write elegant, understandable, and maintainable Ruby tests. Shoulda consists of test macros, assertions, and helpers added on to the Test::Unit framework. It’s fully compatible with your existing tests, and requires no retooling to use.

  • Context & Should blocks – context and should provide RSpec-like test blocks for Test::Unit suites. In addition, you get nested contexts and a much more readable syntax.
  • Macros – Generate many ActionController and ActiveRecord tests with helpful error messages. They get you started quickly, and can help you ensure that your application is conforming to best practice.
  • Assertions – Many common Rails testing idioms have been distilled into a set of useful assertions.

The Shoulda gem can be used for non-Rails projects


Installation


sudo gem install thoughtbot-shoulda --source=http://gems.github.com

Usage

Context Helpers

Stop killing your fingers with all of those underscores… Name your tests with plain sentences!


class UserTest < Test::Unit 
  context "A User instance" do
    setup do
      @user = User.find(:first)
    end

    should "return its full name" do
      assert_equal 'John Doe', @user.full_name
    end

    context "with a profile" do
      setup do
        @user.profile = Profile.find(:first)
      end

      should "return true when sent #has_profile?" do
        assert @user.has_profile?
      end
    end
  end
end

Produces the following test methods:

"test: A User instance should return its full name." 
"test: A User instance with a profile should return true when sent #has_profile?."

So readable!

ActiveRecord Tests

Quick macro tests for your ActiveRecord associations and validations:


class PostTest < Test::Unit::TestCase
  should_belong_to :user
  should_have_many :tags, :through => :taggings

  should_require_unique_attributes :title
  should_require_attributes :body, :message => /wtf/
  should_require_attributes :title
  should_only_allow_numeric_values_for :user_id
end

class UserTest < Test::Unit::TestCase
  should_have_many :posts

  should_not_allow_values_for :email, "blah", "b lah" 
  should_allow_values_for :email, "a@b.com", "asdf@asdf.com" 
  should_ensure_length_in_range :email, 1..100
  should_ensure_value_in_range :age, 1..100
  should_protect_attributes :password
end

Makes TDD so much easier.

Controller Tests

Macros to test the most common controller patterns…


context "on GET to :show for first record" do
  setup do
    get :show, :id => 1
  end

  should_assign_to :user
  should_respond_with :success
  should_render_template :show
  should_not_set_the_flash

  should "do something else really cool" do
    assert_equal 1, assigns(:user).id
  end
end

Helpful Assertions

More to come here, but have fun with what’s there.


assert_same_elements([:a, :b, :c], [:c, :a, :b])
assert_contains(['a', '1'], /\d/)
assert_contains(['a', '1'], 'a')