23 May, 2009

Moved

This blog has moved to http://jamesarosen.com/.

31 January, 2009

Customer Service WIN

I just took a look at my cell phone bill. I went 254 minutes over . . . which is quite surprising to me because I never use it during the day and I have free nights and weekends. Or so I thought. It turns out I only had 400 night minutes and unlimited weekends. (I was sure I was right, but, of course, we know that human memory is quite fallible.)

So I called up T-Mobile to bitch about them changing my plan on me without me noticing. But it seems they did not. I was just wrong. Nonetheless, they offered to add their "faves" plan or whatever it's called so I could get free calls to my five most frequently called numbers, which, given my bill looks like a power law, will help substantially.) Normally they want a 2-year contract for that plan, but they knocked it down to one AND BACK-DATED IT so it applies to this bill and I get out of the contract sooner.

Major win for T-Mobile. I've always said I liked their customer service. Now I remember why I'm not getting an iPhone: stupid AT&T couldn't even tell me my credit card wasn't processing; they just racked up lots of late fees.

24 January, 2009

My Dream Menu, take 1

Mélange

Salad of frisée, radicchio, chive, cucumber, pecans, honey garlic dressing and coconut shavings.

Kanso

Fresh whole wheat pasta, olive oil, fresh cracked black pepper, sea salt. Served with a side bowl of Parmesan snow.

Forte

Four ounce flatiron steak with two grilled jumbo shrimp, drizzled in walnut oil.

Concision

Lime sorbet scooped with a melon-baller into a rocks glass.

(needs a name)

Bacon and leek consommé.

(also needs a name; austerity?)

Trout and asparagus almondine.

Indulgence

Double chocolate bombe with cappucino ice cream.

Digestive

Krupnik, Limoncello, etc.

I might like to fit in a tempura somewhere. Thoughts? Also, bacon is particularly tough to do consommé with because it has lots of fat and little to no cartilage and tendon (needed for the gelatin) — perhaps there's another interesting meat to be used?

20 January, 2009

English as She is Spoke, Part 3: the Ugly

Today was a joyous day in our country. It was also both a monumental and momentous occasion. It was not a "monumentous" one. The opinions of multiple callers and pundits on NPR today notwithstanding.

17 November, 2008

English as She is Spoke, Part 2: the Good

"Meh" was recently added to the Collins English Dictionary. My fuddy-duddy post of yesterday notwithstanding, this makes me happy. I enjoy having an onomotopoetic word for apathy.

English as She is Spoke

<rant> Twenty percent of the words in the title of Richard Ford's The Lay of the Land are misspelled! In the title! You're telling me not even his editor remembers the word "ley?" I suppose I shouldn't be surprised: Firefox doesn't know the word. It snubs me with its little red dotted line, suggesting instead "la," and "lye," and even "hey" and "levy." </rant>

02 November, 2008

Sometimes, having been a music major is a curse

There's a moment in Mendelssohn's Hebrides Overture that reminds me of something, but I can't pin it down. It's about halfway through; 4'55" in on the André Previn recording. It starts out in the celli, I think, and then moves up. Could it be in a recent action movie?

Later...I'm not sure this is what I was thinking of, but it's pretty similar to the base line of the new Dr. Who theme.

02 October, 2008

Supreme Court History

In response to the Know Your Supreme Court History meme, I offer Roberson v. Rochester Folding Box Company. Admittedly, it's a New York Court of Appeals decision, not a U.S. Supreme Court decision, but it has stood the test of time.

What happened

"The complaint alleges that the Franklin Mills Co., one of the defendants, was engaged in a general milling business and in the manufacture and sale of flour; that before the commencement of the action, without the knowledge or consent of plaintiff, defendants, knowing that they had no right or authority so to do, had obtained, made, printed, sold and circulated about 25,000 lithographic prints, photographs and likenesses of plaintiff, made in a manner particularly set up in the complaint; that upon the paper upon which the likenesses were printed and above the portrait there were printed, in large, plain letters, the words, "Flour of the Family," and below the portrait in large capital letters..."

In other words, a company used a woman's picture to advertise their product, but it didn't ask her permission or offer her payment for the picture and/or the endorsement.

Why it's important

Roberson is perhaps the bedrock privacy case in American history. There is no obvious precedent: it is the first case to set the standard that "identity" is a legal object and that it is legally owned by its subject. The decision states that,

"It may be said in the first place that the theory upon which this action is predicated is new."

The case also demonstrates that even though privacy rights are not explicitly enumerated in the Constitution, they can still trump the First Amendment. It's important that the plaintiff did not allege libel, merely that they misappropriated her likeness.

