View Source for Ruby Code

10:15 AM EDT Tuesday, May 6 2008

One thing that all web developers do at some is view the HTML source of the page your application has generated. The reason why is because what your web application does is dynamically generate HTML and you want to see what HTML it generated. You can think of Ruby, as a metaprogramming language, as a language that dynamically generates code. If you are doing Rails, you see this all of the time with association methods like has_and_belongs_to_many. What has_and_belongs_to_many does is generate methods on your class. For example, if you have an Product class that has_and_belongs_to_many categories, it will add a category_ids= method to your class. This all happens at runtime, so you can't see the method, but if you use Ruby2Ruby, you can. sudo gem install ruby2ruby and then run script/console at the root of your Rails app. Then just run these simple commands:

>> require 'ruby2ruby'
>> puts Ruby2Ruby.translate(Article)

The output will be the ruby code that your class now has. Somewhere in that code you will see:

def category_ids=(new_value)
  ids = (new_value or []).reject { |nid| nid.blank? }
  send("#{reflection.name}=", reflection.class_name.constantize.find(ids))
end

Which is the category_ids= method that was generated by has_and_belongs_to_many.

Posted in  | Tags Ruby2Ruby, Rails, Ruby | 0 Comments

Web Programming Languages and Frameworks are like Operating Systems and Editors

6:07 PM EDT Wednesday, April 30 2008

I've been doing some work recently with Facebook, building a Facebook app, and I have to admit that Facebook is a pretty well developed site. There is a lot of functionality. Things work pretty well, I've never gotten any errors while using the site. They've built a decent framework that allows people to develop their own apps for Facebook that work and feel like part of the rest of Facebook. It's fast enough, although not blazingly fast. And it's written in PHP.

I know PHP and know Ruby on Rails even better. If before Facebook came into existence, if someone approached me and explained what the idea for Facebook was, all the features they were planning on building, and they said they wanted to build it in PHP, I'd say you are nuts, building a site that complicated in PHP would be a nightmare. But obviously that wasn't a problem for the developers who built Facebook.

People talk about the question "Do languages matter?". You have some people expounding on the virtues of Lisp macros who will say absolutely and then you have others saying all languages are turing complete and there is basically no difference. Some people believe the Sapir-Whorf is true and applies to computer programming, others don't. But at the end of the day, there are good web applications built in PHP, Ruby, Java, .Net, Python, Smalltalk, Cold Fusion, etc. and there are bad web applications built in all of those languages, including Ruby on Rails.

So what can be taken away from that observation is that languages matter to programmers, in the same way that operating systems and editors matter to programmers. You can be productive developing web applications with Java and IntelliJ on Windows, Ruby on Rails on Mac OS X or Common Lisp and Emacs on Linux. The important thing is to find which combination makes you the most productive and then be part of a team that shares that mindset. That's not to say that all members of a team must use the same language, framework, OS and editor, but it is important for a team to share a common philosophy of software development. The language and framework that appeals to you individually is a strong indication of what your philosophy of software development is.

The fact is that I've found Ruby on Rails to be the best language and framework combination for me. If I am building a web application any level of complexity, I will be able to build it better and faster in Ruby on Rails than with PHP, Java or any other language and framework. But that applies to me and many other developers who have embraced Ruby on Rails, but not everyone and not for every web application. If you asked me to develop a web application in PHP instead of Ruby on Rails, that would be like asking Paul Graham to build a web application in Java using IntelliJ instead of Lisp and Emacs, or just as bad as the inverse, asking a Java developer to build a web application using Lisp and Emacs. I think in any of those cases, you'd end up with an inferior product than you would if you let each of those people use what they know and love best.

So based on that, from the perspective of a CTO trying to make a decision on which technology stack to adopt, you would say it doesn't matter. What matters is that you attract good developers. The key is being able to put together a team of good developers, regardless of the language. But the choice of language does matter because of the community surrounding a language. For example, I would imagine that putting together a team of good Cold Fusion developers would be difficult. For Java or .Net, there is an abundance of developers, but the challenge will be sifting through that abundance to find the truly good ones. This is one area where I believe Ruby on Rails has an advantage. If you could somehow determine the number of total developers for each language and the number good developers for each language, I think you would see that although there are less Ruby on Rails developers, a much higher percentage of them are good developers. I believe Ruby on Rails has a higher Good-Developer-to-Developer ratio than Java, .Net or PHP, and if finding good developers is your goal, that is the number you should care about.

Posted in  | Tags PHP, Ruby, Facebook | 0 Comments

What's to Like in Ruby 1.9

9:52 AM EDT Tuesday, April 29 2008

A few days ago, Charles Nutter asserted that "people are not flocking to Ruby 1.9 in droves". I would consider myself one of those people. When I thought about Ruby 1.9, I just assumed they were tweaking the syntax a little but mostly working on a VM that would make Ruby faster. Mainly though, Ruby 1.9 is an unstable, development release, so it's really just for playing around with it. The intent is for 1.9 to drive development for Ruby 2.0, and have people flock to Ruby 2.0 once that is ready for prime time.

