This blog has moved to http://jamesarosen.com/.
23 May, 2009
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 Supporters | McCain Supporters | Me | |
|---|---|---|---|
| Community | 3.0 | 2.2 | 2.0 |
| Country | 3.0 | 3.7 | 3.2 |
| World | 3.3 | 2.6 | 3.6 |
Moral Dilemmas Results
In part II of the continuing series on morality, I took the "Moral Dilemmas" quiz at yourmorals.org. The results:
| Average | Me | |
|---|---|---|
| Impersonal Dilemmas | 3.0 | 6.0 |
| Personal Dilemmas | 3.2 | 1.0 |
Moral Foundation Results
I just took the highly informative "Moral Foundation" quiz at yourmorals.org. The results:
| Liberals | Conservatives | Me | |
|---|---|---|---|
| Harm | 3.6 | 2.9 | 4.0 |
| Fairness | 3.7 | 3.0 | 4.0 |
| Loyalty | 2.2 | 3.2 | 2.7 |
| Authority | 2.1 | 3.3 | 2.2 |
| Purity | 1.3 | 2.9 | 1.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.
- git checkout -b nifty_name_for_nifty_new_feature
- git pull [repository [branch]]
- for each submodule of interest: cd path/to/submodule; git pull
- [code code code]
- [test test test]
- git add files/related/to/commit
- git commit -m 'nifty feature done'
- take 5 minute break to feed puppy or check roast in oven
- git checkout master
- git merge nifty_name_for_nifty_new_feature
- git branch -D nifty_name_for_nifty_new_feature
- 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:
- The "class method" version does not allow manual caching.
Will break, as Adam T. mentioned in the comments.class Person < ActiveRecord::Base def self.find_active @active ||= find(:all, :conditions => ["active = ?", true]) end end -
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.
You can check out the experiment at https://svn.u-presence.com/svn/experiments/association_vs_class/ (username guest, no password).