Showing posts with label ruby. Show all posts
Showing posts with label ruby. Show all posts

Tuesday, November 11, 2008

The Slashdot faithful and loving languages

Lately I'd say I've been reading roughly 1 out of every 20 Slashdot articles that come through my feedreader. And when I say "reading" I mean reading _all_ the comments. As any other Slashdot aficionado can tell you, there are often hidden diamonds of anonymous nerdiness buried within the rough of fanboy excrement that can be found in no other place. That's what keeps me
coming back I guess.

Yesterday an article mentioned Ioke which caught my attention mostly for being a brainchild of Ola Bini. To no surprise of my own, the best part of this post was the comments.

In one corner you have Ola Bini, a prolific self-trained hacker, author and speaker, talking about what he does in his spare time and how he has a a roughly working new language that has some interesting features (for some definition of "interesting"). In the other you have a sea of nerds who Just Don't Get It. Ola is not trying to create yet another language whose documentaion will clutter blogs and a bookstore near you. He's just having fun.

While he is a promenent member of the Ruby community, I definitely wouldn't label him as a Ruby programmer any more than I would label him a Blub programmer. He, like most of the people I know in the Ruby community, loves computer languages. I started to understand this at RubyConf last year when Matz showed off his Python shirt during the keynote. This year he spoke again of his love for (almost) all computer languages while Dave Thomas proclaimed that now is the time to fork ruby (for reasons no Slashdot pundit would understand). I highly recommend Dave's keynote to anyone who's interested in why we program computers. I suspect it will eventually be available at this link: http://rubyconf2008.confreaks.com/

Tuesday, August 12, 2008

Ruby 1.8.7

I must say I'm a bit worried by the 1.8.7 release. The only reason I even care out about it is because I recently was bitten by a bug in 1.8.6p230 that, as of the time of this blog entry, is the latest version in Fedora. Quite frankly I am surprised whenever Fedora decides not to ship the latest "stable" upstream package which is why I took the time to understand the state of 1.8.6.

I think the main problem is that the goal for 1.8.7 is unclear, at least from the community's perspective. Contrast this situation with 1.9--a release I'm actually excited about. There are plenty of people telling you what to expect from 1.9. Matz talked about it at RubyConf last year. There's even a beta book out about it now.

In short, 1.9 represents the correct way to work with the community to move a platform forward. Namely, coupling core changes that likely break the killer apps with features that entice developers to go through the effort of porting their code. 1.8.7 needs as many eyes looking over it as possible and it's just not attracting them in my opinion simply because the community doesn't see a reason to upgrade.

while(burn :me)
desire_to_upgrade = ignore(:version => :latest_stable)
raise if desire_to_upgrade.nil?
end

Tuesday, March 25, 2008

My ctags lightning talk

Last week at the Raleigh.rb we had an evening of lightning talks. I presented
a handy utility called exuberant ctags for indexing source code and showed
how nicely it plays with Ruby and Vim. Here's a recap of my 5 minute lightning
talk (along with a few points I failed to mention).

Setup:
# From the top level of your project
ctags --recurse

Once it finishes there will be a file called 'tags' in your working directory.
In my case vim loads tag files automatically if it finds them in the same
directory from which it was launched. If for some reason your version does not
do this for Ruby files you can type the following in command mode:

set tags=[path to your tags file]

To make the change permanent add the following to your vimrc:

# Look for a tags file in vim's working directory.
au BufRead,BufNewFile *.rb set tags=tags

In both cases a comma separated list is accepted. This is nice if you are
working on multiple projects.

Usage:
ctags works with most real text editors though I'm only experienced with the vim
integration. Basically, once vim has loaded the tags file you can place
the cursor on top of any word and press cntrl - ] to jump to the
declaration. In some cases users will notice their terminal also has that
specific key combination bound. Under gnome-terminal I have to press cntl-shift - ] to
access my tags. In the case where more than one tag matches a selection
mode will be displayed. Usually it's fairly obvious which one you want.

Also worth mentioning is vim's tagstack. It works pretty much as expected. You push down as far as you
want and then use cntrl - t to pop back.

Limitations:

Obviously this sort of indexing faces challenges when working with a language
as dynamic as Ruby. Things that trip it up are method aliases and any fancy
metaprogramming.

ctags vs rtags

