Posted about 4 hours back at almost effortless
I'm happy to announce that I've made my latest side-project open source. It's called KZAK. It's a simple web-based jukebox that you can use to share and listen to music with your friends.
The feature set is pretty limited right, but I hope to continue to improve things over time. I'm already encouraged by how quickly some of my friends have taken to the app, and I think you'll enjoy it - even in this early form.
So far you can:
- Invite people to use the site via email
- Upload mp3, mp4, and m4a (iTunes) tracks with an upload queue and progress
- Listen to the uploaded music as a playlist, even in an inactive browser tab
Like I said, it's pretty basic (invite, upload, listen) but surprisingly functional. Plus, I'm using all kinds of interesting stuff behind the scenes, which is why I really wanted to share the code ;)
To begin with, we've got a Rails app that's using the latest and greatest in user authentication technology: Devise. If you're using something like restful_authentication or Authlogic, I implore you to take a look at Devise. It's a phenomenal improvement from these other two popular options, and it's being actively supported by José Valim, the latest Rails committer. Essentially, it's a Rails Engine that sits on top of Warden - a generalized Rack authentication framework. This combination is extraordinarily flexible and easy to use. It's opinionated (in a good way) while simultaneously doing a good job of staying out of the way. It introduces very little code into your application, and the source is well documented, well tested, and easy to follow. A++ highly recommended.
To handle the file uploads, I've switched from Paperclip to CarrierWave. While Paperclip has (and continues) to serve me well in many applications I work with, I really appreciate the modular approach that CarrierWave takes. It's agnostic as to which of the popular S3 clients you use, supporting both aws/s3 and right_aws. It's also ORM agnostic and not tightly coupled to Active Record. The tight coupling of Paperclip has caused us some grief at work, and I'm also confused about the state of Paperclip's support for aws/s3 and right_aws. So, I was happy to find this new project, and the maintainer Jonas Nicklas seems to be an extremely responsive and helpful dude, which is always good thing. The code looks great, and I've had an easy time working with this library so far.
In concert with CarrierWave, I'm also using the venerable SWFUpload to support upload queues and progress meters. I'm absolutely baffled as to why this kind of thing isn't easy/possible to support without Flash, but here we are. Of course, I have a fallback "regular upload form" that still uses some ajax to make things a little easier. There are a few blog posts and tutorial applications around on GitHub that helped me get SWFUpload working with Rails and jQuery, and I'm happy to put back out an example application that other people can refer to if they're interested in supporting upload queues and/or upload progress meters.
Next, to support audio playback while I work on supporting html5 properly, I'm using the extremely awesome SoundManager 2. Unfortunately, this is another part of the infrastructure using Flash, but the features and functionality of SoundManager are really something special. I've only scratched the surface of what this library can do, but I'm already enjoying it quite a bit. If you're working with jQuery and SoundManager, you may find the KZAK source code worth perusing. You might also take a look at Adrien Gibrat's plugin, which is a cool jQuery plugin that packs a lot of functionality.
Also running in the background of KZAK is a Twitter-style following/unfollowing system that I haven't exposed much of yet. It's basically the same system that's powering Flowcoder. You can check out this example app I made if you're interested in seeing that on its own. Currently, all users in the system follow (and are followed by) all of the other users. I plan to allow for "unfollowing" users some time soon, which will allow for some healthy splintering of the community in the case that you're not interested in everything that everyone is uploading.
Finally - and perhaps best of all - KZAK is fully compatible with and easy to install on Heroku. All you need is an S3 account and you're ready to get started with a web-based jukebox for you and your friends for free.
http://github.com/trevorturk/kzak
Anyway, please feel free to dig around the source code if you're interested in any of this. I think there's a lot of good stuff in there, especially considering that the Ruby portion of the app is clocking in at under ~250 LOC right now. Thanks, open source community ;)
Posted about 3 hours back at opensoul.org - Home
If you’re running Passenger in development, here is how to make Windows running in a virtual machine connect to your app in Passenger.
- Boot up the VM and open up the Windows command prompt (go to “Start->Run…”, enter “cmd” and press enter)
- Type
ipconfig to see the network configuration. Take note of the “Default Gateway” address.
- Navigate to C:\WINDOWS\system32\drivers\etc and edit the
hosts file. Add a line with the gateway address pointing to your app’s domain (you can even list multiple on the same line).
172.16.248.2 awesomeapp.local otherawesomeapp.local
- Open up a browser in the VM and type in the address.
Tada! Now you can test out your app in those other browsers.
Posted 16 minutes back at almost effortless
Amazon's CloudFront is a phenomenal addition to their S3 file-hosting service.
Amazon CloudFront is a web service for content delivery. It integrates with other Amazon Web Services to give developers and businesses an easy way to distribute content to end users with low latency, high data transfer speeds, and no commitments.
Amazon CloudFront delivers your static and streaming content using a global network of edge locations. Requests for your objects are automatically routed to the nearest edge location, so content is delivered with the best possible performance. Amazon CloudFront works seamlessly with Amazon Simple Storage Service (Amazon S3) which durably stores the original, definitive versions of your files. Like other Amazon Web Services, there are no contracts or monthly commitments for using Amazon CloudFront – you pay only for as much or as little content as you actually deliver through the service.
If you're using S3 and you're not using CloudFront, you should take a moment to check it out. You'll be surprised at how little work it takes to set up, how much it speeds up your assets serving, and how little it costs.
CloudFront is a part of the Amazon Console now, so it's very easy to set up. All you need to do is to create a distribution, which means enabling CloudFront for a specific S3 bucket and choosing a CNAME that you'll serve your assets from. Then, you need to set up the CNAME in your DNS configuration on GoDaddy and you're done.
The following two screenshots illustrate the process.
Step one is to creating the distribution in Amazon's Console:

Note the Domain Name and CNAMEs sections in the lower half of the screen. I've chosen the CNAME of "s3.kzak.org" because I want my S3 bucket to be aliased such that URLs will look like this:
http://s3.kzak.org/example.jpg
CloudFront has provided me with the domain name that I need to provide to GoDaddy. Since I'm using their "Total DNS" option, all I have to do is add the CNAME like so:

Notice that the CNAME of "s3" is set to the domain name that CloudFront provided me.
These changes seem to take about 30 minutes to percolate through the internets, but that's all it takes to get started with CloudFront.
For bonus points, you may want to read up about using multiple asset hosts in Rails and apply this technique in your applications for additional throughput.
Posted 38 minutes back at almost effortless
I just realized that I never posts about our entry into the Rails Rumble last year.
Flowcoder: An Evolution of the Code Snippet Site
Coded and designed by @gbuesing, @scottymac, and @trevorturk for @railsrumble in 2009.

Flowcoder has what you would expect from a code snippet side: multiple language support, raw code view, and support for embedding on other sites.
What was missing for us and what we really wanted was a site that featured not just the code, but the people creating the code. Just as we glean interesting tidbits about people's lives from Twitter, we wanted to learn from our favorite coders by being able to follow the kind of code snippets they create. We wanted to share our own code snippets and have others refactoring them: to fix, optimize, and make them better, and learn in the process. And we wanted to be kept informed: when your code is refactored on Flowcoder, you'll see an @reply from @flowcoderbot with some information and a link. This closes the loop in a casual, low bandwidth fashion and highlights the advantage of using Twitter as both an identity and notification system.
Posted about 5 hours back at Emphasized Insanity - Home
My lat ‘Bye Bye Github’ post caused a far more mess than i initially intended it will, my one and only goal by posting it was to express my thoughts as a user, thoughts which apparently came out a bit too harsh and i am sorry if it hurt someone, i wasn’t aiming for that.
I felt like it is necessary that i will explain things a little more and maybe put an end to this witch hunt that was swirling in both of Github’s direction and mine.
Most people came to realize somehow that i demand SLA for 7$/m, Well, i’m not. Although i do not hold the 200$/m plan on the other hand, i’d like to think that it’s reasonable to want leap in expected level of service once you start taking money from people, and again when you start hosting Mission Critical apps. It’s no secret that i am not the only one disappointed with Github’s uptime history. Yes, they always explain what caused the downtime and I’m glad that they do, But explaining what’s wrong isn’t enough, though.
They try, i know, they have the parts there that show that they really try to make things better, like DRBD, but when things go wrong everything breaks anyway. Basically it’s like making backups but never testing them, and that is the thing that annoys me the most, You can easily compare that to my mistake in my deployment process on those 3 projects that got delayed this week.
I am absolutely sure Github will get better, they have some awesome people working there and they are hosted in a wonderful place but it has nothing to do with the fact that i can always “go somewhere else where they have better uptime and reliability” until the reach my personal service requirement as a paid service.
Yes, it is my responsibility as a business owner to choose the right tools and craft the right processes in order to provide a sustainable toolset for my clients and team members.
All the backups in the world, 500 mirror sites and nothing else couldn’t have helped me get my deployments out because i needed a way to pull from the master, and because of my buggy process (weird situation as it is) regardless Github’s outage i was delayed by 2 hours.
The basic problem was the fact we work as an international team, although usually it works amazingly well. When you need a 24/h development cycle in your team, having 50% of the team still working when the other half is sound asleep in the other side of the world is a wonderful thing. The problem started when one on my Israeli developers (GMT – 5), had committed his last feature to master and acknowledged that i can issue a move to a staging server, ready to deliver a copy to the client as the contract expect.
Up until early this morning I didn’t keep the SSH keys for all the developers machines so when my developer went to his long overdue vacation (leaving the laptop at home obviously) i was left with no access to his local copy, Github being down, and overall stuck. Yes, this is a faulty project management. Yes it is already fixed in the form of adding another remote repository on CodebaseHQ and having all keys (except that guy’s) set on my machine as well.
Coming to think about it, even if the basic process error was indeed mine as a project manager, i expect a high service level from every service and get i pay for. This is why i am driving a mercedes and not on a bus, this is why i live in a house with impact windows and this is why i use a Mac and not Windows.
I can’t create a fault tolerant procedure for every in house project, it would cost a lot more than we can back up and i will spend a lot more time on it than working on our projects and this is why we pay 3rd parties to take those internal processes out of our hand and deliver us a product back.
I don’t see the reason of holding a double or a triple safety net for everything that we do in here, will i need 2 accountants now? a generator in addition to UPSs? it is very hard to draw the line where you fully trust a service you pay for and when you don’t and how you feel about it even.
Today, Github contact me to explain their side of the deal and also offered to park my account for a few months as an act of good service. Although it was very nice of them (as usual, their support was always awesome) i decided not to take it, keeping in mind it might seal this whole thing with an ugly stamp. Thank you Github, but we’ll just have to meet again in 3-6 months.
I hope this will bring an end to this whole thing, tomorrow it’s back to “Bag o Links” routine.
As a last note, I got all kinds of responses, thought it might help to clear those out:
“Git is decentralized, how did you screw that up?”
Yes, that’s true. i covered the reasons why it couldn’t have helped me in our specific situation.
Yes, we should have thought about it earlier and we’ll have to change that in order to make a smoother slide next time.
“He should have just installed Gitosis”.
Again, why should i bother when there are services our there offer to do all the hard work for us? assuming i ask one of our developers to install gitosis, being payed 75$/h it should take apprx 6 minutes a month to maintain it in order to match Github’s lowest offer. makes sense? not for me. some people, including me, prefer to pay money for a properly designed git workflow than to deal with the hassle of doing it themselves. I would happily pay Github even 4 times the current rates they are taking if i was certain it would grant me my peace of mind.
“Fix your grammar”
Sorry, not a native english speaker.
“If you want SLA, pay for it!”
I will, where?
Posted about 10 hours back at InfoQ Personalized Feed for unregistered user - Register to upgrade!
SapphireSteel Software, the developers of the Visual Studio based Ruby in Steel IDE have just released version 1.5. Among many improvements, they also dropped support for IronRuby. By Mirko Stocker
Posted about 11 hours back at Ryan's Scraps
For awhile I’ve wanted to move the “What’s New in Edge Rails” series to its own site to reflect the fact that it is an independent and self-sustaining series and not some small figment of my mind anymore. I started writing the What’s New series about four years ago and it’s clear it needs to be treated like a first-class citizen. While the move is still a work in progress, I’m proud to say that EdgeRails.info is now live and is where all future What’s New in Edge Rails content will be published (including some Rails 3 updates).
<image src="http://ryandaigle.com/assets/2010/2/5/edgerails.png" border="0" style="padding: 5px; float: right;" />
I won’t repeat too much here, but one of the big changes is that I want to take a much more community driven approach to bringing you the latest in updates to the framework and will be harnessing a GitHub-centric process towards letting you both contribute and update posts.
So update your feed and head over to EdgeRails.info. I’m all ears, so flame away if you’re feeling so inclined. And thanks for all your contributions, comments and feedback that past four years – they’ve made the work worthwhile and I hope I can continue the momentum on the new site.
I’ll probably give EdgeRails.info a few weeks to stand on its own before flipping the DNS switch, at which point all links to articles here will be redirected to EdgeRails.
See you on the flip side, home-slice.


