Planet Merb

February 07, 2010

Yehuda Katz (wycats)

The Building Blocks of Ruby

When showing off cool features of Ruby to the uninitiated (or to a language sparring partner), the excited Rubyist often shows off Ruby’s “powerful block syntax”. Unfortunately, the Rubyist uses “powerful block syntax” as shorthand for a number of features that the Pythonista or Javaist simply has no context for.

To start, we usually point at Rake, Rspec or Sinatra as examples of awesome usage of block syntax:

get "/hello" do
  "Hello World"
end

In response, Pythonistas usually point to these syntaxes as roughly equivalent:

@get('/hi')
def hello():
  return "Hello World"
 
def hello() -> "/hi":
  return "Hello World"

While the Python version may not be quite as pretty, nothing about them screams “Ruby has much stronger capabilities here”. Instead, by using examples like Sinatra, Rubyists trade in an argument about great semantic power for one about superficial beauty.

Rubyists, Pythonistas and others working on web development share a common language in JavaScript. When describing blocks to “outsiders” who share a common knowledge of JavaScript, we tend to point at JavaScript functions as a close analogue. Unfortunately, this only furthers the confusion.

On the Ruby side, when PHP or Java announces that they’re “adding closures”, many of us don’t stop to ask “what kind of closures?”

Cut to the Chase

Let’s cut to the chase and use a better example of the utility of Ruby blocks.

def append(location, data)
  path = Pathname.new(location)
  raise "Location does not exist" unless path.exist?
 
  File.open(path, "a") do |file|
    file.puts YAML.dump(data)
  end
 
  return data
end

Here, the File.open method takes a block. It then opens a new file (in “append” mode), and yields the open file into the block. When the block completes, Ruby closes the file. Except that Ruby doesn’t just close the file when the block completes; it guarantees that the File will be closed, even if executing the block results in a raise. Let’s take a look at the implementation of File in Rubinius:

def self.open(*args)
  io = new *args
 
  return io unless block_given?
 
  begin
    yield io
  ensure
    begin
      io.close unless io.closed?
    rescue StandardError
      # nothing, just swallow them.
    end
  end
end

This means that you can wrap up idioms like pervasive try/catch/finally in methods.

# Without blocks
def append(location, data)
  path = Pathname.new(location)
  raise "Location does not exist" unless path.exist?
 
  begin
    file = File.open(path, "a")
    file.puts YAML.dump(data)
  ensure
    file.close
  end
 
  return data
end

Because Ruby runs ensure clauses even when the exception happened in a block, programmers can reliably ensure that Ruby executes teardown logic hidden away in abstractions.

This example only demonstrates the power of well-designed lambdas. With the addition of one small additional feature, Ruby’s blocks become something altogether different.

def write(location, data)
  path = Pathname.new(location)
  raise "Location does not exist" unless path.exist?
 
  File.open(path, "w") do |file|
    return false if Digest::MD5.hexdigest(file.read) == data.hash
    file.puts YAML.dump(data)
  end
 
  return true
end

In the above case, imagine that writing the data to disk is quite expensive, and we can skip writing if the MD5 hash of the file’s contents match a hash method on the data. Here, we’ll return false if the method did not write to disk, and true if the method did.

Ruby’s blocks support non-local-return (some references), which means that a return from the block behaves identically to returning from the block’s original context. In this case, returning from inside the block returns from the write method, but Ruby will still run the ensure block closing the file.

You can think of non-local-return as behaving something like:

def write(location, data)
  path = Pathname.new(location)
  raise "Location does not exist" unless path.exist?
 
  File.open(path, "w") do |file|
    raise Return.new(false) if Digest::MD5.hexdigest(file.read) == data.hash
    file.puts YAML.dump(data)
  end
 
  return true
rescue Return => e
  return e.object
end

where Return is Return = Struct.new(:object).

Of course, any reasonable lambda implementation will support this, but Ruby’s version has the benefit of feeling just like a normal return, and requiring much less chrome to achieve it. It also behaves well in scenarios that already use rescue or ensure, avoiding mind-warping combinations.

Further, Ruby also supports super inside of blocks. Imagine the write method was defined on a subclass of a simpler class whose write method took the raw data from the file and printed it to a log.

def write(location, data)
  path = Pathname.new(location)
  raise "Location does not exist" unless path.exist?
 
  File.open(path, "w") do |file|
    file_data = file.read
    super(location, file_data)
    return false if Digest::MD5.hexdigest(file_data) == data.hash
    file.puts YAML.dump(data)
  end
 
  return true
end

In a purer lambda scenario, we would need to store off a reference to the self, then use that reference inside the lambda:

def write(location, data)
  path = Pathname.new(location)
  raise "Location does not exist" unless path.exist?
 
  this = self
  File.open(path, "w") do |file|
    file_data = file.read
 
    # imaginary Ruby construct that would be needed without
    # non-local-super
    this.super.write(location, file_data)
    raise Return.new(false) if Digest::MD5.hexdigest(file_data) == data.hash
    file.puts YAML.dump(data)
  end
 
  return true
rescue Return => e
  return e.object
end

You can also yield to a method’s block inside a block. Imagine that the write method is called with a block that chooses the correct data to use based on whether the file is executable:

def write(location)
  path = Pathname.new(location)
  raise "Location does not exist" unless path.exist?
 
  File.open(path, "w") do |file|
    file_data = file.read
    super(location)
    data = yield file
    return false if Digest::MD5.hexdigest(file_data) == data.hash
    file.puts YAML.dump(data)
  end
 
  return true
end

This would be called via:

write("/path/to/file") do |file|
  if file.executable?
    "#!/usr/bin/env ruby\nputs 'Hello World!'"
  else
    "Hello World!"
  end
end

In a pure-lambda language, we would take the block in as a normal argument to the function, then call it inside the closure:

def write(location, block)
  path = Pathname.new(location)
  raise "Location does not exist" unless path.exist?
 
  this = self
  File.open(path, "w") do |file|
    file_data = file.read
 
    # imaginary Ruby construct that would be needed without
    # non-local-super
    this.super.write(location, file_data)
    data = block.call(file)
    raise Return.new(false) if Digest::MD5.hexdigest(file_data) == data.hash
    file.puts YAML.dump(data)
  end
 
  return true
rescue Return => e
  return e.object
end

The real benefit of Ruby’s approach comes from the fact that the code inside the block would be identical if the method did not take a block. Consider the identical method, except taking a File instead of a location:

def write(file)
  file_data = file.read
  super(file)
  data = yield file
  return false if Digest::MD5.hexdigest(file_data) == data.hash
  file.puts YAML.dump(data)
  return true
end

Without the block, the Ruby code looks exactly the same. This means that Ruby programmers can more easily abstract out repeated patterns into methods that take blocks without having to rewrite a bunch of code. It also means that using a block does not interrupt the normal flow of code, and it’s possible to create new “control flow” constructs that behave almost identically to built-in control flow constructs like if and while.

Rails uses this to good effect with respond_to, which provides convenient syntax for declaring content negotiation:

def index
  @people = Person.find(:all)
 
  respond_to do |format|
    format.html # default action is render
    format.xml { render :xml => @people.xml }
  end
end

Because of the way Ruby blocks work, you can also return from any of the format blocks:

def index
  @people = Person.find(:all)
 
  respond_to do |format|
    format.html { redirect_to(person_path(@people.first)) and return }
    format.xml  { render :xml => @people.xml }
    format.json { render :json => @people.json }
  end
 
  session[:web_service] = true
end

Here, we returned from the HTML format after redirecting, allowing us to take additional action (setting a :web_service key on the session) for other cases (XML and JSON mime types).

Keep in mind that the code above is a demonstration of a number of features of Ruby’s blocks. It’s very rare to see return, yield and super all used in a single block. That said, Ruby programmers commonly use one or more of these constructs inside blocks, because their usage is seamless.

So Why Are Ruby’s Blocks Better?

If you made it this far, let’s take a look at another use of blocks in Ruby: mutex synchronization.

Java supports synchronization via a special synchronized keyword:

class Example {
  final Lock lock = new Lock();
 
  void example() {
    synchronized(lock) {
      // do dangerous stuff here
    }
  }
}

Essentially, Java provides a special construct for expressing the idea that it should run a block of code once at a time for a given instance of the synchronization object. Because Java provides a special construct, you can return from inside the synchronization block, and the Java runtime does the appropriate things.

Similarly, Python required the use of try/finally until Python 2.5, when they added a special language feature to handle the try/finally idiom:

class Example:
  # old
  def example(self):
    lock.acquire()
    try:
      ... access shared resource
    finally:
      lock.release() # release lock, no matter what
 
  # new
  def example(self):
    with lock:
      ... access shared resource

In Python’s 2.5’s case, the object passed to with must implement a special protocol (including __enter__ and __exit__ methods), so the with statement cannot be used like Ruby’s general-purpose, lightweight blocks.

Ruby represents the same concept using a method that takes a block:

class Example
  @@lock = Mutex.new
 
  def example
    @@lock.synchronize do
      # do dangerous stuff here
    end
  end
end

Importantly, synchronize is a normal Ruby method. The original version, written in pure Ruby, looks like this:

def synchronize
  lock
  begin
    yield
  ensure
    unlock
  end
end