There is a Ruby ctags alternative called rtags. In my opinion ctags works better:
  1. ctags is several orders of magnitude faster that rtags. On my laptop a 100,000 SLOC project is indexed in less than one second. rtags takes about a minute to do the same.
  2. ctags supports dozens of languages. Run ctags --list-languages to see them all.
  3. rtags has trouble parsing files on most Ruby projects I work on. This is what led me to switch back to ctags in the first place.
  4. rtags claims to be more aware of Ruby syntax though in practice I find it indexes many things I just don't care about.

Sunday, October 28, 2007

DSLs made easy

XOAP recently hosted the first Belgian Ruby User Group meeting and Peter Vanbroekhoven gave a great talk on metaprogramming in Ruby. I would recommend this to any of your Blub programming friends. For some reason the last 5 minutes or so of audio seems like it was cut out. The speaker gets through all the slides though. Perhaps they edited out the audience's questions.

Thursday, June 14, 2007

Ruby closure shootout

Ok, so I too have been bitten by the arity differences between Proc.new and lambda so a few months ago I tried to find the Ruby spec to get a better understand. It was then I came to realize that the only true Ruby spec is defined by the C implementation. While such a spec may allow for rapid improvements to the language it comes at the cost of warts--and Ruby is not without it's fair share. I stumbled across this site today that is possibly the best 'research' compiled on Ruby's closures that I have seen to date. It does a great job of exposing Ruby's warts while at the same time demonstrating the power of closures in Ruby.

