06 July, 2007

has_many_polymorphs and the open-closed principle

I like has_many_polymorphs. I would love it if only it obeyed the open-closed principle.

Let's say I have a PetOwner model, and I want it to have_many pets polymorphically.

has_many_polymorphs lets you do this:

class PetOwner < ActiveRecord::Base
  has_many_polymorphs :from => [:dogs, :cats, :fish]
  ...
end

But what if I later decide I want to add a Ferret class? In addition to

class Ferret < AbstractPet
  ...
end

I also have to change PetOwner:
class PetOwner < ActiveRecord::Base
  has_many_polymorphs :from => [:dogs, :cats, :fish, :ferrets]
  ...
end

It would be really lovely if has_many_polymorphs could just tell what has inherited from AbstractPet. There's no reason you can't do this (in fact, I did before I wrote this post), but there's a timing problem: all of the inherited classes have to load before PetOwner does. The has_many_polymorphs ... call only happens when PetOwner is first included, so all of those other classes have to have already registered themselves with AbstractPet (simply by inheriting from it) by then; unfortunately, there's no good way to guarantee class load order without major hacking at the environment.

Sometimes we just have to put up with not-the-best. Alas.

01 July, 2007

and the test_spec_on_rails journey continues

Test/Spec has a wonderful - if largely unnoticed - feature: you can specify the superclass of contexts. The default is the ole' Test::Unit::TestCase, but that won't always do.

Let's say, hypothetically, you wanted to write some integration tests for your not-quite-shiny Rails app. You'd use ApplicationController::IntegrationTest, right? That way you can do things like get "/posts/34.html" and it would look up the routings and just do the right thing. Awesome.

Except... things aren't quite so simple when using test/spec. Therefore, I bring you an illustrious, illustrative example:

require File.dirname(__FILE__) + '/../test_helper'

class UserStoriesTest < ActionController::IntegrationTest
 fixtures :people, :openid_authentications, :password_authentications
 context "User Stories", ActionController::IntegrationTest do
   context "a person coming to the site to log in", ActionController::IntegrationTest do
     specify "should see the welcome page" do
       get '/'
       template.should.be 'welcome/index'
       status.should.be 200
     end
     specify "should be able to successfully log in with email and password..." do
       post_via_redirect '/login.html', {:email => 'pete.thomas@xahoo.com', :password => 'test'}
       template.should.be 'people/home'
       status.should.be 200
     end
   end
 end

end

test_spec_on_rails continued...

Yesterday, I was very happy because all my controller tests (using test/spec, of course) were passing individually.

Today I decided to run rake test:functionals just to make sure they played well together. CRASH! BOOM! OTHER LOUD NOISES!

The problem, after two hours of debugging, is that I was creating the same context in different controllers. DocumentationControllerTest had a "A guest" context, and so did "AccountControllerTest" and "WelcomeControllerTest"

Test/spec is perfectly happy to merge these . . . I just didn't realize it merged them. I assumed that it would scope the context to its parent TestClass. No such luck.

The solution is quite easy, and really not all that bad practice anyway: scope your contexts manually. For example:

class WelcomeControllerTest < Test::Unit::TestCase
 context "The Welcome Controller" do
   context "A guest" do
     ...
   end
   context "A logged-in user" do
     ...
   end
 end
end

30 June, 2007

ActsAsAuthenticated in test_spec_on_rails

I was having trouble getting "login_as" from the ActsAsAuthenticated plugin to work with test/spec on Rails.

TechnoWeenie suggested doing a def login_as... within each context. (It no longer does; I've put the code from this post into that page now.) That didn't seem very DRY, so I tried including ActsAsAuthenticated all over the place. Nothing worked...

Until I realized the problem: each "context" block creates a new instance of Test::Unit::TestCase. I had assumed it created a new instance of XxxControllerTest. Alas. Easy to fix. Just putTest::Unit::TestCase.send(:include, AuthenticatedTestHelper) before the opening of your XxxControllerTest.

For example:

require File.dirname(__FILE__) + '/../test_helper'
require 'welcome_controller'

Test::Unit::TestCase.send(:include, AuthenticatedTestHelper)

# Re-raise errors caught by the controller.
class WelcomeController; def rescue_action(e) raise e end; end

class WelcomeControllerTest < Test::Unit::TestCase
  fixtures :people
  def setup
    @controller = WelcomeController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
  end
  context "A logged-in person" do
    setup do
      use_controller WelcomeController
      login_as :yvette_moore
    end
     ...
  end
end

29 June, 2007

My Keirsey Profile

According to Keirsey, I'm an ENTP: The Inventor. II. NT, the RATIONALIST (6% of population) GENERAL DESCRIPTION:

  • Technology-oriented / Motto: Knowledge is power
  • Strategists: Designers and executers of a plan
  • NTs are task oriented; they determine how things get done
  • Curious yet skeptical; “Why?” drives their actions
  • Objective, logical, and analytical
  • Detached
  • Focus on things; ideas
  • NTs eat, sleep, and breathe answers to a single question
  • Uncompromising quest for competence, excellence, to be at the top - not near the top)
  • Worst thing for NTs: to be normal
  • Set extremely high standards / high bar
  • Also interested in making you competent; has little tolerance for incompetence; you are no longer of any value to them; probably a large number of people are placed in the non-value category
  • Seek to lift up the level of the environment / the organization
  • Strong need for predictability
  • Visionary – constantly brainstorming about taking things to the next level of competence/excellence
  • There is always something wrong with today – NTs are self-correcting either mentally or through maneuvers
  • Perceive that they are teetering on the brink of disaster
  • Fear of not succeeding is greater than the fear of failing
  • They have the gift to get people to see where they are today and where they are going
