Come see me at OSCON 2008

(cross posted from http://brionesandco.com/ryanbriones/2008/07/come-see-me-at-oscon-2008.html)

If you see me this week, please come up and chat for a bit! If you’re even more adventurous, come and see one of my talks:

Hooks and Classes

After watching episode 6 “Some Hook Methods” of the Pragmatic Screencasts of The Ruby Object Model and Metaprogramming with Dave Thomas I wrote some methods for Class.


class Class
  def inherited(subklass)
    puts "class #{subklass.inspect} desends from #{self.inspect}" 
  end

  original_new = instance_method(:new)

  define_method(:new) do |*args|
    puts "#{self}.new called" 
    original_new.bind(self).call(*args)
  end

  class << self
    original_new = instance_method(:new)

    define_method(:new) do |*args|
      puts "#{self}.new called with #{args.inspect}" 
      original_new.bind(self).call(*args)
    end
  end
end

What happens in IRB?


~ irb -r class.rb
IRB::Irb.new called
IRB::Context.new called
IRB::WorkSpace.new called
IRB::ReadlineInputMethod.new called
IRB::StdioOutputMethod.new called
RubyLex.new called
IRB::SLex.new called
IRB::SLex::Node.new called
IRB::SLex::Node.new called
IRB::SLex::Node.new called
# ... 72 lines of "IRB::SLex::Node.new called" 
IRB::SLex::Node.new called
IRB::SLex::Node.new called
IRB::SLex::Node.new called
>>

That’s quite a lot of nodes.

Let’s see what happens when classes are created.


>> class Q;end
RubyToken::TkCLASS.new called
RubyToken::TkSPACE.new called
RubyToken::TkCONSTANT.new called
RubyToken::TkSEMICOLON.new called
RubyToken::TkEND.new called
RubyToken::TkNL.new called
class Q desends from Object
=> nil
>> Class.new(Q)
RubyToken::TkCONSTANT.new called
RubyToken::TkDOT.new called
RubyToken::TkIDENTIFIER.new called
RubyToken::TkLPAREN.new called
RubyToken::TkCONSTANT.new called
RubyToken::TkRPAREN.new called
RubyToken::TkNL.new called
Class.new called with [Q]
Class.new called
class #&lt;Class:0x53c654&gt; desends from Q
=> #&lt;Class:0x53c654&gt;

The new method is not used to create every object.


>> [nil]
RubyToken::TkLBRACK.new called
RubyToken::TkNIL.new called
RubyToken::TkRBRACK.new called
RubyToken::TkNL.new called
=> [nil]
>> Array(1)
RubyToken::TkCONSTANT.new called
RubyToken::TkLPAREN.new called
RubyToken::TkINTEGER.new called
RubyToken::TkRPAREN.new called
RubyToken::TkNL.new called
=> [1]
>> Array.new(1)
RubyToken::TkCONSTANT.new called
RubyToken::TkDOT.new called
RubyToken::TkIDENTIFIER.new called
RubyToken::TkLPAREN.new called
RubyToken::TkINTEGER.new called
RubyToken::TkRPAREN.new called
RubyToken::TkNL.new called
Array.new called
=> [nil]

This has been an exercise into hooks and to see what classes are created.

Easier Capistrano Deployments from Github

A couple of weeks ago we at Edgecase decided that we would like to start using Github as our main repo for our git versioned projects. I really wanted to take advantage of the great user experience and the administration aspects that Github had to offer. As we started the process of moving our projects to Github we ran into a bit of an issue that took a little “tweaking” to get right, but in the end I think we came out with nice solution.

Github provides you the concept of “deploy keys”, SSH public keys which essentially provide the user of this key pair read-only access to your project. For simple deployments this is perfect. There’s a bit of a catch though: deploy keys must be unique from project-to-project and they must not collide with any user key on all of Github. At first this wasn’t a problem. We were initially using Github for some project specific gems and it worked fine. However when we started deploying applications we ran into a couple issues:

  1. For most of our projects, we work from one staging server running multiple applications. The project-to-project uniqueness of keys constraint is then a problem.
  2. Our current projects use gems/plugins that we’re hosting on Github. The same project key constraint applies here too.

Using Google as my guide, I managed to find a few ways that didn’t work.

  • Using a specially crafted .ssh/config on the server. Since the hosts aren’t unique per project, configuring your ssh client to respect different key files for each project seems impossible.
  • Being able to choose a specific public key to use with git at runtime. This seems like it should be possible, but I was unable to find any reference to it.

The solution I ended up with I had actually tried on the “specially crafted .ssh/config” attempt, but I was missing a key step when running on OS X Leopard. SSH Agent Forwarding1 to the rescue! This solution is actually really nice because it means that making the server deployable requires zero configuration because it’s likely that the person that is deploying the application already has public key access to the repo. There’s two ways to you can go about doing this. The first requires having each user that needs to deploy edit their .ssh/config like so:

Host serveriamdeployingto.com
    ForwardAgent yes

But that requires a lot of manual editing of files. With Capistrano, we can make this simple for everyone by adding the following line to your deploy config:

set :ssh_options, {:forward_agent => true}

Unfortunately, and I can’t speak for Linux or Windows, but for OS X Leopard there’s one more thing that needs to be done. For what I have to assume are “security purposes” the ssh-add command needs to be run every time that you reboot. For those of you trying to beat the record for longest uptime, it occurs to me that you may need to run ssh-add after a certain amount of time (the man page makes references to key lifetime), but I haven’t run into this issue personally. Luckily Capistrano 2.x’s event callbacks provide an easy way to ensure we have the key in our agent by adding the following to our deploy config:

on :start, :run_ssh_add
task :run_ssh_add do
    `ssh_add`
end

# or more simply

on :start do
    `ssh-add`
end

Badda bing! You’re deploying from Github hopefully with zero issues.

1 http://www.unixwiz.net/techtips/ssh-agent-forwarding.html#fwd – “An Illustrated Guide to SSH Agent Forwarding”

Meta Meta

After watching the Pragmatic Screencasts of The Ruby Object Model and Metaprogramming with Dave Thomas a few of us at the office decided to investigate further.

Developers in the Ruby on Rails community are familiar with the concept of constructing custom finders for models.

class User
  class << self
    def find_by_geography(options)
      # ... custom geographic finder logic ...
    end
  end
end

One invokes method name find_by_geography directly from the User class.

@users = User.find_by_geography(options)

A programmer can alternately prepend self. to the method name.

class User
  def self.find_by_geography(options)
    # ... custom geographic finder logic ...
  end
end

And the method is called in exactly the same fashion.

@users = User.find_by_geography(options)

QUESTION: What is the nature of a method that employs both the self. and the class << self constructs?

The terms metaclass, eigenclass, shadow class, virtual class, or ghost class have been used to refer to the anonymous singleton class in between every object and its class in Ruby. This article will use the term “metaclass.”

How does one access the metaclass? The following defines a method metaclass for every object.

class Object
  def metaclass
    class << self
      self
    end
  end
end
>> cat = 'miaow'
=> "miaow" 
>> cat.metaclass
=> #<Class:#<String:0x525670>>
>> cat.metaclass == cat.class
=> false

Another useful method definition for this article follows.

class Object
  def metaclass?(object)
    self.metaclass == object
  end
end
>> x = cat.metaclass
=> #<Class:#<String:0x525670>>
>> y = 'not cat'.metaclass
=> #<Class:#<String:0x586970>>
>> z = cat.metaclass.metaclass
=> #<Class:#<Class:#<String:0x525670>>>
>> cat.metaclass?(x)
=> true
>> cat.metaclass?(y)
=> false
>> cat.metaclass?(z)
=> false

Let us see an example of a class-level method definition and a self. method definition also declared at the class-level.

class A
  class << self
    def b
      self
    end

    def self.c
      self
    end
  end
end

Two questions come to mind: “How do I call those methods?” “What do they return?”

The answers to method b are easy enough.

>> A.b
=> A
>> A.b == A
=> true

The method b is called from class A. It returns class A.

>> A.b.b.b.b.b.b
=> A

How does one invoke the other method?

>> A.c
NoMethodError: undefined method `c' for A:Class
>> A.metaclass.c
=> #<Class:A>
>> A.metaclass?(A.metaclass.c)
=> true

The method c is called from the metaclass of A. It returns the metaclass of A.

>> A.metaclass.c.c.c.c.c.c
=> #<Class:A>

Let us observe inheritance and if method self.c is inherited.

class B < A
end
>> B.b
=> B
>> B.b.b.b.b.b.b
=> B
>> B.c
NoMethodError: undefined method `c' for B:Class
>> B.metaclass.c
NoMethodError: undefined method `c' for #<Class:B>

Nope.

ONE MORE META

What is the nature of a method that employs both the self. and the class << self constructs and returns self within another class << self construct?

Perhaps a code example is better

class A
  class << self
    def self.meta_metaclass
      class << self
        self
      end
    end
  end
end

Hmmm… that’s a little hard to read. The following should be a little better.

class A

  class << self

    def b
      self
    end

    def self.c
      self
    end

    def self.meta_metaclass
      class << self
        self
      end
    end

  end

end

Since is has similar method defintion to self.c it is most probable that self.meta_metaclass is called the same way.

>> A.metaclass.meta_metaclass
=> #<Class:#<Class:A>>

Yes!

Now for the other question: What is returned?

>> mm = A.metaclass.meta_metaclass
=> #<Class:#<Class:A>>
>> A.metaclass?(mm)
=> false
>> A.metaclass.metaclass?(mm)
=> true

The method self.meta_metaclass returns the metaclass of the metaclass of A

CONUNDRUMS

~ irb -r meta.rb
>> String.metaclass.superclass
=> #<Class:Class>
>> Class.metaclass.superclass
=> #<Class:Class>
>> Object.metaclass.superclass
=> Class

What?

~ irb -r meta.rb
>> Class.metaclass.superclass == Class.metaclass
=> true
>> Class.metaclass.superclass
=> #<Class:Class>
>> Class.metaclass.metaclass.superclass
=> #<Class:#<Class:Class>>
>> Class.metaclass.superclass
=> #<Class:#<Class:Class>>
>> Class.metaclass.superclass == Class.metaclass
=> false

What? What?

~ irb -r meta.rb
>> A.metaclass.c.meta_metaclass.c.meta_metaclass
=> #<Class:#<Class:#<Class:A>>>
>> A.metaclass.c.meta_metaclass.c.meta_metaclass
NoMethodError: undefined method `c' for #<Class:#<Class:A>>
        from (irb):2

What? What? What?

If you answer, truly you have a dizzying intellect.

Everyday DTrace with OSX (Slides)

Before we head out I wanted to post the slides from our Everyday DTrace talk. You’ll find a link to our code (zip) and slides below.

Everyday DTrace pdf

D Examples

It's all about the Edge Cases

Today at lunch we had a conversation about the "Steve Rule."

What's the "Steve Rule"?

In any group of technology professionals, there will generally be more white males named Steve than there are people of any other minority.

But we don't have anybody named "Steve" at work.

This is an edge case.

Everyday DTrace on OSX subject of Barron/Humphries Presentation

(RailsConf - Portland, Oregon, May 29 to June 1, 2008)

Ruby on Rails experts Chad Humphries and Scott Barron will be presenting at RailsConf, the largest official Rails conference, in Portland, Oregon.

In their fourty-five minute presentation Barron and Humphries will provide a good day-to-day guide on how to best use DTrace on OSX Leopard to debug, profile, and gather more information about applications.

Humphries is a principal at EdgeCase, an 11-person Ruby software development firm based in Columbus, Ohio. In the past he worked with .NET and Java with Fortune 500 companies to help them evaluate and implement open-source technologies. He works in the Ruby open-source community on projects such as RSpec, and RubyFurnance.

Barron, a Rails Core Team member, is also active in the open-source community working on acts as state machine, RGTE, The Ruby DTrace Patch, and RTrace.

EdgeCase provides a full range of software development and mentoring services.

Capistrano 2: In the Wild

(cross posted from brionesandco.com/ryanbriones)

About 29 days late I suppose. Better late than never.

This presentation was given at the Columubs Ruby Brigage on November 19th, 2007. Enjoy!

CRB_2007.11_Capistrano2.pdf

Testing Javascript

Javascript is of pivotal importance to a modern web application. Page behavior done with Javascript is often requisite of client acceptance. So why don’t we test our Javascript with the same diligence as we do our server side application code?

The biggest barrier standing in the way of testing Javascript seems to be the initial entry. In Ruby on Rails, we get provisions for testing virtually for free. Test::Unit is built into Rails, and other tools like rspec and rcov are easy to install. Javascript testing does not have the same pervasiveness, and as a result there are few tools out there to help us get started.

I recently wanted to use Ryan Johnson’s Event.Behavior in a personal project of mine, but as the library is untested if I use it as is I will have no confidence in the behavior of the application. Check back here over the next couple weeks as I’ll be working on a Javascript centric Rails app and I will be posting what I hope to be a how-to guide to get started testing Javascript in Rails painlessly.

Scott Barron joins EdgeCase

(cross posted from objo.com)

One of the great things about starting a company is the ability to team up with some of the best talent you can find. It’s a nice feeling to be extremely excited when you hire someone. Every time we have brought someone on, I’ve wanted to tell the world. It’s a fantastic feeling.

We are extremely excited to welcome Scott Barron to EdgeCase.

Scott is a member of the Ruby on Rails Core Team, avid twitter monkey (although we will have to work on his nic), and incredible developer. We are looking forward to not only working with him, but helping him with his incredible contributions to the open source community.

Scott lives (and will remain) in Cincinnati. We have worked hard on creating an environment that allows us to pair-program even if the person is remote. It works really well for Jim and I. With video skype, we are able to feel as if the person is right there, combine it with ssh + screen + emacs and it’s no different than sitting in the same room.

Welcome Scott!

EdgeCase presenting Pragmatic Studio

(cross posted from objo.com)

Jim Weirich and Joe will be teaching a Pragmatic Studio on Testing Rails in Columbus Ohio, October 17-19.

We are preparing some fantastic content to help show attendees what TDD is all about, as well as how to get the most out of your testing. This is as much how to test correctly as it is about how to test Rails specifically. We are taking our years of testing experience in and out of Ruby and showing you how we apply it to Ruby and Rails. We will show you how to test as individuals and in your teams.

We have learned a lot at EdgeCase over the past year about specifics of testing Rails applications, and especially about the fantastic RSpec framework. You get the benefit of having all of the things we have learned the hard way wrapped up in a nice, neat package.

Nicole and Mike have put together a fantastic program with the “Pragmatic Studio” brand and we are honored to be a part of it.

What are you waiting for, register now!

erubycon Sessions Announced

We have finally posted the session list for erubycon.

We will be having two tracks and have some incredible talks to choose from. Stay tuned for the exact schedule. Some of the topics we are covering:

  • Data Warehousing
  • Large Teams and Rails
  • JRuby, the DLR and other alternative platforms
  • Security
  • Domain Specific Languages

What are you waiting for? Register soon while we still have space.

Come be a part of the first Enterprise Ruby Conference. It’s being held n Columbus Ohio July 16, 17 & 18. Come get all the ammunition you need to convince your boss to take a good, hard look at Ruby. Maybe you too could be coding in Ruby this year!

RSpec 1.0 Released...

We were privileged enough to be around during RailsConf to support David, Brian, and Aslak during there final push to 1.0. They have been putting in countless hours driving this excellent tool toward this significant milestone.

Congrats to the RSpec team!!!

Interesting Enterprise Ruby Announcement

(cross posted from objo.com).

So I thought it a bit odd to run into Roy, the founder of ThoughtWorks upon my arrival to RailsConf today. I then get to the speakers lounge, register and find a two page spread announcing not only mingle but also the most interesting announcement of all:

Today ThoughtWorks Studios introduces the convenience, power and flexibility of Ruby / Ruby on Rails to Fortune 1000 companies.

RubyWorks is what appears to be ThoughtWorks supporting Ruby for the Enterprise. To say this is huge would be a drastic understatement. ThoughtWorks is releasing a production LAMP stack for Ruby on Rails that’s designed for both Red Hat Enterprise and CentOS (think free version of RedHat). According to their website, beginning in July they will begin offering 24×7 paid support. This is putting you money where you mouth is.

RubyWorks – a new products and support service for Ruby. Designed to help enterprises implement and use Ruby more effectively …

EdgeCase is pushing the meme of Enterprise Ruby with erubycon, and now ThoughtWorks is getting behind it with full support.

This is going to be a stellar year.

New site released

While the blog still needs some work, you will notice that we have released our new site. We have worked very hard on this over the last few months. Hope you like it.

As always, feedback is welcome