“A Little Ruby, a Lot of Objects,” back on line

When I was first learning Ruby, one of the resources that helped me most was Brian Marick’s “A Little Ruby, a Lot of Objects.” It’s modeled after The Little Schemer (or, if you’re older, The Little LISPer), but it uses Ruby, and teaches the core ideas of object-oriented programming in a way that helped me, even after I’d been doing OOP for 6 years. (I’m not surprised that his newer book, Functional Programming for the Object-Oriented Programmer, is just as illuminating.) The only thing I didn’t like was that it stopped after only 55 pages.

My team is about to welcome a new junior intern, and when Ben asked me for any learning resources I thought we should send, I suggested “A Little Ruby.” I have the original PDFs, but we were planning to send an email with URLs, and that’s when I realized that the book’s site, visibleworkings.com/little-ruby, was down.

I asked Brian whether I could host the files, and he agreed (thanks again!), so here they are:

A Little Ruby, A Lot of Objects

Front Matter

“My goal is to teach you a way to think about computation, to show you how far you can take a simple idea: that all computation consists of sending messages to objects.”

“The real reason for reading this book is that the ideas in it are neat.”

Chapter 1: We’ve Got Class…

The First Message: Computation is sending messages to objects.

The Second Message: Message names describe the desired result, independently of the object that provides it.

The Third Message: Classes provide interface and hide representation.

Chapter 2: …We Get It From Others

The Fourth Message: Protocols group messages into coherent sets. If two different classes implement the same protocol, programs that depend only on that protocol can use them interchangeably.

The Fifth Message: Classes define protocols for their subclasses.

The Sixth Message: If a class and its superclass have methods with the same name, the class’s methods take precedence.

The Seventh Message: Instance variables are always found in self.

Chapter 3: Turtles All The Way Down

The Eighth Message: Classes are objects with a protocol to create other objects

The Ninth Message: Methods are found by searching through lists of objects.

The Tenth Message: In computation, simple rules combine to allow complex possibilities

The Eleventh Message: Everything inherits from Object.

RubyNation 2013 In Review

RubyNation 2013 is done! Outside of un-confs like BarCamp, it was the first conf I’ve presented at. I was nervous, so I kept practicing and smoothing the slides, and I think that helped a lot – everyone seemed to like the talk. Thanks again to everyone who came to hear it!

RubyNation was a smaller conference. Someone said they felt as though you could almost talk to every attendee, or at least recognize them all by face. It felt comfortable and familiar. But I think there was more to that than just being small – I think the organizers made some particular choices that made it that way.

First, rather than rows of chairs, they provided banquet-style round tables with about 10 chairs each. This is really good for getting people talking: you have a handful of neighbors, and you’re all facing each other. It’s much more social than 2 neighbors and the back of someone’s head. It does mean that half the table has to turn around to watch the talks, but in practice, it wasn’t a problem. Whatever extra floor space the round tables took up was worth it.

Second, rather than catering lunch, each conf organizer paired with a speaker to lead the way to a different nearby restaurant. Attendees got to pick which group they would go with. Splitting into so many groups meant there was a good chance you’d eat your lunch chatting with a speaker or organizer. It also meant you had much more choice over what to eat. (Remember RailsConf 2012, when they served pot pies every single day?)

Rails Girls DC was there in force. I’m not sure, but I think this was the first time RubyNation was paired with a Rails Girls DC training day. It was great to see so many people new to the community, discovering ruby and programming, and I think the variety of talks must have complemented the more-focused training day very well.

For a first-time speaker, it was a very welcoming, laid-back group – though, as Sandi Metz helpfully warned me ahead of time, they might not laugh too loudly at your jokes. If you’ve never given a talk at a conference, try starting with RubyNation.

I’m Speaking at RubyNation 2013!

This weekend, I’ll be giving a talk at RubyNation 2013, titled “Object-Functional Fusion in Ruby.”

While Ruby is a great object-oriented language, its functional aspects are a bit less-appreciated. But it’s no Haskell: if you try to go full-on-functional, you’ll run into headache and heartache. I want to talk about some ways to fuse the two approaches.

Come say hello!

ERMAHGERD, the Gem

I just published my first “official” gem, ermahgerd, and what an auspicious way start my gem-author career! ERMAHGERD, I’M A RERL RERBER PRERGRERMAHR!

It’s (currently) totally based on J Miller Design’s translator, but there are some bits I’d like to tweak. We’ll see, it’s just for fun.

Get started with ERMAHGERD:

$ gem install ermahgerd
$ irb
ruby-1.9.3-p0 :001 > require 'ermahgerd'
 => true 
ruby-1.9.3-p0 :002 > Ermahgerd.translate("Goosebumps, my favorite books!")
 => "GERSBERMS, MAH FRAVRIT BERKS!" 

Rails 3: Selectively Override Email Recipients

It’s a common thing, in your test environments, to intercept out-going email, and stuff it in some dumpster out back, so you don’t bother your users. We do this at SeeClickFix, and we’re upgrading to Rails 3, so I went searching for the new way to do this, and found Rob Aldred’s handy post on the subject.

So we deployed our Rails 3 branch to a test environment & unleashed our QA staff on it, but they all knew that they’d never get email from that environment, so they never checked for them. Which was a problem, because all the email were broken in QA. Oops.

It’d be nice to only dump certain messages (the ones to your normal users) and let through others (the ones to your QA staff). Can we do this? Let’s see.

ActionMailer::Base lets you register an interceptor, and every time it’s about to send an email, it’ll call your interceptor’s #delivering_email method with the email as an argument. All the examples I found register a class as an interceptor, with #delivering_email implemented as a class method, like this:

class FooInterceptor
  def self.delivering_email(message)
    message.to = "dump@example.com"
  end
end

ActionMailer::Base.register_interceptor(FooInterceptor)

Now that’s fine, but why pass a class with a class method? Why not an object with an instance method? Especially since a class is just an object, an instance of Class. Will ActionMailer::Base#register_interceptor do something funny with its argument? Try to call #new on it? Who knows?

I tried this just to see if it would work:

class FooBarRecipient
  def delivering_email(message)
    message.to = "dump@example.com"
  end
end

ActionMailer::Base.register_interceptor(FooBarRecipient.new)

And it does! Nice job, register_interceptor, not doing anything funky with it. Thanks!

This means we can create an interceptor object with a whitelist:

class WhitelistInterceptor

  def initialize(whitelist)
    @whitelist = whitelist
  end

  def delivering_email(message)
    message.to = Array(message.to).map { |address|
      if @whitelist.include?(address)
        address
      else
        "dump@example.com"
      end
    }
  end

end

Of course that’s really basic – you probably want to allow all email sent to your domain, for instance. And maybe you want the messages to be tagged somehow, so you can tell which test environment a message came from, so you give the WhitelistInterceptor the Rails environment to add as a message header. But that’s the idea. And my favorite part is that the class has no Rails dependencies, so it’s trivial to test.

Is there any reason not to do this?

Out of Love with Active Record