The article (it's really just a script you can feed the interpreter!) was encouraging in that it showed me I really should spend a little time in the MRI perusing the source for these sorts of tidbits. I can really appreciate all the work that the groups heading up the various Ruby implementations are doing to formalize a Ruby spec.

Saturday, June 2, 2007

Black-boxing Google Translate

It seems like the more I watch the Mountain West sessions the more I stumble across solutions to itches I've had recently. Just yesterday at work I was hacking with a friend on a simple CLI for Google Translate and we were struggling a bit getting 'curb' to do exactly what we wanted. After watching James Britt's session on Black-boxing with Ruby I realized that mechanize would probably be a better choice for what we were trying to do. 10 Minutes later:

require 'rubygems'
require 'mechanize'

agent = WWW::Mechanize.new
agent.user_agent_alias = 'Linux Mozilla'
page = agent.get("http://translate.google.com/translate_t?langpair=en|#{ARGV.shift}")
translate_form = page.forms[0]
translate_form.text = ARGV.join(' ')
translate_form.ie = "UTF8"
translate_form.hl = "en"
results = agent.submit(translate_form)
puts Hpricot(results.body).search("//div[@id='result_box']")[0].to_plain_text


# Examples
ruby translate.rb zh-CN "I love to eat tacos on Tuesdays" => 我爱吃tacos周二
ruby translate.rb es "I love to eat tacos on Tuesdays" => Amo comer el tacos el martes

While these may not be accurate translations, this script definitely works for testing out i18n functionality until the real translations come in. If and whenever Google decides to release an API for their site it will be painless to throw this script away.

Programming Rule #42

"Every problem has already been solved. It is Open Source. And it is the first result on Google"
--Ara T. Howard (I don't know if he's actually the one who said that first, someone correct me if I'm wrong)

I spent some time this weekend watching the Mountain West Ruby Conf's videos and I must say what I've seen so far has been great (now I'm really exited about the Ruby Hoedown). The session on Ruby Queue is going to be immediately useful to me in my effort to distribute selenium tests over a linux cluster. It's actually quite amazing that the solution I had cooked up approached the task of clustering from almost the same way--simply using a queue to feed shell tasks to an array of nodes. It's quite ironic in light of Ara's quote on Rule #42 and his project that basically sent mine to the grave.

Luckily my solution was only the product of a few weeks of work off and on. In < style="font-weight: bold;">it's that simple. So, I'm going to take my project off rubyforge and stick it somewhere else. The one thing that I really need that RQ doesn't handle is clustering with Windows machines. Since I need to run tests with IE I'll have to spend some time to see if this is something that could be worked into RQ. I have absolutely zero experience with Windows and NFS so I don't have any idea how much work would be needed at this point.

Tuesday, May 8, 2007

": No such file or directory" error from bash

I hit a strange problem this morning that I hadn't seen before. I tried to run a ruby script and bash kept telling me ': No such file or directory'. I then tried feeding the script to the interpreter directly and things worked as expected. After double and triple checking my shebang line everything seemed correct. It then occurred to me to think about where I had gotten the particular script in question from. It was generated by the Selenium IDE while I was on a windows test machine a few weeks before. As many already know line breaks in the windows world end with simply a carriage return and not a carriage return linefeed pair. I used the wonderful dos2unix utility to sanitize my script and then everything worked as expected.

Wednesday, April 25, 2007

If you can read this you are too big to play here.

I remember when I was in preschool I used to climb on a huge tree in the middle of the playground. My friend David and I would catch caterpillars and then squish them on the steps of the school to see what color they were inside. That tree is barely standing now and I've long since realized that squishing things for mere novelty is a little strange. Another thing I discovered later in life was a sign that was hanging from the surrounding fence stating, "If you can read this you are too big to play here".

After my first pass reading this article on InfoQ I had the an all too familiar feeling as if there was something going on that missing me entirely. I read through it a second time and the uses of eval, class/module_eval and instance_eval are starting to become more apparent. Read the code and pay close attention to the use of eval. It might not be so evil after all.

Tuesday, April 24, 2007

Migration gotcha

Apparently sqlite3 is more forgiving than mysql when it comes to migrations. I found out today that there is no need to specify the ':id' column and if you try it with mysql5 you will get an error similar to:
Mysql::Error: #42000You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(11), `suite_id` int(11) DEFAULT NULL, `text` varchar(128) DEFAULT NULL) ENGINE=' at line 1: CREATE TABLE surefire_notes (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY(11), `suite_id` int(11) DEFAULT NULL, `text` varchar(128) DEFAULT NULL) ENGINE=InnoDB
The problem has to do with the 'PRIMARY KEY(11)'. I pasted the above command directly into mysql and removed the '(11)' and everything worked just fine. With some more googling I came across this site which further confirmed my discovery.

Monday, April 23, 2007

The best explanation of metaclasses in Ruby I've found

I stumbled across "seeingMetaclassesClearly.html " today. I don't know how I never came across it. It's definately the best explanation of metaclasses in Ruby I've ever read. Now the whole "class << obj; def meth; puts "hello from the metaclass"; end; end;" syntax makes sense. Previously I had used "obj.extend(module)" before but the former is obviously more convenient if you are in a class definition.

Wednesday, April 4, 2007

getaddrinfo: name or service not known

Once again I find myself trying to get a ruby app working on a windows machine. I can hardly express bad I feel for anyone who is plagued to work in such an environment full time. The last time I was struggling to understand how Ruby's in-process threads on win32 are not concurrent. This time around it's trying to understand why getaddrinfo() was failing.

Basically I'm working with DRb which by default uses TCPSocket as the default protocol. Socket.getaddrinfo() was telling me 'name or service not known' when it was trying to connect to the DRb server on my unix host. After hours of googling around learning about getaddrinfo() on windows and cygwin I came to realize that my problem was probably not related to what most of the google (and yahoo) results were returning. Apparently there was a time when that call would simply fail or was not implemented in cygwin. It turned out my problem was actually related to the hostname of the machine it was working on: 'LENOVO-A0EFF48'. I can't say I totally understand the relationship between cygwin and windows understand of a machine's hostname but I eventually changed the hostname to 'localhost'. I rebooted I got a different error because my VPN was choking (and I suspected it to be related to the hostname change). I then changed the hostname to 'laptop' and rebooted. Voila, my VPN and getaddrinfo() worked. Now I think I'm back to fighting Ruby threading issues on windows.

When I get around to it I'll look microsoft's getaddrinfo() source and figure out why it was choking on 'LENOVO-A0EFF48', oh wait....

Monday, January 1, 2007

define_method

I frequently find myself writing the exact same method over and over with only minor differences between them (I'm sure there are plenty of design patterns to get around this in every language). One way of getting around this in ruby without much fuss is 'define_method'. Here's a snippet from Widi:


['header', 'footer'].each do |m|
define_method('generate_' + m) {
@widi_config = WEBrick::Config::Widi
file = @widi_config[m.capitalize.to_sym]
if
file =~ /rhtml/ && File.exists?(file)
data = open(file) {|io| io.read}
return
ERB.new(data).result(binding)
elsif file.nil?
constant = self.class.to_s + '::DEFAULT_' + m.upcase
return
constant.split('::').inject(Object) do |x,y|
x.const_get(y)
end
end
}
end
Once that code is run the encompassing class will have two methods called 'generate_header' and 'generate_footer'. This approach would be more justifiable if I needed more than just two methods so I may end up ripping it out.

One thing that did not behave how I expected was Module#const_get. It doesn't handle the ::'s nicely and I had to use an idiom I found in The Ruby Way.

Tags

my google reader feed