Ruby LOAD_PATH
I cleaned up an example from Giles’ post about issues with common Ruby idiom:
$:.unshift(File.dirname(__FILE__))
Giles gives an example for expanding relative paths, which I’ve cleaned up very minorly (he forgot the slash, big whoop):
class File
def self.here(string)
join(expand_path(dirname(__FILE__)), string)
end
end
I suggest reading the previously mentioned post for context. It’s worth it simply for the Highlander joke.
Update: I should have read the comments. Much more good discussion there.
TweetTail – HTML
I was reading through some Ruby code on GitHub tonight when I ran across Dr Nic‘s TweetTail utility. TweetTail prints a the latest Twitter search results to the console.
I decided I wanted to write a utility that would generate html listings of different searches I want to follow. I ran into some issues that I couldn’t satisfactorily solve, so I ended up forking and patching TweetTail itself. This is undesirable. I don’t want to have to maintain my own parallel version of TweetTail just to have a little bit different behavior.
I’m going to explain my problem. Hopefully someone will offer a better solution.
TweetPoller is the workhorse. Render_latest_results and format are the methods we’re concerned with:
class TweetTail::TweetPoller
# irrelevant code omitted
#...
def render_latest_results
@latest_results.inject("") do |output, tweet|
output += format(tweet)
end
end
def format(tweet)
screen_name = tweet['from_user']
message = tweet['text']
"#{screen_name}: #{message}\n"
end
#...
# irrelevant code omitted
end
What I wanted to do was just override the format method with my own version. I didn’t want to just monkeypatch over the top of it, so I inherited from TweetPoller and provided my own format method:
class HtmlTweetPoller < TweetTail::TweetPoller
def format(tweet)
screen_name = tweet['from_user']
created_at = tweet['created_at']
link = tweet['source']
message = tweet['text']
"<div class='tweet'>#{screen_name}: #{message}<br /> <a href='#{link}'>#{created_at}</a>\n"
end
end
That didn’t work. It was obvious why after I took another look at the metaprogramming section of the Pickaxe book: The render_latest_results method was still calling TweetPoller’s format method.
Getting around that is easy, you simply override the TweetPoller’s render_latest_results method:
class HtmlTweetPoller < TweetTail::TweetPoller
def render_latest_results
@latest_results.inject("") do |output, tweet|
output += format(tweet)
end
end
def format(tweet)
screen_name = tweet['from_user']
created_at = tweet['created_at']
link = tweet['source']
message = tweet['text']
"<div class='tweet'>#{screen_name}: #{message}<br /> <a href='#{link}'>#{created_at}</a>\n"
end
end
Now I’ve got code that has been copied and pasted from TweetPoller into my own class. That doesn’t make me happy. I haven’t come up with a situation where it’s actually a problem. It just seems suspect to me.
This is where I’m stuck. This is the point I decided to modify TweetTail.
Any guidance is greatly appreciated.
Work Is Great
I’m having a blast at work. Definitely enjoying it much more than I would have guessed.
I recently got to start throwing a little bit of my work time (and quite a few off-the-clock hours) into learning Django + Pinax and getting them setup as a blogging/wiki/forum platform.
I think having two or more projects is a real good thing for me. It means I have two carrots to motivate myself; Get X amount done on project A and then I can do Y amount of work on project B.
It’s also helpful to me to switch platforms during the day. Most of my work is on WebForms/C#, which harshes my melon. Getting to look at non-evil stuff is very refreshing, even if it’s a tiny amount of my working day.
(Apologies for lack of structure and coherence. I wrote this completely in the quickpress widget.)
Codetry
One of my work mates has a quote in his status message:
To strive, to seek, to find, to never yield!
Here’s my translation into Ruby:
def seek(sought)
sought
end
def strive(for_this)
found = seek(for_this)
found or yield found
end
strive(:perfection) { |r| puts r.to_s }
It strives. It seeks. It finds. It never yields.
Baseball Allegory
Even full-blown baseball sucks but I guess the point of this is valid anyway.
Lotus Notes
I’ve had the, um, privilege of writing a lot of code for Lotus Notes applications (native and web). It is a horrifically painful experience. Some simple things are easy, others are impossible. Don’t get me started on how it goes when you try to do complex things.
Do I hate Lotus Notes? Not really. I hate the way the platform is inflexible and encourages bad development practices. Lotus Notes is also riddled with what some might call “convention-over-configuration” features. Others would call these “wildly inconsistent, undocumented behaviors” or even “bugs.” I just love having no programmatic access something mundane like the querystring without adding a special field to all of my documents. Seriously, why isn’t this just in the NotesSession object?
I am halfway through reading The Pragmatic Programmer (It’s as good as everyone says). And I haven’t found much in it that I can apply to my Lotus Notes development work. Andy and Dave’s advice isn’t deficient. It’s usually immediately obvious how and why you would want to follow their suggestions. Instead the limits of the Lotus Notes platform actively work against good development practice.
For instance, I’m converting several MS Access applications to Lotus Notes web applications, so it would be nice to be able to generate NotesForms from the database schema. This isn’t possible because you can’t meaningfully modify a NotesForm object programatically.* Instead of being able to write some code to alleviate this pain, I have to go through a long, tedious process involving delimited files, format listings, and mouse clicking.
So, contrary to my constant exclamations, I don’t hate Lotus Notes. I hate the restrictions it places on me as a programmer. I hate that it encourages people to be really, really crap programmers, while still considering themselves programmers.** And I hate that it could be so much more, but isn’t.
* Is there some sort of black magic that will let you do this? If so, nobody I’ve ever worked with knows it and Google doesn’t know it.
** Okay, so most of my co-workers consider themselves “Lotus Notes Developers.” Being a Lotus Notes Developer apparently entails lots of copy and paste.***
*** It seems that every Lotus Notes application borrows the same broken code. I have some real fun stories about this — more later.
Election Day Monkey Patch
Ruby Arrays have a delete_if method, so I thought I’d add delete_unless for fun:
class Array
def delete_unless(&block)
self.replace self.select {|v| v if yield(v)}
end
end
There’s something that makes me smile about that method.
Monopoly
Monopolies are important. They are a key player in making things “safe.”
The trade monopolies of the past, like the British East India Company, made it safe to do business in the Far East, Africa and the New World. IBM made it safe to use computers in big business. Microsoft did the same for computers on every desk, even at home. Google tamed the web and turned it into a safe and somewhat less interesting resource.
What do I mean by safe? I mean that these companies transformed risky ventures into reliable, accepted practices. What was once deemed irresponsible or doomed to failure became commonplace and boring. The extraordinary became ordinary.
There are numerous examples where monopolies have changed the world in enduring ways. Makes me wonder if the world had reached the point where these changes were inevitable, or if powerful monopolies perpetuated them.
Ruby DCamp
I’m going to be at Ruby DCamp on October 11th and 12th. I’ve also registered for a couple of other meetups in October. One is for the Northern Virginia MySQL group on October 6th and the other is for the Baltimore on Rails group on October 14th.
DCamp is going to be a blast. Meeting local developers that like the same stuff I do will be great too.