Posted about 17 hours back at Railscasts
Get started with Rails 3.0 Beta and install Ruby 1.9.1 using RVM: Ruby Version Manager. Stay tuned to the end for a challenge on giving back to open source.
Posted 1 day back at Katz Got Your Tongue?
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.
<script type="text/javascript">
addthis_url = 'http%3A%2F%2Fyehudakatz.com%2F2010%2F02%2F07%2Fthe-building-blocks-of-ruby%2F';
addthis_title = 'The+Building+Blocks+of+Ruby';
addthis_pub = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12"></script>
Posted 1 day back at Katz Got Your Tongue?
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.
<script type="text/javascript">
addthis_url = 'http%3A%2F%2Fyehudakatz.com%2F2010%2F02%2F07%2Fthe-building-blocks-of-ruby%2F';
addthis_title = 'The+Building+Blocks+of+Ruby';
addthis_pub = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12"></script>
Posted 1 day back at Emphasized Insanity - Home
Being a software developer these days, is 90% about having a high quality of service, when you are becoming a serious part of this business you have to keep up with the expectations, especially if you are a providing an essential basic tool for developers all over the world.
I love Github, it’s a very simple tool and made it very easy to collaborate code, find open source projects you want to participate in and basically replaced the need to manage your own source control server.
Github are also offering a free account as we all know and their actual paid accounts are not that expensive and start from 7$ which gives you theoretically, a good bang for a buck.
But this is where the fun part ends.
As a business owner and a person that relays on services such as Github to provide efficient support and operation, i’ve decided based on the following week fiasco to drop my personal and Nautilus6 payed aacount on GitHub and look for an alternative.
This decision is based on my will to operate my business in a professional, coordinated and responsible matter and as i am responsible on getting things done in time for my clients, i am also obligated to make a right choice if i choose to use a 3rd party service such as Github.
It’s not a new phenomenon that Github goes down, and to be honest i don’t blame the hosting companies (EngineYard in the past and Rackspace at the momemt) since i am a loyal user of other large scale applications hosted successfully, silently and professionally in those companies.
I blame Github. And why? because Github acts like a toy, and when a service acts like a toy, it loses it’s right to be in my professional company toolset.
By saying “act like a toy”, i mean “not acting like a real, serious business”, a real serious business would have created an infrastructure that will provide paying customers a better redundancy for their accounts, a serious decision that would prevent my (and others) payed account to go down due to overload caused by free account, useless forks and god knows what.
I do not accept the excuse of “we have more users than we expected and when we had less it was fine” – that kind of stuff doesn’t work, someone should have thought about it before.
Taking the responsibility of being a serious service provider holds more to it than to have cute animal sketches pop up on your 500 error pages, and as much as i like that octu-cat or whatever it was, i like my happy clients more. But when in one way or another, i delayed 3 client deploys in the past week due to Github’s downtime, i see that this responsibility is not taken or taken for granted.
Some of you may say “so why don’t you use a local ssh deploy” or something like that, Why? simple. Because i pay Github, and i want to get the service i am paying for, and yes, i want the service i am paying for before free accounts get it.
As far as my public repositories, they will stay on Github unless something dead serious will happen (doubt it) and since i prefer not to manage our own git server at Nautilus6, i’d go for one of the following:
- Unfuddle – They also have some free accounts, give out both svn (yak) and git support. comes a long with a ticketing system as well.
- bitbucket – been hearing some good reviews on these guys, even cheaper than Github.
- Repository Hosting – one plan, all included. really looks good
- CodeBaseHQ – actually my favorite for now, simple, clean and fun.
- repo.or.cz – an open source project too, haven’t tried this one yet.
And i am not forgetting Heroku which proves to be an extremely reliable service and for some projects that’s all you really need, service and cost wise.
Posted 2 days back at Web 2.0 with Ruby on Rails
What do you get when the power of Ruby on Rails is combined with flexibility of Merb web framework? Rails 3 of course!
We have a very happy news: Rails 3 Beta is ready for testing. The improvements are numerous: ActiveRecord, ActionController, ActionView, and ActionMailer, ActiveSupport have all been redesigned. ActiveRecord got pimped with ActiveRelation scoped queries.
Some components have been refactored into their own: ActionDispatch, ActiveModel. Even better, all components can be used alone and you don’t have to require the entire Rails framework.
Rails is now not only Rack compatible, but subcomponents of Rails, like routing, are Rack middlewares.
Not to mention better dependency management system called Bundler, and improved performance especially on ActionView.
Read more detailed explanation on Yehuda Katz’s post:
http://www.engineyard.com/blog/2010/rails-3-beta-is-out-a-retrospective/
Will you upgrade to Rails 3?
No related posts.
Related posts brought to you by Yet Another Related Posts Plugin.