14 September, 2008

Loyalty Scale

In part III of the continuing series on morality, I took the "Identification with All Humanity" quiz at yourmorals.org. The results:

 Obama SupportersMcCain SupportersMe
Community3.02.22.0
Country3.03.73.2
World3.32.63.6

Moral Dilemmas Results

In part II of the continuing series on morality, I took the "Moral Dilemmas" quiz at yourmorals.org. The results:

 AverageMe
Impersonal Dilemmas3.06.0
Personal Dilemmas3.21.0

Moral Foundation Results

I just took the highly informative "Moral Foundation" quiz at yourmorals.org. The results:

 LiberalsConservativesMe
Harm3.62.94.0
Fairness3.73.04.0
Loyalty2.23.22.7
Authority2.13.32.2
Purity1.32.91.0

05 July, 2008

Comcast, Airport Express, and DHCP

I just got a new Comcast high-speed cable account today. It was a bit of a hassle to get the setup utility to run properly on OSX, but it did eventually. Then I had a working connection from laptop to cable modem to the world.

I wanted to use my Airport Express as a wireless router; this went less smoothly. I fiddled with this setting and that, but could not get the Airport Express to get a DHCP lease. This discussion, however, solved my problem immediately: the trick is that the cable modem remembers the MAC address of the computer you set up the account with. To fix the problem, just power-cycle the modem while the Airport Express is plugged in to the LAN port.

25 June, 2008

Ruby Needs a StringBuffer

john has written a little post about using a String as a File (really as an IO) in Ruby. He does a great job explaining how StringIOs work for reading characters. They're particularly good for unit tests on IO operations.

What john doesn't mention, however, is that StringIO is only an 'I.' It has no 'O.' You can't do this, for example:

s = StringIO.new
s << 'foo'
s << 'bar'
s.to_s
# => should be "foo\nbar"
# => really is ''

Ruby really needs a StringBuffer just like the one Java has. StringBuffers serve two important purposes. First, they let you test the output half of what Ruby's StringIO does. Second, they are useful for building up long strings from small parts -- something that Joel reminds us over and over again is otherwise very very slow.

So I wrote a StringBuffer, but it's not very good, and it's not very fast. What we need is one written in C in the core Ruby library. Now that will help Rails scale.

27 May, 2008

Handling Routing and Dispatch Errors in Rails

I've been trying to show nice error pages for RoutingErrors and MethodNotAllowed errors, which are raised outside of the context of a Controller. I dug into the routing and dispatch code and finally realized that those errors cause a direct call to :rescue_action, bypassing :rescue_action_with_handler.

I've put the result at http://pastie.caboo.se/204355.

25 April, 2008

9PM: End of the World

I went to check the weather on weather.com today. I like their hour-by-hour feature. Unfortunately, today it gave me some odd information:
So 8PM: Thunderstorms; 9PM: world ends?

16 April, 2008

Really Simple Development With Git

Once you've got your hot new app up on GitHub, you want to work on it, but you're used to the Subversion world of update-code-test-update-commit. What does a good code cycle look like in Git?

My friends, I tell you I have the answer. And it's simple.

  1. git checkout -b nifty_name_for_nifty_new_feature
  2. git pull [repository [branch]]
  3. for each submodule of interest: cd path/to/submodule; git pull
  4. [code code code]
  5. [test test test]
  6. git add files/related/to/commit
  7. git commit -m 'nifty feature done'
  8. take 5 minute break to feed puppy or check roast in oven
  9. git checkout master
  10. git merge nifty_name_for_nifty_new_feature
  11. git branch -D nifty_name_for_nifty_new_feature
  12. git push

This keeps all development in tight little branches. The branches only exist locally, and go away when the feature makes its way to master. Happiness. Especially when teammates ask you to stop working on nifty_feature and fix acts_as_pointy_haired_boss. In that case, I recommend "fixing_bug_12345" as the branch name; that helps you remember what the branch does after you get back from the really boring meeting on how you can sell more purple pleather pants to Auckland this year.

Thank You For Arguing

I bought Jay Heinrichs' Thank You For Arguing last summer, but never got around to more than glancing at it. I've been reading it at pretty much every chance over the past few days, though. It's absolutely fantastic!

One of the main theses of the book seems to be that people shouldn't think of rhetoric as manipulation, and Jay even does little sidebars to point out when he's using techniques within the book to convince you of his points, but I still can't help but feel manipulated. Ah well, it doesn't stop me from wanting to practice my rhetoric more.