It has all the hallmarks of what we’ve discussed so far. It locks, yields to the block, and ensures that the lock will be released. This means that if a Ruby programmer returns from inside the block, synchronize will behave correctly.

This example demonstrates the key power of Ruby’s blocks: they can easily replace language constructs. In this case, a Ruby programmer can take unsafe code, plop it inside a synchronization block, and it will continue to work.

Postscript

I’ve historically written my posts without very many links, mostly out of a fear of links going out of date. I’ve received increasing requests for more annotations in my posts, so I’ll start doing that. Let me know if you think my annotations in this post were useful, and feel free to give me any suggestions on that front that you find useful.

by wycats at February 07, 2010 02:53 PM

February 05, 2010

Merbunity

MerbAdmin Installation and Overview

Erik Michaels-Ober demonstrates the installation process and some of the functionality of MerbAdmin.


Watch it...

by sferik at February 05, 2010 05:59 AM

Learn About Merb Dependencies and the new Bundler!

Carl Lerch and Yehuda Katz released this helpful screencast with Merb 1.0.6. It deals with how to utilize all the new features the new gem dependency bundler brings.


Watch it...

by wifelette at February 05, 2010 05:43 AM

February 04, 2010

Jack Dempsey (jackdempsey)

notes from yet another rails 3 upgrade

These tips and tricks are valid as of today, February 3rd, 2010. Who knows what next week will bring, but for now, I thought compiling some of the techniques and hacks I've seen might help others.

Rails Related

If you see a "no such file to require: rails/all" you probably don't have Rails installed correctly. I was basing my upgrade on the great screencast produced by Topfunky over at peepcode.com, and his method didn't work for me. To get things running I added this to my Gemfile:

path "/Users/jack/git/rails", :glob => "{*/,}*.gemspec"
gem "rails", "3.0.pre"
gem "rails", "3.0.0.beta" # Just changed today it seems


Obviously, change the path to wherever you have rails checked out locally.

HAML

If you see something like this: Missing template articles/index with {:formats=>[:html]} in view path

you probably need to install haml.


$ haml --rails .


and then you'll likely see an error about html_safe!

Geoff has a nice little idea going with a config/initializers/rails3_hacks.rb file which I've also done. You can drop this in and get by the errors for now:

projects/app master > cat config/initializers/rails3_hacks.rb
class String
def html_safe!() self end
def html_safe?() true end
def safe_concat(value) value+self end
end


WillPaginate

Looks like Mislav and other's have been doing a lot of work in upgrading the plugin. If you see a "no paginate method for Class...." error, try cloning the source down locally, check out the rails 3 branch,build and install that gem and then update your Gemfile:

...
gem 'will_paginate', '3.0.pre'
...

It also seemed that WillPaginate wasn't being required into my app. For now I've created a config/initializers/requires.rb file and dropped in random requires for attention later. Putting a "require 'will_paginate'" in there fixed that up nicely.

Update:
Seems something's broken now. I'm getting this error:

uninitialized constant ActiveRecord::Calculations::CALCULATIONS_OPTIONS

Seems WP relies on that constant without checking for its existence, and it looks like its gone now. Easy enough to quick patch it if you need to get by it, but I imagine it'll be fixed in the rails3 branch soon enough.
Assorted Issues

HTMLEntities doesn't seem to be working, so I commented that out for now. For a great beginning list of what gems should be working, take a look here: http://wiki.rubyonrails.org/rails/version3/plugins_and_gems

Devise: not ready for rails 3 yet. I think they're trying to see what routing changes will settle and how that will affect their code. I'm going to see if I can pop over into that and help out a bit as I'd love to keep using it in this app.

new_rails_defaults.rb: I had an error from this file and realized it's old anyway, so git rm and it's gone.

Passenger

I also overhauled a bunch of other ruby related items on my boxes recently, and one of those items was passenger. After updating to 2.2.9, reinstalling the module, changing RailsEnv to RackEnv, things are mostly good. Remember to point to the right ruby if you're using rvm. I also deleted the config.ru file per their recommendation: "Smart spawning (the mechanism with which REE’s 33% memory reduction is implemented) is *not* supported for Rack apps. This means that if you want to utilize smart spawning with Rails 3, then you should remove your config.ru file."

I think that's it for now. I imagine I'll update this page as I deal with new issues. Pretty excited about the new changes and starting to actually make use of them.

Update

Previous notes were from my macbook pro. Now that I'm back on the iMac I'm finding other issues. Latest is:

/Users/jack/git/rails/activesupport/lib/active_support/dependencies.rb:167:in `require': no such file to load -- rails/commands/rails (LoadError)

I'm actually not sure if that was something I did as it looks like its definitely just "require 'rails/commands'" in the latest source, but either way, if you're seeing that, just take off the second rails in that line. Correct line should be:

require 'rails/commands'

at the end of your script/rails.

Bundler

Somehow just found myself facing this:

projects/app master > bundle install
/Users/jack/.rvm/gems/ree-1.8.7-2010.01/bin/bundle: line 1: require: command not found

A quick cat and I see something's changed, no #!...ruby line to see. Realized I had bundler 0.9.0 and 0.9.0.pre4, so I uninstalled them both, and reinstalled with:

$ gem install bundler --pre

and now have bundler-0.9.0.pre5 installed.

Still things are borked, but it seems its a result of github being down: "Page did not respond in a timely fashion."

Will try again in a few to make sure this gets me back on track.

Update

Ok, github's back, and just saw a tweet from Wycats. Looks like 0.9.0 final is out now, but it's recommended to wait til tomorrow and 0.9.1 + some docs. YMMV.

Application != ApplicationController

So, the app I'm converting was originally written in Merb, was partially converted to Rails 2, and is now on its way towards Rails 3. In this transition I've generally remembered what pieces to change from Merb to Rails, but I had a nice stumble earlier in forgetting to change a controller. So, if you find yourself in a place where you have a route that you know works, but is not recognized, make sure your controller is named whatever_controller.rb, and contains the code:

class WhateverController ApplicationController
...
end

not " Application". You'll an error about a route missing and could easily spend a couple hours missing the obvious.

Routes

I keep tripping myself up with this. Lets say you have a route defined as:


match 'foobar/:foobar' => 'foobar#foobar', :as => :foobar


These calls will all fail:


ree-1.8.7-2009.10 > app.foobar_path
ActionController::RoutingError: No route matches {:action=>"foobar", :controller=>"foobar"}
... from (irb):3
ree-1.8.7-2009.10 > app.foobar_path('')
ActionController::RoutingError: No route matches {:use_defaults=>false, :action=>"foobar", :foobar=>"", :controller=>"foobar"}
... from (irb):4
ree-1.8.7-2009.10 > app.foobar_path('test')
=> "/foobar/test"


until that last one which passes in a value. This makes sense, as the route defines foobar as a requirement, and not passing in a value is an 'error'. It's a little less obvious that an empty string doesn't satisfy it to me, and definitely not obvious when you have this in a loop and an object just happens to be missing its value for foobar.

One way around this is to make the :foobar piece optional, and handle that reality in your controller elsewhere. You could also protect against this by checking that object.foobar exists in your loop, and not linking unless it does.

I've also just realized that for a certain route of mine, one that passes in domain names, sending in 'euraeka.com' will result in an error. I'm not sure if this is the recommended solution, but its letting me progress for now:


match 'domain/:domain' => 'search#domain', :as => :domain, :domain => /.+/


I'm using domain here instead of host as I think host might be reserved somewhere. Couldn't seem to get it to work before, so if you're having that issue, let me know.

by Jack Dempsey (noreply@blogger.com) at February 04, 2010 12:20 PM

February 02, 2010

Matt Aimonetti (mattetti)

How and why I joined the “suit people”

It is now official: I have traded my freedom & home office for a job title, an Aeron chair in a cubicle and a 401K.

I received my new employee package and, in less than a week, I will officially become a full-time employee at  SCEA (Sony Computer Entertainment America).

I’m going to work in the PlayStation department, working on PS3, PS2 and PSP game titles developed by various game studios.

Why ‘o why?

Why leave behind a happy life of indie contracting to join corporate America?

For many reasons actually:

  • A Team

Being a consultant I have been working with other independent consultants and existing teams. Nonetheless, I really miss being part of a stable team which grows together and learns from each other as we go through new projects and maintain old ones.

  • Long term plan

As a consultant, I usually start projects or “rescue” existing projects. I work on them for a little while and then move on. It’s exciting and rewarding but you don’t really pay the consequences of your mistakes. You usually don’t have to maintain the code you wrote and you rarely deal with the mistakes you made.

It sounds good, nobody likes to maintain the crappy awesome code they wrote 2 years ago and most developers love working on new stuff. But at the same time, to become a better engineer you need to learn from you mistakes and assuming responsibility for your bad decisions is part of the process.

It might sound weird, but I’m actually excited to work on long term projects and feel some sort of ownership over the projects. Having to support games for many years means that I’d better not mess up the implementation. And if I do, I hope I’ll quickly learn from my mistakes.

  • Avoiding burn out

There is no secret: when you are passionate about what you do, you have a hard time stopping and taking a break. I’m a recovering workaholic and it’s really hard for me to say no when I’m presented the possibility to work on interesting projects. I love what I do and I keep writing code even after I’m done with client work.

The problem is that this can start me on the slippery slope to isolating myself from friends, family and people who don’t share the same passion. I’m really lucky that my wife is a geek and loves hanging out at conferences, looking at code and playing with my buggy prototypes. But still, I spend too much time “playing” with my computer and I just can’t manage my free time wisely.

Having a full time position will hopefully help me put boundaries and will hopefully teach me to disconnect from work.

  • Exciting projects

Hey, let’s be honest, how many geeks do you know don’t want to work in the video game industry? By the way, if you don’t have a PS3, they are now at $299 and on top of getting an awesome console you get a blue ray player! (And no, I do not receive any bonuses or commissions for mentioning the console or promoting it in my blog. I had to pay for my own like everyone else.)

Corporate America? Are you going to write Java now?

No, I’m mainly going to stick to the language I love: Ruby.
From time to time I will probably use other languages here and there, but that usually makes me love Ruby even more. The reality is that Ruby’s power and flexibility seem to be appreciated by SCEA, which makes sense when you have tight deadlines and a lot of new technologies to deal with. Ruby is a perfect match!

As you can guess, I can’t go into any detail about how and why Sony uses Ruby, but let me just say that while games are still usually written in C++, they are becoming more and more interactive and need to communicate with game servers where some logic operates. Game players also need to interact with other gamers as well as check their gaming progress online, as well as the progress of the players around them etc… Basically, outside of the game engine and the console SDK, there is a lot of potential for Ruby.

Coming back to Corporate America, I have to say that I’ve known my future manager for a few years now. He’s always been a fervent Ruby advocate and has introduced lots of teams to the happiness of Ruby & Rails development. He’s also a great developer who’s contributing patches to major projects and has a bunch of cool stuff on github. To give you an idea, my job description mentions Rails, Merb, Sinatra, CouchdB, MongoDB, Redis, AWS. All these Ruby technologies are actually already used in production or are being seriously evaluated.

I’m also really looking forward to join the existing team. I know I’m going to love working with a bunch of awesome developers coming from various backgrounds.

Those who know me, know that I’m not a morning person. And while your typical office job is categorized as ‘9-5′, don’t feel too bad for me. I will be joining the video game product department, and morning people are rather rare in these kinds of groups ;)

Conclusion

I’m really excited about this opportunity. For me, it is proof again that the Ruby revolution took place and that the Enterprise is evolving. Of course, time will tell if I am right, but I am quite confident.

Also, Sony is always looking for new, talented people who want to push the entertainment world to the next level. Feel free to keep in touch with me if you are interested in joining the fun.

by Matt Aimonetti at February 02, 2010 07:19 PM

Undo/Redo in MacRuby

As I’m working on my upcoming O’Reilly MacRuby book, I’m writing quite a lot of example code. I have spent the last few weeks digging through most of the Foundation framework classes to hopefully make Cocoa more accessible to Ruby developers.

In some instances things might look quite weird to someone new to Cocoa in some cases, things seem almost too easy. Here is an example implementing a undo/redo functionality using Foundations’ NSUndoManager.

framework 'Foundation'
class Player
  attr_accessor :x, :y
 
  def initialize
    @x = @y = 0
  end
 
  def undo_manager
    @manager ||= NSUndoManager.alloc.init
  end
 
  def left
    undo_manager.prepareWithInvocationTarget(self).right
    @x -= 1
  end
 
  def right
    undo_manager.prepareWithInvocationTarget(self).left
    @x += 1
  end
end

Which you can use as such:

 
>> lara = Player.new
=> <Player:0x200267c80 @y=0 @x=0>
>> lara.undo_manager.canUndo
=> false # normal since we did not do anything yet
>> lara.left
=> -1
>> lara.x # -1
=> -1
>> lara.undo_manager.canUndo
=> true # now we can undo, so let's try
>> lara.undo_manager.undo # undo back to initial position
=> #<NSUndoManager:0x200257560>
>> lara.x
=> 0
>> lara.undo_manager.canUndo
=> false # we can't anymore which makes sense 
>> lara.undo_manager.canRedo
=> true # however we can redo what we just undone
>> lara.undo_manager.redo # redo to before we called undo
=> #<NSUndoManager:0x200257560>
>> lara.x
=> -1

The above example was tested in macirb but as you can see, actions can be undone and redone very very easily. This is just a quick preview of what you can do using Ruby + Cocoa and hopefully it will give you some cool ideas to implement.

by Matt Aimonetti at February 02, 2010 10:19 AM

February 01, 2010

Yehuda Katz (wycats)

Bundler 0.9: Heading Toward 1.0

Over the past two years, Carl and I have been working on-again off-again on the problem of dependency resolution. Fabien Franzen implemented the first partial solution for Merb, with thor merb:gem:install.

When we started working on Rails, we knew we wanted to finally crack the nut, making it possible for Rails itself to have some of its own dependencies, and solving some persistent, long-term problems with gem plugins.

Earlier this year, we released bundler, our first real attempt to solve this problem. Among other things, it shipped with the first true dependency resolver for Rubygems. It also modeled the entire dependency process on top of Rubygems, allowing us to support git repositories in the same dependency resolution process as Rubygems themselves.

Over the next few months, we refined the bundler quite a bit. We’re proud of the fact that individuals, web shops, and deployment companies have adopted bundler, and Gemfile has become a standard way of expressing gem dependencies for an app.

During this time, we’ve also received quite a bit of feedback. As we approach the release of Bundler 1.0, which we hope to ship along with Rails 3.0 final, we took the opportunity to take a look at all the feedback people have sent so far.

Having done so, we’re proud to announce Bundler 0.9 with radically improved workflows that fit our needs and the needs of those who have contributed feedback and patches.

The Cache

Before Bundler 0.9, Bundler installed gems and git repositories to a local application cache. When we looked at the deployment workflow, we found that while people liked the ability to cache their .gem files in their application, they had a lot of trouble at deployment time.

Essentially, people (and we!) wanted the ability to expand the gems to a central cache that they could reuse across deployments. People tried various symlinking approaches, but it became clear to us Bundler 1.0 needed to support this workflow natively.

On a related note, people who developed a number of applications on a single machine wanted to be able to reuse a single system cache across their application, and not need to connect to remotes so often when they already had all the gems they needed on their systems.

Finally, Rails itself grated against the default Bundler workflow. Most people installing a new Rails app run gem install rails, then rails my_app, and then want to go into their application and start working. But with Bundler 0.5 to 0.8, they needed to hit the remotes again even though, by definition, the system gem cache already had all the gems they needed.

Runtime

The fully-packaged application works fantastically for deployment, enabling a repeatable, reliable development to staging to production workflow. However, the need to explicitly bundle the application after added a new dependency in the very early stages of an application’s life cycle feels more like a compile step than a lean mean agile machine.

In Bundler 0.9, we’re adding the ability to run your application against gems already on your system, with the same reliability that you’ve grown to love from our dependency resolver.

Once you’ve gotten your application working, you can lock down the dependencies, so coworkers or production will use exactly the same environment that worked for you.

This allows you to use your common system gem repository across multiple apps, with a fully resolved virtual environment for each application based on the app’s dependencies specified in the Gemfile.

Locking

A lot of people (including me) love the idea of storing the .gem files in the application to create a single deployable unit with no network dependencies.

Storing the .gem files in the repository also provides a record of the fully resolved dependencies for your application, so that a new released gem between testing and deployment cannot change the environment. In Bundler 0.9, we provide a mechanism for you to save that record without having to also store the .gem files.

This won’t give you a single, dependency-less deployment package, but it will save you from unexpected environment changes.

New Commands

When we started Bundler, we had just one command: gem bundle. Over the following months, the command took on a life of its own, with a slew of flags representing both options and verbs. Bundler 1.0 will have a small, streamlined list of commands, each with its own set of flags:

bundle pack

Take all .gem files needed for the application and place them into the local application. By default, bundler places them in vendor/gems.

bundle lock

Resolve all dependencies in the Gemfile, and store a record of that process. In the future, use that record, preventing any changes in the environment or in the remote sources from changing the gems used by the application.

bundle install

Install the bundle specified by the Gemfile to the cache. By default, Bundler installs the gems (and git repositories) into system gems. You can override this to install into another location, or into your local application, just like in Bundler 0.8 and before.

After cloning a new repository for the first time, you will probably want to run this command.

If you packed gems, Bundler will use the gems from your application. If you packed and locked gems, Bundler will install the gems immediately without updating the remote sources.

bundle check

Check to see whether your cache has all the required dependencies. If it does not, Bundler will print out the list of missing gems.

bundle exec …

Run the specified command using the local environment. For instance, if you have Rails 2.3 and 3.0 installed, if you run bundle exec rails . in a Rails 2.3 application, Bundler will run the rails command using Rails 2.3 (and other gems in the current environment).

Environments

In Bundler 0.9, as in Bundler 0.8 and before, the Gemfile specifies an app-specific environment. New in Bundler 0.9, you may store the .gem files and unpacked gems in a central location, as well as in the application itself.

Because Bundler ships with a dependency resolver, you do not need to specify named environments and switch between them. Instead, the environments are virtual, based on the gems you specify as application dependencies in the Gemfile, and you still get all the benefits of a shared, system-wide cache.

by wycats at February 01, 2010 08:50 AM

SafeBuffers and Rails 3.0

As you may have read, Rails adds XSS protection by default in Rails 3. This means that you no longer have to manually escape user input with the h helper, because Rails will automatically escape it for you.

However, it’s not as simple as all that. Consider the following:

Hello <strong>friends</strong>!
 
<%= tag(:p, some_text) %>
<%= some_text %>

In the above example, we have a few different scenarios involving HTML tags. First off, Rails should not escape the strong tag surrounding “friends”, because it is unambiguously not user input. Second, Rails should escape some_text in the <p> tag, but not the <p> tag itself. Finally, the some_text in the final tag should be escaped.

If some_text is <script>evil_js</script>, the above should output:

Hello <strong>friends</strong>!
 
<p>&lt;script&gt;evil_js&lt;/script&gt;</p>
&lt;script&gt;evil_js&lt;/script&gt;

In order to make this happen, we have introduced a new pervasive concept called html_safe into Rails applications. If a String is html_safe (which Rails determines by calling html_safe? on the String), ERB may insert it unaltered into the output. If it is not safe, ERB must first escape it before inserting it into the output.

def tag(name, options = nil, open = false, escape = true)
  "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe
end

Here, Rails creates the tag, telling tag_options to escape the contents, and then marks the entire body as safe. As a result, the <p> and </p> will emerge unaltered, while Rails will escape the user-supplied content.

The first implementation of this, in Koz’s rails-xss plugin, accomplished the above requirements by adding a new flag to all Strings. Rails, or Rails applications, could mark any String as safe, and Rails overrode + and << to mark the resulting String appropriately based on the input Strings.

However, during my last performance pass of Rails, I noticed that overriding every String concatenation resulted in quite a bit of performance overhead. Worse, the performance overhead was linear with the number of <%= %> in a template, so larger templates didn’t absorb the cost (as they would if the problem was once-per-template).

Thinking about the problem more, I realized (and confirmed with Koz, Jeremy, and Evan Phoenix of Rubinius), that we could implement roughly the same feature-set in a more performant way with a smaller API impact on Ruby. Because the problem itself is reasonably complex, I won’t go into a lot of detail about the old implementation, but will explain how you should use the XSS protection with the new implementation. If you already used Koz’s plugin or are working with the prereleases of Rails, you’ll notice that today’s commit changes very little.

SafeBuffer

In Rails 3, the ERB buffer is an instance of ActiveSupport::SafeBuffer. SafeBuffer inherits from String, overriding +, concat and << so that:

  • If the other String is safe (another SafeBuffer), the buffer concatenates it directly
  • If the other String is unsafe (a plain String), the buffer escapes it first, then concatenates it

Calling html_safe on a plain String returns a SafeBuffer wrapper. Because SafeBuffer inherits from String, Ruby creates this wrapper extremely efficiently (just sharing the internal char * storage).

As a result of this implementation, I was starting to see a lot of the following idiom in the codebase:

buffer << other_string.html_safe

Here, Rails is creating a new SafeBuffer for the other_string, then passing it to the << method of the original SafeBuffer, which then checks to see if it is safe. For cases like this, I created a new safe_concat method on the buffer which uses the original, native concat method, skipping both the need to create a new SafeBuffer and the need to check it.

Similarly, concat and safe_concat in ActionView proxy to the concat and safe_concat on the buffer itself, so you can use safe_concat in a helper if you have some HTML you want to concatenate to the buffer with no checks and without escaping.

ERB uses safe_concat internally on the parts of the template outside of <% %> tags, which means that with the changes I pushed today, the XSS protection code adds no performance impact to those cases (basically, all of the plain text in your templates).

Finally, ERB can now detect the raw helper at compile time, so if you do something like <%= raw some_stuff %>, ERB will use safe_concat internally, skipping the runtime creation of a SafeBuffer and checks for html_safety.

Summary

In summary, the XSS protection has the following characteristics:

  • If a plain String is passed into a <%= %>, Rails always escapes it
  • If a SafeBuffer is passed into a <%= %>, Rails does not escape it. To get a SafeBuffer from a String, call html_safe on it. The XSS system has a very small performance impact on this case, limited to a guard calling the html_safe? method
  • If you use the raw helper in a <%= %>, Rails detects it at compile-time of the template, resulting in zero performance impact from the XSS system on that concatenation
  • Rails does not escape any part of a template that is not in an ERB tag. Because Rails handles this at template compile-time, this results in zero performance impact from the XSS system on these concatenations

In comparison, the initial implementation of XSS impacted each concatenation or + of String, had impact even if the app used the raw helper, and even on plain Strings in templates.

That said, I want to extend personal thanks to Koz for getting the first draft out the door. It worked, demonstrated the concept, and let the community test it out. All in all, an excellent first pass.

by wycats at February 01, 2010 07:41 AM

Corporations Cannot Have Natural Rights… Duh

When I first read through the Citizens United decision that essentially made it illegal to “discriminate” against corporate political speech, I found myself very torn. On the one hand, I’m an extremely avid supporter of free speech rights, and Kennedy wrote the majority decision to tug at my heartstrings:

Premised on mistrust of governmental power, the First Amendment stands against attempts to disfavor certain subjects or viewpoints or to distinguish among different speakers, which may be a means to control content.

On the other hand, something felt wrong.

In the days that followed, I realized the the court had pulled a bait-and-switch, finding a way to split defenders of free speech, preventing a consistent response to the ruling, and resulting in a fair bit of liberal support for the ruling.

If you read the above quote closely, you can see the lie hiding in plain sight. The court, without drawing much notice, calls corporations “speakers” in the context of the First Amendment.

The problem is simple. The Bill of Rights exists to protect, for the long term, a set of natural rights. If you don’t believe me, read the writings of the anti-federalists, the guys who argued against the constitution and successfully agitated for the addition of the Bill of Rights in the first place:

That insatiable thirst for unconditional controul over our fellow-creatures, and the facility of sounds to convey essentially different ideas, produced the first Bill of Rights ever prefixed to a Frame of Government. The people, although fully sensible that they reserved every tittle of power they did not expressly grant away, yet afraid that the words made use of, to express those rights so granted might convey more than they originally intended, they chose at the same moment to express in different language those rights which the agreement did not include, and which they never designed to part with, endeavoring thereby to prevent any cause for future altercation and the intrusion into society of that doctrine of tacit implication which has been the favorite theme of every tyrant from the origin of all governments to the present day.

The language is a big crufty, but the meaning is clear. Without government, people have certain rights. They choose to surrender some of them to the government. The Constitution outlines the powers they have surrendered, and the Bill of Rights outlines specific cases where those powers may not tread.

However, corporations do not exist outside of government. They are not “creatures”. Instead, corporations are creations of the government, and therefore cannot reserve any rights via a bill of rights.

Looking at the quote from the ruling again:

Premised on mistrust of governmental power, the First Amendment stands against attempts to disfavor certain subjects or viewpoints or to distinguish among different speakers, which may be a means to control content.

The ruling fundamentally subverts that actual purpose of the Bill of Rights, using language that appeals to defenders of free speech to apply to entities that, by their very definition, the First Amendment cannot cover.

In short, the Bill of Rights protects the natural rights of people who have already surrendered a fair bit of their autonomy to the federal government. Corporations, by definition, cannot have natural rights, and since they don’t exist outside of government, cannot have surrendered any autonomy to the government. Therefore, the Bill of Rights, and the First Amendment, cannot apply to them. QED.

by wycats at February 01, 2010 06:47 AM

Matt Aimonetti (mattetti)

MacRuby 0.5 final is out

After going through two betas, MacRuby 0.5 final is now released and can be downloaded by clicking on the icon below:


MacRuby 0.5

Don’t worry about having MacRuby and Ruby 1.8.x or 1.9 installed, MacRuby is namespaced and won’t affect your current Ruby installations, just download and launch the installer. (Note: The build was compiled for SnowLeopard only)

You can read all the details of the release on the MacRuby website.

So what changed since 0.4? Too many things for me to list them here but basically 0.5 uses LLVM to compile code and make MacRuby faster and integrate better with the Obj-c runtime. However since the last beta, here is what changed:

  • HotCocoa is now a separate gem
  • improved AOT compilation
  • Grand Central Dispatch support – use all your cores without the pain of threads. Read this post for more info.

0.5 is a solid release which I consider production ready, I personally wrote a few of small Cocoa apps in MacRuby and everything has been working very well. Of course, I’m also excited about the new stuff in 0.6 trunk like the debugger previewed a few weeks ago: http://merbist.com/2010/01/18/how-to-detect-cylons-with-macruby/ but also some drastic changes in the primitive classes that I might cover later on.

Finally, people are asking if the iPad will be able to run apps running in MacRuby. Unfortunately, the current answer is: no. The two issues with the IPhone/iP*d OS are the lack of Garbage Collector and support for BridgeSupport (needed to define CocoaTouch constants available from MacRuby). However, this matter is being discussed on the mailing list and progress is made by contributors (the core team primarily focusing on the desktop).

That is going to be an exciting Ruby week as MacRuby 0.5 is now out and Rails 3 beta/RC0 is expected really soon.

by Matt Aimonetti at February 01, 2010 03:13 AM