Posted 2 days back at Web 2.0 with Ruby on Rails
What do you get when the power of Ruby on Rails is combined with flexibility of Merb web framework? Rails 3 of course!
We have a very happy news: Rails 3 Beta is ready for testing. The improvements are numerous: ActiveRecord, ActionController, ActionView, and ActionMailer, ActiveSupport have all been redesigned. ActiveRecord got pimped with ActiveRelation scoped queries.
Some components have been refactored into their own: ActionDispatch, ActiveModel. Even better, all components can be used alone and you don’t have to require the entire Rails framework.
Rails is now not only Rack compatible, but subcomponents of Rails, like routing, are Rack middlewares.
Not to mention better dependency management system called Bundler, and improved performance especially on ActionView.
Read more detailed explanation on Yehuda Katz’s post:
http://www.engineyard.com/blog/2010/rails-3-beta-is-out-a-retrospective/
Will you upgrade to Rails 3?
No related posts.
Related posts brought to you by Yet Another Related Posts Plugin.
Posted 2 days back at Emphasized Insanity - Home
For my next project i have to use Facebooker, which is currently the most stable Ruby gem that wraps the Facebook API.
Sadly it’s very badly documented and for the past 2 projects i’ve been using it, i remember exactly why i don’t really like this library.
So why do i use it and don’t write our own implementation? we’ll we do. but it will take some time since the Facebook API’s own documentation is a world of pain and we are not going to make the same mistake again and make a library with poor documentation.
So for the meanwhile, i’ll just post some useful tips we find along the way and might help others getting things to work:
Tip #1: SessionExpired
Yeah, i posted how to handle Facebook’s stupid Session Expiry in a safe manner before, thought it worth mentioning again.
Tip #2: Test your Facebook application with Facebook
Oh this was hell, there was absolutely no documentation about how to mock a facebook user and API interaction if you use Cucumber. I did find this tutorial which, just doesn’t work.
So for example if we use this scenario:
<script src="http://gist.github.com/296758.js?file=manage_users.feature"></script>
And this is how the step goes:
<script src="http://gist.github.com/296758.js?file=user_steps.rb"></script>
Note the usage of User#facebook_user, which basically returns a Facebooker::User instance:
<script src="http://gist.github.com/296758.js?file=user.rb"></script>
Cucumber’s default environment
Cucumber runs on it’s own environment, default named Cucumber, so when you get something like that trying to run your features:
<script src="http://gist.github.com/296759.js?file=gistfile1.txt"></script>
All you need to do is just to add another environment named cucumber in config/facebooker.yml :
<script src="http://gist.github.com/296763.js?file=facebooker.yml"></script>
Posted 3 days back at InfoQ Personalized Feed for unregistered user - Register to upgrade!
Last week, InfoQ published a piece on YouTube offering HTML5 beta for its videos, in H.264 format. Shortly thereafter, Vimeo announced an HTML5 beta as well, also using H.264 as the video codec. However, Mozilla has come out against using H.264, whilst the recent iPad launch has focussed on the H.264 hardware decoding. Has Flash finally met its match? By Alex Blewitt
1 2 3 ... 317