Another factor is that up until today, I didn't really know much about what is planning on being added to Ruby 1.9. There is a complete list of changes in Ruby 1.9, but it wasn't until I came across a slideshow by Bruce Williams that covers some of the changes in Ruby 1.9 that I took the time to download, install and try out a few new features. So I thought I would put together a blog entry of 5 of my favorite changes:

  1. New Literal Syntax for Hashes

    {:foo => 1, :bar => "two"} now becomes {foo: 1, bar: "two"}. This is probably minor, but I really like it. It's a little bit cleaner, although I'm sure Obie will be sad to see the hash rocket go. Actually, I'm sure the hash rocket will still be supported, it will just become no longer idiomatic.

  2. New Proc literal

    But fear not Obie, we lose one operator, the hash rocket, but gain another, the proc rocket. You can now define a proc like this:

    double = ->(x) { x * 2 }
    puts double.(5) # => 10
    

    That can lead to some pretty crazy things, like this:

    p = ->(n, name="it", &block) {
        n.times{|i| block.call }
        puts "I did #{it} #{n} times"
    }
    
    
    p.(3) do |i| 
      puts "#{i} is #{i.even? ? 'not ': ''}odd"
    end
    
    
    p.(3, "foo") do |i| 
      puts "#{i} is #{i.even? ? 'not ': ''}odd"
    end
    

    The difference being that you can now have default values for arguments to a Proc and also you can pass a Block to a Proc. I could see this being used in metaprogramming. You could probably do a lot of things with this instead of things that get done using class_eval now.

    #Ruby 1.8
    class Foo
    end
    Foo.class_eval <<-CODE
      def bar(x,y=2)
        puts "x => \#{x}, y => \#{y}"
      end
    CODE      
    
    
    #Ruby 1.9
    class Foo
    end
    Foo.send(:define_method, :bar, ->(x, y=2) { 
      puts "x => #{x}, y => #{y}" 
    })
    

    Not sure yet if that would be better, I guess we'll see.

  3. Hashes preserve insert order

    Say goodbye to using 2D arrays just because you want things to be in a certain order. This is very convenient, but I was always under the impression that this is the way it was for performance reasons. I'd like to hear more about this. Is this one of those things where 80% of the time you don't care about that level of performance because your hash is relatively small and the convenience of preserving sort order is a better benefit? Is there some kind of FastHash class that can be used for cases where you don't care about ordering and better performance is needed? Or is the performance of the insertion-order Hash good enough for all cases?

  4. New Regular Expression Engine

    The Oniguruma regular expression engine is used in Ruby 1.9. This engine supports many advanced regular expression features. I once looked into directly porting the Perl Markdown code into Ruby but quickly found out that wasn't possible given the limitations of the Ruby 1.8 regular expression engine, so it's nice to see Ruby will have a regular expression engine that is on par with that of any other language.

  5. Object#tap and Symbol#to_proc

    I lumped these together into one because they are both kind of the same thing. These are two language level features that have become idiomatic Ruby because they have been added in Rails. The downside has been that if you are not in Rails, you either don't have these, or you have to define them to use them. Now that is a problem no more and they are just going to be part of Ruby. Symbol#to_proc you should recognize and Object#tap is the same thing as returning.

Posted in  | Tags Ruby | 3 Comments

Displaying error messages in RSpec failures

6:30 PM EDT Wednesday, April 23 2008

The suggested way of checking if an ActiveRecord model has errors with RSpec is:

@something.errors.should be_empty

When that fails, you get a report that says:

expected empty? to return true, got false

That's not very helpful because it doesn't tell you what the errors are. If you do this:

@something.errors.full_messages.should == []

You get a more informative failure message:

expected: [],
got: ["Whatever can't be blank"] (using ==)

Posted in  | Tags RSpec, Rails, Ruby | 3 Comments

Adding Columns to Tables with the Migration Generator

12:11 PM EDT Monday, April 21 2008

I just stumbled upon a neat little Rails feature and figured I'd share with the world. I'm working on a Facebook application and I'm going through some of the examples in Developing Facebook Platform Applications with Rails. In chapter 4, one of the tasks is:

Let's add a boolean hit column to our attack model. I'll wait while you create that migration.

It doesn't tell you how to do that, which I like. This is a simple enough task the reader should be able to do in their own, no need to clutter up the book with the code.

So I set out to do that, but for whatever reason my mind is in a bit of a fog today. I don't what it is, I've been making an inordinate number of typos. So when my fingers went to type the command to generate the migration, I just instinctively did this:

script/generate migration add_hit_to_attack hit:boolean

I accidentally added the hit:boolean column specification as if this were a script/generate model Whatever command. But it turns out Rails is able to read my mind. I opened up the migration file that was generated and there was this:

class AddHitToAttack < ActiveRecord::Migration
  def self.up
    add_column :attacks, :hit, :boolean
  end

  def self.down
    remove_column :attacks, :hit
  end
end

The code to add the column was already there. I checked the docs and sure enough there is support for this naming convention:

You can name your migration in either of these formats to generate add/remove
column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable

Example:
`./script/generate migration AddSslFlag`

With 4 existing migrations, this creates the AddSslFlag migration in
db/migrate/005_add_ssl_flag.rb

`./script/generate migration AddTitleBodyToPost title:string body:text published:boolean`

This will create the AddTitleBodyToPost in db/migrate/005_add_title_body_to_post.rb with
this in the Up migration:

  add_column :posts, :title, :string  
  add_column :posts, :body, :text  
  add_column :posts, :published, :boolean

And this in the Down migration:

  remove_column :posts, :published  
  remove_column :posts, :body  
  remove_column :posts, :title

Posted in  | Tags Rails, Migrations, Ruby | 0 Comments

<< Previous Page    Next Page >>