27 March, 2008

New Gem: Avatar

I released Avatar version 0.0.3 today. This gem offers avatar support for a variety of sources. It's not Rails-specific, but to use it in a Rails app, do something like the following.

In app/helpers/people_helper.rb:

class PeopleHelper
  include Avatar::View::ActionViewSupport

  def default_avatar_url(size)
    req = controller.request
    "#{req.protocol}#{req.host_with_port}#{image_path("/images/avatar_default_#{size}.png")}"
  end
end

app/views/people/show.html.erb:

<%= avatar_tag(@current_user, :size => 40, :default => default_avatar_url(:small) %>

The default settings will check for a Gravatar for @current_user.email. There are other implementations, including one that works with the file_column plugin. I'll be happy to add more implementations; the project is hosted on GitHub.

11 March, 2008

Shelves: Rack Extensions

I think Christian's Rack is fantastic. It's such a good idea, in fact, that Ab5tract and I are starting a GitHub projct called Shelves for Rack extensions. Our mission is to do request and response support for all the non-HTTP types of interaction that a website needs to do these days. We envision SMS, Email, and Twitter queries, and maybe even Port Knocking. Shelves will be modular, with lots of support classes for new request/response media.

More info as we get near a usable version. If anyone wants to contribute, drop us a line.

01 March, 2008

The Final Word on Rails Association Extension

There has been a great deal of debate on how to extend Rails Associations. Ryan discusses the "block" method:

class Organization < ActiveRecord::Base
  has_many :people do
    def find_active
      find(:all, :conditions => ["active = ?", true])
    end
  end
end

This is identical to the "extend" method; in fact Rails converts a "block" into an "extend":

module FindActiveExtension
  def find_active
    find(:all, :conditions => ["active = ?", true])
  end
end

class Organization < ActiveRecord::Base
  has_many :people, :extend => FindActiveExtension
end

The commenters then debate the merits of the "class method" method:

class Person < ActiveRecord::Base
  def self.find_active
    find(:all, :conditions => ["active = ?", true])
  end
end

class Organization < ActiveRecord::Base
  has_many :people
end

In all three cases (really two), you can call something like:

organization.people.find_active

There are differences, though! I ran some experiments to find out how each works, and found that unless you have some particular reason not to, you should always use the "block" or "extend" version, for two reasons:

  1. The "class method" version does not allow manual caching.
    class Person < ActiveRecord::Base
      def self.find_active
        @active ||= find(:all, :conditions => ["active = ?", true])
      end
    end
    
    Will break, as Adam T. mentioned in the comments.
  2. The association version is slightly faster then the class version. I created the same has_many relationship to two pairs of classes (Person has_many Things; User has_many Widgets). I then added 6 sub-association selectors (red, green, blue, small, medium, large) in different ways: Thing had class methods; User had the same methods embedded in the has_many association. I then ran benchmarks on 100 users/people and 5000 things/widgets (with identical respective associations). The x1 times are for finding all of 6 sub-association lookups on every Person (Class) and User (Association). The x2 times are for finding and reloading all 6 (that is, to gain the benefit of any automatic caching done by Rails or the database). In absolute times:
                               user     system      total        real
    Class (x1):            4.650000   0.680000   5.330000 ( 11.320903)
    Association (x1):      4.530000   0.670000   5.200000 ( 10.861711)
    Class (x2):            9.240000   1.360000  10.600000 ( 21.934539)
    Association (x2):      9.000000   1.330000  10.330000 ( 21.066327)
    
    Dividing the bottom two rows in half:
                               user     system      total        real
    Class (x1):            4.650000   0.680000   5.330000 ( 11.320903)
    Association (x1):      4.530000   0.670000   5.200000 ( 10.861711)
    Class (x2)/2:          4.620000   0.680000   5.300000 ( 10.967270)
    Association (x2)/2:    4.500000   0.665000   5.165000 ( 10.533164)
    
    Dividing all rows by the number of queries performed (per/query time):
                               user     system      total        real
    Class (x1)/600:        0.007750   0.001133   0.008883 (  0.018868)
    Association (x1)/600:  0.007550   0.001117   0.008667 (  0.018103) 
    Class (x2)/1200:       0.007700   0.001133   0.008833 (  0.018279)
    Association (x2)/1200: 0.007500   0.001108   0.008608 (  0.017555)
    
    The association version is a little faster, and gains more from the automatic caching Rails does.
  3. You can check out the experiment at https://svn.u-presence.com/svn/experiments/association_vs_class/ (username guest, no password).