RailsConf 2008

A couple of random Rails tips

Posted by rick Wed, 03 Jan 2007 00:07:00 GMT

UPDATE: I edited the autotest hook to (1) fix a bug, and (2) to make it more readable (not sure if I succeeded, but worth a shot).

I figured out a couple of things that were useful enough to me that I thought I’d share.

First off, if you’re a big user of autotest (and if you’re not, you might oughta should be), and you’re working on a really large application, maybe you’ll find this useful:

Drop this in your ~/.autotest file:


Autotest.send(:alias_method, :real_find_files, :find_files)
Autotest.send(:define_method, :find_files) do |*args| 
  real_find_files.select do |k,v| 
     (ENV['AUTOTEST'] and ! ENV['AUTOTEST'].empty?) ?   
        Regexp.new(ENV['AUTOTEST']).match(k) : true
  end
end

and then you can do stuff like:

% AUTOTEST='users' autotest    # run all tests with 'users' in the name
% AUTOTEST='digital.*cont'  autotest   # run all the digital signaturing functional tests
% AUTOTEST='party|digital'   autotest  # run all tests for parties or digital signaturing

This allows you to focus in on a small area of concern and still get the rapid feedback autotest gives you. Be sure to periodically run your entire test suite to make sure you’re not missing action-at-a-distance errors.

The other tip is a purely Rails tip. If you’re ever used ActiveRecord’s polymorphic associations then you may have run into a situation where you want many many many things to be able to be on the other (has_many) end of the polypmorphic association. I ran into this while doing work with digital signatures: I want to be able to associate a signature with almost any model object in my system. I should be able to retrieve the signatures (if any) for an object by just saying “object.signatures”.

This would normally require a “has_many :signatures, :as => signable” in every signable class in the system. Maybe reasonable, but if I were to forget to add the has_many to a class signaturing would stop working. It’s actually worse in my case since the signing algorithm can sign a web of related objects, so forgetting the has_many in one class would result in failures in related but not identical classes.

I decided to add functionality to have this happen automatically. At first I tried just opening ActiveRecord::Base and adding the call, which doesn’t put the call in the right scope for the subclasses (as don’t a variety of other AR::Base hacks I tried). I realized at some point that I needed to use Ruby’s “inherited” method to get the subclass at the right time, but AR::Base already uses inherited for other nefarious purposes. It turns out, this is the incantation that works:


class ActiveRecord::Base
  def self.inherited_with_signaturing(subclass)
    self.inherited_without_signaturing(subclass)
    subclass.send(:has_many, :signatures, :class_name => 'DigitalSigDigest', :as => :signable) unless subclass.name =~ /^DigitalSig/
  end

  class << self
    alias_method_chain :inherited, :signaturing
  end
end

As you’ll notice, my signaturing model is actually DigitalSigDigest. Also, I have other DigitalSig-something classes lying around that are part of the signaturing library, and using inherited this way allows me to actually conditionally include/exclude which classes get the signaturing has_many relationship. That’s cooler than I expected. Chalk up another one for Ruby.

By the way, you’re probably also going to be interested in this ticket if you’ve got STI classes with polymorphic stuff linked to them.

Tags , , ,  | no comments


banned vocabulary
"+1" (and "-1")
"existential"
"onboarding"
"ferret"
"finesse"
"yeah."
<blank> <units> thin
<blank> warriors
<blank> years young
<blank>'s team
<x> of the moment
(it|)'s all good
(noo|new)b(|ie|y)
I.T.
ROI
P.D.I.
[web] portal
accountab(le|ility)
actuate
advocate (v. and n.)
anyhoo
assessment
belief system
best practice(s)
best practice(s)
blog(|ger|ging)
business rules
cautiously optimistic
celebrate
closure
construct (n.)
creative(s) (n.)
dialogue
divers(e|ity)
diversity
document (n.)
emerg(ing|ent)
emoticon(s)
enabler
eponymous
everyday heroes
extreme <blank>
facilitate
faith-based
foment
gestalt
git 'r done
gradation(|s) [sic]
guiding vision
hoi polloi
human drama
ill-fated
incentivise
jejune
kerfuffle
killer app
kudos
leverage
marginalize(d)
matriculate
merch
monetize
mouth-feel
multitask(|ing|er) (n.t.)
n(oo|ew)b(ie|)
network(|ing) (n.t.)
nexus
outsider art
podcast(ing)
proggy
protocol
quantum leap
reflect (v.)
repurpose
revamp
river system
schadenfreude
sea change
shopping (etc.) culture
shout-out
some <blank>-action
sophomore effort
strategic repositioning
synergy
team members / partners
the <blank> arena
the <x> Street
tix
under 30-set
value system
vertical
where('|i)s the outrage?
win-win
winders
Weltanschauung