(I’m a new-comer to Rails. When I first found Ruby, and Rails, I liked the Ruby better. And I never found many Rails jobs near home anyway. So for years, Ruby flavored my C#, and C# is where I learned, among other things, to persist my domain aggregates with NHibernate. Now I’m a card-carrying Rails jobber, which is great, because I play with Ruby all day. And the Rails community is discovering domain-driven design, and ORMs…)

Steve Klabnik just posted about resisting the urge to factor your models into behavior-in-a-mixin and dumb-persistence-with-active-record. He nails it when he says:

Whenever we refactor, we have to consider what we’re using to evaluate that our refactoring has been successful. For me, the default is complexity. That is, any refactoring I’m doing is trying to reduce complexity… One good way that I think about complexity on an individual object level [is its] ‘attack surface.’ We call this ‘encapsulation’ in object oriented software design.

If you learn only one thing from his post, let it be that “mixins do not really reduce the complexity of your objects.” Greg Brown threw me when he said that mixins are just another form of inheritance, and I think he was getting at the same thing.

Steve’s suggestion for separating persistence and behavior is to – duh, once you see it – separate them into different classes: a Post and a PostMapper, or a Post and a PostRepository. When I used C# and NHibernate, we loaded our Posts from the PostRepository, which used our PostMapper for data access. (Actually, our PostMapper was an XML mapping file.) You might call that overkill, but in a legacy app, it was nice to sheetrock our repositories over all the different data access technologies we’d acquired over the years, from the shiny new ORM to the crusty old Strongly-Typed DataSets.

When I was on that team, the thing that we worried about was, what grain should we build our repositories at? We didn’t have simple models, we had domain aggregates: we’d load a ThirdPartyAdministrator, which had many Clients, which each had a number of Accounts of different types, each of which had different options and sub-objects. So, what kind of repositories should we build, and what methods should they have? If we want to load the Client’s Accounts, should we load the ThirdPartyAdministrator, find the Client, and get its Accounts? load the Accounts directly? load the Client, and get its Accounts?

For a ridiculously simplified example, but to give you the flavor of it, say we load the ThirdPartyAdministrator, the aggregate root, and go from there:

class ThirdPartyAdministratorRepository
  def load_tpa(id)
    ...
  end
end

tpa = ThirdPartyAdministratorRepositor.load_tpa(42)
client = tpa.clients[client_id]
accounts = client.accounts

That’s too coarse; do we really have to load the TPA before we can get the client we’re after?

class ClientRepository
  def load_client(id)
    ...
  end
end

class AccountRepository
  def load_account(id)
    ...
  end
end

client = ClientRepository.load_client(client_id)
accounts = client.account_ids.map { |id|
  AccountRepository.load_account(id)
}

That’s too fine a grain, too low-level; we don’t want to have to muck around with Account IDs.

client = ClientRepository.load_client(client_id)
accounts = client.accounts

That might be a good middle-approach.

It comes down to knowing your application’s data-access patterns, and your domain’s constraints. If you often need a chunk of data, all together, you should probably have a repository for it. If one piece of data depends on another, your repository probably shouldn’t make you get them separately.

With Rails’ ActiveRecord, all this is sorted out for you – you define your associations, it provides all those querying methods, and you use the correct ones for what you need. With repositories, you have decisions to make – you have to design it, and design is choice. But choosing is work! and you can choose inconsistently! sometimes, it even makes sense to! I’m curious to see how the Rails community, with its culture of convention, tackles this. And for myself, I plan to check out DataMapper at some point.

Come to the Hartford Ruby Brigade’s January Meeting

As we trudge back to our regular schedules after assorted holiday debaucheries, here’s a heartening thought: Hartford.rb is meeting on Monday, 1/26! Gary Wright will tell us the story of how he learned Git, and some lucky stiff will walk away with a free copy of The Rails Way. We’ll even have pizza — though we’re now on the look-out for a pizza sponsor, so if you know anyone looking to feed us (for only ~$50 a month!), it might even be free.

The usual details:
Monday, 1/26, 6 – 8 PM
GeeZeo
750 Main St, Hartford

See you soon.

Next Hartford Ruby Group meeting: 11/24

The Hartford Ruby Group is meeting this Monday, 11/24, from 6 – 8 PM.

Flinn Mueller will be talking about rspec, and we’ll hopefully hear stories from the Voices that Matter attendees.

We’ll raffle off The Professional Ruby Collection: Mongrel, Rails Plugins, Rails Routing, Refactoring to REST, and Rubyisms CD.

GeeZeo offices
750 Main St, Hartford
Suite 1314
(next to the CVS)

Thanks to GeeZeo for hosting us, to Sun for feeding us, and to Addison Wesley for giving us books to raffle off. Hope to see you there!

Hartford Ruby Brigade next meeting: 10/27

The Hartford Ruby Group is meeting this Monday, 10/27, at 6:00 PM.

We’ll be tackling a Ruby Quiz problem, pairing up newcomers with veterans, and we’ll be raffling off a copy of Design Patterns in Ruby, by Russ Olsen.

GeeZeo offices
750 Main St, Hartford
Suite 1314
(next to the CVS)

Thanks to GeeZeo for hosting us, to Sun for feeding us, and to Addison Wesley for giving us books to raffle off.  Hope to see you there!

Hartford Ruby Brigade meeting tonight

If you’re in the area, feel free to drop in:

The Hartford Ruby Brigade’s September meeting is tonight, from 6 to 8 PM, at GeeZeo’s offices on 750 Main St, Suite 1314, in Hartford (next to the CVS).

The big news is Addison Wesley has a ticket for the Voices That Matter: Professional Ruby Conference this November, and we’ll raffle it off. It looks like a sweet conference, go take a look. You have to be there to win, so if you’ve been waiting for the right time to make an appearance, this is it. And since only one of us can win the ticket, we’ll also raffle off a great Ruby book, Hal Fulton’s The Ruby Way. A big thanks to Addison Wesley!

Aaron will give his long-promised IronRuby talk, and I’ll show a mini-project of mine that generates MSWord .docs from Textile, with RedCloth. It’s flashy, I promise.

Remember, if you have a topic you’d like to talk about, or one you’d like to hear about, or even if you just have an idea for what to do for the evening, don’t be shy, speak up! The group is what we make it, and it belongs to all of us.

As always, we’ll have free pizza and soda, courtesy of Sun Microsystems.

Hope to see you there!