DOWNSIDE:
  • Encoded is an unreasonable bar of excellence
  • Great facility with words
  • Plagued with the fear of being found out: there may be a crack in the armor
  • NTs may never discover that the earlier tapes played in their heads (one’s value as a human being is determined by one’s level of excellence) are not the truth.
  • They have this internal competency check list that is, all too often, uncompromising.
  • By failing the internal competency checklist … bad things will happen. Likely that there are a large number of people who question: are you competent by my criteria / very few people will fit into their inner core of close and acceptable associates
  • Always upping the bar
  • They go to jobs that they know they will be good at
  • Theoretically, they don’t finish anything; it’s always in a state of improvement, modification, expanding
  • If they conceptualize something beyond their perceived capacity, they disengage or / they will focus on ways to get their arms around it to make it manageable
  • NTs won’t lie; they will word-smith the truth
Needs a Sensing Type to ...
  • bring up pertinent facts
  • apply experience to problems
  • read the fine print in a contract
  • notice what needs attention now
  • have patience
  • keep track of essential details
  • face difficulties with realism
  • remind them that the joys in the present are important
Needs a Feeling Type to...
  • persuade
  • conciliate
  • forecast how others will feel
  • arouse enthusiasm
  • teach
  • sell
  • advertise
  • appreciate the thinker
CAREERS: Leans toward science and technology; systems analysts, research and development INTELLIGENCE: Strategic intelligence; everything must be analyzed in terms of its how and why RULES: Challenge all rules and dismiss any that do not make sense SEARCHES FOR TWO THINGS: To be a part of a team yet maintain a level of detachment / autonomy

21 June, 2007

Some Band/Album Names

Some possibly great band or album names:

  • Jerome Sheffield and the Wrong Goldfish
  • Three Halves Make a Whole Turquoise Sandwich
  • Eight Full Sundays
  • The Standards
  • Octothorp
  • Prefixes to Problems
Some really bad ones:
  • If, But, When, ...
  • Intricate and Restful
  • Refurbished Pickles
  • Yessiree, I Am Indeed a Proctologist
  • Teh H4x0r5
  • Fiends with Hairnets
  • Big Buttresses
  • Nothing to See Here; Move Along

Problems with a Democratic Republic

Scott Adams writes that he thinks Michael Bloomberg might be the man to stop this inane, barbaric feast upon "flip-floppers." I hope it's true.

But it's not the only problem with representative democracy. The Federalist Papers make many great arguments why our system is the best that humans can achieve, but it really fails in one area: public bias.

This past week, the Economist had a great story on public bias. The author lists four biases: "first, people do not understand how the pursuit of private profits often yields public benefits: they have an anti-market bias. Second, they underestimate the benefits of interactions with foreigners: they have and anti-foreign bias. Third, they equate prosperity with employment rather than production: Mr Caplan calls this the "make-work bias". Finally, they tend to think economic conditions are worse than they are, a bias towards pessimism."

I am now extremely disheartened that any politician would be able to convince the public that his or her policies are good given these biases. Congress and the President have done some astounding work (and some necessary compromises) to build a strong piece of legislation on immigration reform, but the public hates it . . . and it isn't helping Congress's report card.

Maybe the immigration bill isn't perfect. Maybe it's even downright bad. Certainly with all this bias, though, there have to be plenty of instances where the people disagree with a good idea.

19 February, 2007

Success, but no record

Well, I did it . . . I think. See, I remember thinking "I've gotta study every day" quite often for the last couple weeks, but I didn't write down when I did or check off each day from a list.

What did we learn: keep track of your goals so you know when you're hitting and missing. I must've forgotten something from my earlier weight training days. And maybe it would help to start keeping track of that again.

05 February, 2007

New Horizons in Self-Discipline

Today I begin my new self discipline training. I will study Chinese vocab at least 5 minutes every single day for the next 10 days. No exceptions. No, "I'll do double tomorrow." No excuses. (For those curious, Steve Pavlina was much of my inspiration.)