Ruby, Rails, Web2.0 http://www.rubyrailways.com Experiences with Ruby and Rails, Web2.0 and other development technologies Tue, 26 May 2009 07:57:08 +0000 http://wordpress.org/?v=2.7 en hourly 1 Dear Railsists, Please Don’t be Obtrusive http://www.rubyrailways.com/dear-railsists-please-dont-be-obtrusive/ http://www.rubyrailways.com/dear-railsists-please-dont-be-obtrusive/#comments Tue, 19 May 2009 08:22:54 +0000 peter http://www.rubyrailways.com/?p=437 obtrusive_or_not.png Update: thanks to Jon Wood aka jellybob, a prototype demonstration has been added, which is even better than my original jQuery btw as it degrades gracefully. Check it out in the ‘prototype-unobtrusive’ directory.

I am guessing 9 out of 10 of you reading the title is prepared for yet-another Rails drama on some obtrusive community members, and because everyone is tired of Rails dramas, I am risking that some of you won’t care to read the article - but I couldn’t resist :-). Actually I’d like to talk about usage of (un)obtrusive Javascript - why is it a bad idea to be obtrusive, especially given that (as you will learn from the article) writing unobtrusive Javascript is not harder, and you get the warm, fuzzy feeling of writing nice and clean code!

The Drill

To demonstrate the differences, I’ll lead you through the creation of a quick AJAXy shout wall both the default/standard (and obtrusive) way, then do the same with unobtrusive Javascript to show you that contrary to the popular belief, you don’t need to memorize the “Tome of Javascript Black Magick Tricks” by heart, use obscure libraries or special coding techniques to achieve clean, unobtrusive code. The shout wall is simply a form for posting a new message, and a list of messages below it, like so:

shout_wall.png

(You can check out the code used in this post from it’s github repository).

The Standard Way

Note: If you’d like to follow along, please use the provided pastie links - do not try to cut & paste multiple lines from the page (single lines are OK), as it will be b0rk3d.

  1. Creating a new Rails application
    1. rails obtrusive-shout-wall
  2. Get into the Rails dir
    1. cd obtrusive-shout-wall
  3. Generate the resource message
    1. script/generate resource message
  4. Add this the following to the generated migration (some_timestamp_create_messages (Get it from pastie):
    1. t.string :author
    2. t.text :message
  5. Run the migrations:
    1. rake db:migrate
  6. Because we want to view the messages in reverse order (newest one first), we add a default scope to the Message model (in message.rb):
    1. default_scope :order => ‘created_at DESC’
  7. Create the application layout - create a new file in app/views/layouts called application.html.erb, and fill it with the following content (Get it from pastie):
    1. <html>
    2.   <head>
    3.     <%= stylesheet_link_tag "application" %>
    4.         <%= javascript_include_tag :defaults %>     
    5.   </head>
    6.     <body>
    7.     <%= yield %>
    8.     </body>
    9. </html>
  8. Create a file application.css and drop it into public/stylesheets. Add the following content (Get it from pastie):
    1. body {
    2.     background-color:#FFFFFF;
    3.     color:#333333;
    4.     font-family:"Lucida Grande",verdana,arial,helvetica,sans-serif;
    5.     margin:0 auto;
    6.     padding:0;
    7.     text-align:center;
    8.     width:960px;
    9. }
    10.  
    11. #messages {
    12.     text-align: left;
    13.     margin-left: 80px;
    14.     margin-top: 50px;
    15. }
    16.  
    17. #message-form {
    18.     text-align: left;
    19. }
    20.  
    21. #message-form dl {
    22.     margin:10px 0 0 80px;
    23. }
    24.  
    25. #message-form dd {
    26. color:#666666;
    27. font-size:11px;
    28. line-height:24px;
    29. margin:0 0 5px 80px;
    30. }
    31.  
    32. #message-form dt {
    33.     float:left;
    34.     font-size:14px;
    35.     line-height:24px;
    36.     width:80px;
    37.   text-align: left;
    38. }
    39.  
    40. #author {
    41.   margin-right: 640px;
    42. }
    43.  
    44. #message {
    45.   width: 600px;
    46.     height: 200px;
    47.   margin-right: 194px;
    48. }
    49.  
    50. .message {
    51.   margin-bottom: 20px;
    52. }
    53.  
    54. .first_row {
    55.   padding-bottom: 10px;
    56. }
    57.  
    58. .message-meta {
    59.     font-size: 12px;
    60. }
    61.  
    62. .author {
    63.   color: #FF5050;
    64.     font-weight: bold;
    65. }
    66.  
    67. .new-message-label {
    68.   text-align: left;
    69.   padding-top: 30px;
    70.   margin-left: 80px;
    71. }
    72.  
    73. #submit-button {
    74.   float : right;
    75.   margin-right: 195px;
    76.   margin-top: 10px;
    77. }
  9. Create a new action, index in MessagesController (Get it from pastie):
    1. def index
    2.   @messages = Message.all   
    3. end
  10. This goes into app/views/messages/index.html.erb (Get it from pastie):
    1. <h3 class="new-message-label">Enter new message!</h3>
    2. <% remote_form_for :message, :html => {:id => "message-form"} do |form| %> 
    3.   <dl>
    4.         <dt>Author:</dt>
    5.     <dd><%= text_field_tag ‘author’ %></dd>
    6.         <dt>Message:</dt>
    7.         <dd><%= text_area_tag ‘message’ %></dd>
    8.     </dl>
    9.     <%= submit_tag "Submit!", :id => "submit-button"%>
    10. <% end %>
    11.  
    12. <div id="messages">
    13.     <%= render :partial => ‘message’, :collection => @messages %>
    14. </div>
    We are showing the form for the messages and list the already exiting messages below the list. Note that we are using the _remote_form_for_ Rails helper to create an AJAXy form. This is already obtrusive, since if you observe the generated HTML, you will see that the form has an onsubmit parameter with some horribly looking code attached to it.:

    Obtrusive helper.png

    Sure, you can go ‘meh’ all the way, but slinging Javascript code all over the place is just as bad idea as writing inline CSS (or even worse, using HTML code for styling) or putting Rails code into views. It will work without any problems - but it’s just not the right way of doing things, especially if your code is going to hit a certain size.
  11. You probably noticed that we are rendering a message as a partial - so create a partial file app/views/messages/_message.html.erb with the following content (Get it from pastie):
    1. <div class="message" id="message-<%=message.id%>">
    2.   <div class="message-meta">on
    3.    <%= message.created_at.to_formatted_s(:long_ordinal) %>,
    4.    <span class="author"><%= message.author %></span>
    5.    said:
    6.   </div>
    7.   <div><%= message.message %></div>
    8. </div>
  12. We need a ‘create’ action in MessagesController in order to process the form submission (Get it from pastie):
    1. def create
    2.   @message = Message.create(:author => params[:author], :message => params[:message])
    3. end
  13. And obviously we’ll need to render something to respond to the create action. Using the standard Rails way, RJS, we might come up with something like this (in app/views/messages/create.js.rjs - Get it from pastie):
    1. page.insert_html :top, "messages", :partial => ‘message’, :object => @message
    2. page.visual_effect  :highlight, "message-#{@message.id}"
    Here we insert the “messages” partial, using the just created @message, and throw a splash of yellow fade into the mix for good measure. Easy peasy.
  14. We are done! Fire up script/server, hit localhost:3000/messages and voila!

The Good Way

Here I am presenting only the steps that are different from the above - i.e. if step 3 is skipped, use the one from above.

  1. Creating a new Rails application
    1. rails unobtrusive-shout-wall
  2. Get into the Rails dir
    1. cd unobtrusive-shout-wall
  3. Same as above
  4. Same as above
  5. Same as above
  6. Same as above
  7. Since we are going to use jQuery (unobtrusiveness is *not* a property of jQuery, you can be just as unobtrusive with Prorotype - but I switched to jQuery just before learning how, and now I am lazy to go back check out how in the ‘prototype unobtrusive’ directory in the github repository), you have to download jQuery with some basic effects, as well as an AJAX form handling library (still from the directory unobtrusive-shout-wall - Get it from pastie):
    1. curl http://jqueryjs.googlecode.com/files/jquery-1.3.1.min.js > public/javascripts/jquery.js
    2. curl http://www.malsup.com/jquery/form/jquery.form.js?2.28 > public/javascripts/jquery-form.js
    3. curl http://view.jquery.com/tags/ui/latest/ui/effects.core.js > public/javascripts/effects.core.js
    4. curl http://view.jquery.com/tags/ui/latest/ui/effects.highlight.js > public/javascripts/effects.highlight.js
    and replace
    1. <%= javascript_include_tag :defaults %>
    with
    1. <%= javascript_include_tag ‘jquery’ %>     
    2. <%= javascript_include_tag ‘jquery-form’ %>
    3. <%= javascript_include_tag ‘application’ %>
    4. <%= javascript_include_tag ‘effects.core’ %>
    5. <%= javascript_include_tag ‘effects.highlight’ %>
    in the layout file.
  8. Same as above
  9. Same as above
  10. Same as above - just delete “remote” from the name of the helper, i.e. use a standard Rails view helper, form_for
  11. Same as above
  12. Since we are not relying on Rails to do the rendering for as via a template file, we return the html chunk that we will render from Javascipt. So your create action should look like (Get it from pastie):
    1. def create
    2.   @message = Message.create(:author => params[:author], :message => params[:message])
    3.   render :partial => ‘message’, :object => @message
    4. end
  13. Now comes the fundamentally different part - instead of using RJS to respond to the create action, we move all our code to application.js (Get if from pastie):
    1. $(document).ready(function() {     
    2.   $("#message-form").ajaxForm({success: handleNewMessage});
    3.  
    4.   function handleNewMessage(response, statusText) {
    5.     $("#messages").prepend(response).effect("highlight", {}, 1500);
    6.   }   
    7. });
    I don’t think so that this code is particularly more complicated or hard to understand that the RJS one. Everything is inside the ready() function, which means that it’s only run once the document is properly loaded. Then we declare that “#message-form” is an AJAX form, and that upon successful submission, the handleNewMessage() method should be called. And if that happens, we add the response (which is the return value of the “create” action) to the “#messages” div, just as we did in RJS. Then we apply the yellow fade! w00t!
  14. Same as above

(You can check out the code used in this post from it’s github repository).

Conclusion

As you can see, the only real difference between the obtrusive and non-obtrusive version is in the last 2 points (downloading and including the jQuery header files can be easily solved with Rails templates): instead of leaving the rendering part to Rails, we return the response as a string and dynamically insert it from jQuery. With about the same effort, we kept all the Javascript code in application.js, which is much cleaner this way (you can open up 1 file and check out all the JS/AJAX behavior in one place), especially after introducing a lot of Javascript functionality into your code - in other words, for the same amount of work we got something much better. Please try to keep this in mind when you are working with Javascript and Rails the next time - believe me, it can save you from a lot of pain!

]]>
http://www.rubyrailways.com/dear-railsists-please-dont-be-obtrusive/feed/
RailsBridge is Born http://www.rubyrailways.com/railsbridge-is-born/ http://www.rubyrailways.com/railsbridge-is-born/#comments Mon, 04 May 2009 10:14:12 +0000 peter http://www.rubyrailways.com/?p=430 rails_bridge.pngI surely don’t have to introduce last week’s Ruby/Rails earthquake to anyone by now - it has been covered by a boatload of blogs (including this one), analyzed, argued over, rebutted, reddited, dugg and whatnot - suffice to say, it’s time to move on. It was a rather unpleasant drama piece, but fortunately it shed light on some problems the Ruby/Rails communities are facing, and (besides the ensuing trollfest and pointless arguing) it had a pleasant side-effect: a handful of people started to discuss how things could be made better, creating a small (and growing) but determined community: RailsBridge!

Say Hello to RailsBridge!

RailsBridge’s mission is “To create an inclusive and friendly Ruby on Rails community” (check out details on the homepage). Everyone is welcome to participate - with ideas, suggestions, design, code, new project proposals or just about anything that would make Rails a more open and accepted technology and community.

It’s very important to understand that we are not trying to form yet another oh-my-god-we-are-so-awesome Rails group of uber-hackers which looks down on everyone not in it’s ranks - for two reasons, at the very least:

  • RailsBridge is open to anyone! - you don’t have to be a Rails core commiter, coder with 20 years of experience or a renowned Rails blogger - it’s enough if you’d like to make the Ruby/Rails scene more welcoming in any way
  • We are trying to promote the exact opposite philosophy - we acknowledge that Rails’s image is somewhat tarnished because of the “rock star” attitude and we’d like to show by our actions that we are working on this and will eventually turn Ruby and Rails into a very welcoming and enjoyable community

Surely, this is quite a venture - our mission statement sounds great, but everyone can do the talking on just about whichever Gordian Knot out there, be it world hunger, world peace or friendly Rails. We’ll have to demonstrate that we mean serious business, and that’s why we need you - everyone’s ideas, insights and help matters! Check out the RailsBridge homepage to learn more about what are we up to and how to get involved.

]]>
http://www.rubyrailways.com/railsbridge-is-born/feed/
Rails *is* (still) a Ghetto http://www.rubyrailways.com/rails-is-still-a-ghetto/ http://www.rubyrailways.com/rails-is-still-a-ghetto/#comments Mon, 27 Apr 2009 11:28:51 +0000 peter http://www.rubyrailways.com/?p=411 nice_ass.png

While I know the title is both asking for trouble (because of the now anecdotal original article with a similar title) and flamebaity, please read on - my goal is not to get some great stats but rather to know your opinion about the situation and discuss the possible solutions of the problem.

How it all started…

I would not like to re-iterate what has been said on several blogs, just to summarize: Matt Aimonetti, member of the Rails Activists, gave a presentation at GoGaRuCo which contained sexually explicit images (according to some - I am not here to judge whether that’s true, and it doesn’t matter anyway, as you’ll see in the rest of the post).

I am not really discussing whether it’s appropriate to have images of nude chicks in your presentation at a Ruby conference (I think it’s not, it’s unprofessional etc. - but that would be a matter of a different post Update: Someone summed this up in the article’s reddit thread nicely: If you’re a Rails programmer, or a Ruby programmer, and you don’t decry this sort of thing, you have no business calling yourself a professional. It doesn’t matter how large your website is, how easy it was to write, how much better it is over PHP or ASP.NET or J2EE; by definition, you do not belong to a professional community. That’s all there is to it. It’s incumbent on every Ruby programmer to either reject this sort of misogynistic sewage, or accept that you’re never going to advance the promotion of Rails in the public perception because members of the community still think it’s edgy or cool to put pictures of strippers in their public presentations. And here’s a hint: if your decided reaction is to talk about how unimportant this is, how much it doesn’t matter, or how much it doesn’t offend you personally, you probably don’t understand professionalism at all.) because sadly, I think there are far bigger problems here than that - shedding light on them is the real purpose of the article, not talking about pr0n at GoGaRuCo again.

Would You Walk Into a Hindu Temple with Your Shoes on?

hindu_temple.pngI have been living in India for 2 months last summer, working on a Rails startup. Maybe I am odd or something, but I knew that I had to remove my shoes when entering a Hindu temple, and no one had to convince me (what’s more, I didn’t even think about it for a second) wether this is the right thing to do, why is it so, whether I should do otherwise etc. This is a similar situation - I just don’t do X when speaking at a conference, if I suspect that X makes feel even one person in the room uncomfortable, whether because of his gender, race, nationality, Ruby/Rails skills, penis size or what have you - regardless whether I think it’s fine for me, my wife, for other members of the community and/or the majority of the room.

The trick is, how does a hindu feel when I enter a temple in footwear (even if that is perfectly acceptable in my country, culture, family, friends) - it’s perfectly irrelevant how do I feel in the given situation. Using the previous paragraph, try to apply this to a Ruby/Rails conference.

Shit happens…

Until this point in the story, I see no problem at all, and could even agree with the guys asking “what’s wrong with you, don’t make a fuss out of nothing” - the pictures Matt used are non-problematic in my book, and he had no idea they are problematic in anyone’s book - theoretically it could have worked, but the point is, it did not. Some members of the Ruby community got offended, and here our story begins.

…and hits the fan

One of the real problems is that after this has been pointed out, Matt still keeps answering “As mentioned many times earlier, I don’t think my presentation is inappropriate.”. As I mentioned two paragraph above, it doesn’t matter what do you think, unless of course, you don’t care about offending some members of the community. In that case you should not try to apologize at all. However, if you are trying, reciting “I don’t think my presentation is inappropriate” will not put and end to the discussion. It just doesn’t work. Why can’t you just simply apologize, admitting that this was a bad move (because it offended some, not because porn, sexual images or whatever in presentations are bad, per se) and finish the discussion?

Rails is Still a Ghetto

However, in my opinion that’s still not the worst part of the story, or to put it differently, some members of the Rails community still found a way to make things worse, by applauding to all this:

dhh_pr0n_is_great.png

OK, you say, we are all used to DHH’s style, this is just how the guy is. That’s (kind of) cool, but I heard that most of the Rails core team (and obviously Matt himself) has the same opinion - and that’s a much more serious problem, because it means that a Rails activist, backed by DHH and other Rails core members finds all this OK, despite of the fact that numerous people in the community voiced their opinion otherwise.

This is not about being a closed-minded prude, shouting for police and suing everyone using sexually explicit images in a presentation. This is not even about women, as I have seen both males and females on either side of the fence. This is about mutual respect - I don’t agree with you, but respect your feelings. Or not, as demonstrated in this case.

So Rails continues to be the most socially unacceptable framework - associated with arrogance, elitism and whatnot in the past - now add pr0n images in presentations. Thankfully RailsConf is held in Las Vegas, and that should calm down all the people who associate Rails with all this crap :-). The real problem is that people associate you with the tools you are using - think Cobol, PHP, Java… or Rails. By being part of the Rails community people associate me with Railsy stereotypes automatically, which aren’t nice at all right now.

I hear you, dear creme-de-la-creme Rails (core) member, I know you don’t give a shit, and you think this is all prude babbling - because your hourly rate is more than some of us earn in a day, and you’ll be sought after even if Rails will have a much worse image than it has now. But 99.9% of us are not in the ‘circle of trust’ and would be happier if Rails would not be constantly associated with a ghetto.

MINASWUBN

In case you are wondering what does the acronym stand for, it’s “Matz is Nice And So We Used to Be Nice”. Unfortunately, the stuff I don’t like about the Rails community is sneaking into Ruby too, it seems, as the above case demonstrates. Besides this, the count of aggressive comments and reactions on various blog posts is really disturbing to me. Please (at least Rubyists) try to avoid being contaminated by all this shit and stop thinking you are cool because you can swear on a forum (always in anonymity). You don’t have to be a douchebag just because you are a Rubyist / Rails coder, as surprising as this might sound to some.

Conclusion

I think “incidents” like this and getting more and more antisocial members are inevitable by-products of growth in a community. The questions is, whether, and if, how, do we stop them. The problem is that it seems to me the Rails “top management” doesn’t want to stop them (what’s more, even encourages them) in the first place (please prove me otherwise - maybe I don’t see the full story - I’ll be the happiest to admit that I am talking bullshit).

I have to admit I have no clue what would be the right move - burying our heads in the sand and pretending everything is fine is not. Please leave a comment if you have an idea or anything to add.

]]>
http://www.rubyrailways.com/rails-is-still-a-ghetto/feed/
FOWA Dublin videos (including DHH talk) http://www.rubyrailways.com/fowa-dublin-videos-including-dhh-talk/ http://www.rubyrailways.com/fowa-dublin-videos-including-dhh-talk/#comments Tue, 31 Mar 2009 10:43:59 +0000 peter http://www.rubyrailways.com/?p=405 dhh-ftrw.png As promised, here’s a quick post about the FOWA Dublin videos which have been uploaded recently - including the most anticipated Doing a Start Up in the Real World (a.k.a. ‘Fuck the real world’) talk by David Heinemeier Hansson. If you watch only one video, make sure it’s this one :-).

I just got back from a wonderful Scotland on Rails 2009 so will post my experience later today (or whenever I’ll be able to catch up with all my chores - spent almost 1.5 week in England + Scotland so my TODO list is huge :-)

]]>
http://www.rubyrailways.com/fowa-dublin-videos-including-dhh-talk/feed/
Twitter Unveils New Premium Accounts? I hope not!!! http://www.rubyrailways.com/twitter-unveils-new-premium-accounts-i-hope-not/ http://www.rubyrailways.com/twitter-unveils-new-premium-accounts-i-hope-not/#comments Thu, 19 Mar 2009 10:18:19 +0000 peter http://www.rubyrailways.com/?p=395 twitter_post.png Update: I definitely jumped the gun with this one :-) It is meant to be a joke. Thanks god.

I hope this is a joke. A bit sounds like it, but it might be still true. I am really hoping it’s not!

The news (”Twitter Unveils New Premium Accounts“) is spreading like wildfire on twitter right now, making it impossible to even guess who retweeted who, but that doesn’t really matter anyway. What matters is that everyone in twitterverse is talking about it right now. I really do hope it’s just a scam, because I don’t like the idea at all… here’s why:

  • Raising the character limit - (this is the part that makes me think/hope it’s a scam) I believe twitter’s success is partly because of the ‘do less’ scheme. If you look at jaiku, plurk, pownce and a ton of other failed (or let’s put it like this: not as successful as twitter by a wide margin) microblogging services, who hoped to differentiate themselves from twitter (also) by adding a ton of other features twitter doesn’t have, didn’t succeed. I (and I believe I am talking for the most of the twitter users out there) love the service exactly because it’s a no-brainer: you have to squeeze some interesting information into 140 chars. That’s it. The story ends here.
    There are plenty of third party apps (several hundreds when I last checked) that add this or that on top of twitter, some of them actually very good. That’s a win for everyone: you can choose which service to use (often multiple sites are competing for the same type of service - competition is always a good thing!). Modularity is a good thing - not to mention that great services (like search, a.k.a. summize) are integrated into twitter later anyway.
  • Messing it up - you get random followers?!?! Why is that? I am already annoyed by the ‘quest for numbers’ “feature” of twitter - totally unrelated people following each other just to bump their follower count. This is kind of understandable, as the follower count is viewed as an universal number of influence/power on twitter, but still, why should you push information to people (or consume the information they are pouring onto you) if you are not in the same niche/field/market? This sounds really crazy.
    Anyway, how will those 20/100/1000 random followers be chosen? Will they accept that they have to follow someone? Bullshit meter +1. This really smells like hoax.
  • Elitism - the same concerns as with Kevin Rose’s latest brainchild, wefollow.com - the rich get richer, the poor get poorer. Invisible (and possibly otherwise great) people will remain undiscovered Good Will Huntings for good, while users already boasting thousands (or much more than that) followers will climb to even more higher places. How is this good for a community as a whole??!
  • Price - this is basically the B variant of “Elititsm”. Open source enthusiasts, students, researchers, a big part of developers (the group I am personally interested in) and a lot of others (you surely have a similar group with other interests) won’t be willing (and able to in some cases) to pay the $15/$50/$100 monthly fee - it’s just too much. $5 is OK for everyone, but that doesn’t buy you nearly anything. The other premium levels are just too much for most of people, again just pushing the elite to higher places.

I have a ton of other points, but the more and more I think about it, I seriously think this is a SCAM. I really love twitter and hope they’ll have a solid business model and will make a ton of money sooner or later, but please not this way. I am not even against premium accounts, or just paying a sensible monthly fee - would surely do that - but please stay with the roots and don’t promote elitism. Khtxbai!

]]>
http://www.rubyrailways.com/twitter-unveils-new-premium-accounts-i-hope-not/feed/
DHH: Fuck the Real World http://www.rubyrailways.com/dhh-fuck-the-real-world/ http://www.rubyrailways.com/dhh-fuck-the-real-world/#comments Tue, 10 Mar 2009 10:32:59 +0000 peter http://www.rubyrailways.com/?p=389 dhh-ftrw.png I planned to do a writeup on the talks @ FOWA Dublin, but Dave Concannon did such a great job that I could not add too much without re-iterating what he said, so I’d like to concentrate on just one talk instead, which totally blew me away: Creating Software in the Real World by David Heinmeier Hansson.

Let me start with a bit of background - as a Rails developer for almost 3 years now, this was obviously not the first time I heard about David, 37signals, their Getting Real principles, business practices etc. - however, this was the first time I have seen him live, delivering a great talk. And it made a huge difference.

If you happen to know me, you probably know that I am not a guy who gets ecstatic because someone is an alleged rock star, ninja, pirate or zen master, even if he happens to be author of something as significant as Ruby on Rails which I think is the greatest piece of software since Prince of Persia. I had my own reservations wrt David (a slew of blog posts about him suggest that he is kind of a controversial character to say the least: the potty-mouth Dane, the F-bomb terrorist who always has a curse or two up his sleeve for good measure, brings on the vitriol first and ask questions later etc. etc.) After seeing him perform live, I am quite sure that most of these negative comments are either taken out of context, coming from the sour grape camp or are just plain wrong. Sure, David is not a grail knight when it comes to defending his stance - that’s one of the reasons why he keeps building kick-ass stuff like Rails or Basecamp. He totally pwn3d the stage from the very beginning, and even if I wanted to be very critical, I just could not see that he is the douchebag suggested by his critics.

It also became clear to me that DHH != (only) Rails. While he is often primarily described as the author of the Rails framework, that’s a gross oversimplification of the big picture. I think Rails is “just” the side effect of David’s passion to create web apps in a getting real way. Above everything else, he is a guy with a vision who gets things done, no matter what does it cost - e.g. writing a web framework in Ruby (the language he found the most “getting real” style when he needed to implement Basecamp).

OK enough rambling - here is the summary of the talk (I certainly could not get everything, but I am trying my best)

  • “We don’t have 200k RSS subscribers because of my deliciously swirly hair” - a central question (asked also during the Q/A session): how on the earth did Basecamp and other 37signals products become so popular? All of a sudden, they emerged from nowhere! As David points out, it was not that ‘out of the blue’ as it looks like. When they started with Basecamp, they already had 2000 subscribers on their blog, Signal vs Noise, so they built a channel which through they could advertise themselves. This advice meshes with one of my favorite points from Getting Real which goes something like “Just start doing something”. Really. Start blogging. Creating/contributing to open source software. Get on twitter. Let your voice be heard! You probably won’t have thousands of listeners right away, that’s OK - it takes time. But you can start today!

  • “Fuck the real world” - probably the tagline this speech will be remembered for. Taken out of context, DHH critics have yet another flickr snapshot where they can demonstrate arrogant F-bomb usage, good for nothing. Bullshit. It was designed and “dropped” perfectly, kicking off the whole talk! David’s advice is to stop listening to “advice” which goes like “yeah, this is a great idea/concept/whatever, but it will not survive in the real world”. Sure, Rails didn’t look like a great idea when Java and PHP have been the bee’s knees. Today no one (except the hard-core sour-grape Java/PHP/COBOL fanboys) would argue that it made a big impact on how web software is developed (call it web2.0 if you like). David said that none of their current apps passed the “real world” (in the sarcastic sense) test - and look where they arrived.

  • “I didn’t start coding when I was 6, but 21, and Jason (Fried) started business school later too” - David de-bunked the myth that you have to be a “natural” to accomplish great things. True, quite a few of the IT related success stories start with “I got my first Sinclair ZX Spectrum/Commodore/Atari/Amiga when I was 4, started coding in xyzBasic at the age of 5, roocked fooBasic at 7 etc. While this is all great, and certainly a big help if one happens to become a professional coder later, it’s certainly not the only path to victory. There is no such thing as “starting out too late”. Just make sure you start today.

  • “Forget the advice that you shouldn’t build too simple software” - “Good bye to bloat”, “Simple, focused software that does just what you need and nothing you don’t” are rules 37signals are living by, not just pretending. If you check out their award-winning software, used by over a million people today, you’ll notice that despite of their age (several years) they are still simple pieces of focused apps. That’s one of the secret sauces of 37signals: if it works for them, why shouldn’t it work for you? The point is to create something usable, not bloated.

  • “Would I pay for this app?” - a great reality check they are asking themselves all the time. If you wouldn’t pay for such a product, why would anyone else?

  • “Running your own business = the power to say no - You should be able to say “no” and stick to your vision rather than trying to add all the bells and whistles required by the customers. Note that this does not mean you should refuse / reject all the requests - some of them are really great, but eventually you have to decide which ones to keep and which ones to boot (because they just don’t fit into your vision).

  • “startup is a category I hate - you have to build a business” - another great point. It’s so trendy to found start-ups today, it almost sounds like a game for grown-ups. (It’s not, I founded two of them myself and it was the hardest part of my professional life so far. Compared to a startup, regular freelancing / contracting feels like a walk in the park :-)). You have to plan for long term, have real goals, start making money as soon as possible (vs. wait for google or another Silicon Valley dude with a lot of money), get real. It’s not a game, it’s a business.

  • “You don’t need rock stars, but a rock star environment. Your employees are not stupid” - argues that the environment your company is in matters more than the individuals. With a great company culture where you respect and trust your employees (e.g. 37signal employees get a company credit card, with one policy - use it reasonably! wow) your team will live up to their full potential. By creating and nurturing an atmosphere of growth, you won’t have to micromanage everybody and everything - don’t treat your employees as idiots, because they are not.

  • “An idea is so small part of a business that it’s almost a rounding error” - So true. I have so many ideas right now, that it would take months to prototype them - but that would eventually become an endless process, because during prototyping I would get new ideas, etc. Ideas are cheap, everyone has them. The question is whether you have the skills and perseverance to make them happen.

  • “you have to build massive popularity slowly” - Probably my most favorite point of the talk. As a small business owner, startup founder and entrepreneur I found out on my own skin several times that it’s relatively easy to start something - be it a startup, a blog, an open source project, a client assignment, a relationship/marriage/organization/company/habbit/just about anything. The trick is to keep pushing with the initial vigor (at least) once you reach the plateau - for a long time, until the breakthrough comes (you finish your project, your blog gets picked up, your startup is featured on techcrunch, etc.) That’s one of the main things that sets successful ventures apart from non-succesful ones. Everybody has ideas. Everybody can start. A few of them can finish because it takes time and perseverance. You have to believe in yourself and your idea to make it through, as long as it takes.

Unfortunately this summary can’t capture the atmosphere of the talk - as far as I can tell, the room was on fire, everybody was charged up and motivated by this speech (I can’t imagine who wouldn’t be). For me it was worth the price of the conference alone. Massive thanks to David!

]]>
http://www.rubyrailways.com/dhh-fuck-the-real-world/feed/
FOWA Dublin - a Mixed Blessing http://www.rubyrailways.com/fowa-dublin-a-mixed-blessing/ http://www.rubyrailways.com/fowa-dublin-a-mixed-blessing/#comments Sun, 08 Mar 2009 23:45:28 +0000 peter http://www.rubyrailways.com/?p=380 fowa.png I am sitting on the plane flying home from Dublin, trying to summarize my thoughts about the Future of Web Apps conference. While I think that overall, FOWA Dublin was worth attending (because of the speakers, especially David Heinemeier Hansson, who surpassed all my (high) expectations - will post about it later), in my opinion it did not live up to its full potential. The most annoying thing is that just with a tiny bit of more effort it could have been an 5-star conference in every sense of the word - however it missed to deliver this additional plus, leaving a bad taste in my mouth.

I have seen blog posts/tweets raving about the conference - in a paradoxical way (given what I just wrote in the above paragraph) I can mostly agree with those posts too. The trick is whether you are judging the conference solely based on the content (in which case I can agree with the above blog posts) - or as a whole, including venue, wifi, organization, socialization, before and after parties, freebies, extras, all the bells and whistles. Using the latter method (and I see no reason why one should not) the conference was mediocre IMHO - a few thoughts why:

  • (almost) no wifi - After all, a conference centered around the web full of nerds with iPhones, notebooks and other wifi-hungry devices needs no wifi right? Wrong. (OK, the reality was more complex than that: there was some kind of “home wifi” but in practice that meant constant hunting for the signal which broke randomly after a few minutes)

  • crowd - A huge crowd (or too little space, if you put it like that) right from the very beginning; Arrived 30 minutes before the actual start, to experience an episode from the life of herrings in the lobby on my own skin, without the slightest idea of why couldn’t we enter the auditorium or what are we supposed to do (other than brewing in our own sweat and looking around to see more puzzled herrings)

  • the way the uni sessions were delivered - no microphone; very noisy from outside; people running around all the time, causing constant distraction;

  • no announcements of talks - (like someone running out to the foyer and shouting ‘hey guys we are starting in 5 minutes!’) - half of the people still in the foyer, resulting in slow, continuous trickling into the auditorium, again causing a lot of distraction (probably less distracting the closer you sit to the stage, but at the upper end it was really annoying). The doors were open for some reason, so constant murmuring from the foyer.

  • No freebies - for this price, at least a coffee or two (and maybe I am not too demanding to add something like snacks/muffins/mineral water?) would have been nice. Ridiculous prices at the bar (well, quite normal compared to Dublin - 2-3 EUR for a tea, 4-5 EUR for a coffee, 5-6 EURs for a pint of Guiness, you get the idea)

  • seats - people standing around; though there were theoretically enough seats, de facto about a dozen or more people have been standing around all the time, which felt weird to me, even though I managed to get a seat somehow during the whole conference.

  • no sockets - If you were lucky enough to sit close to one of the few (ok, make it a dozen - for 400 ppl!) sockets in the wall, you could recharge your laptop. Otherwise, you have been out of luck.

  • a huge rush - I had the feeling that the organizers wanted to pack as much action into one day as possible, which theoretically sounds great, but IMHO it didn’t work out that well in the practice; I missed the beginning of two talks and one full talk after the lunch break because the breaks were barely enough to accomplish anything, be it buying snacks/coffee, use the toilet (1 working toilet for hundreds of guys - great idea) or to grab a proper lunch at a restaurant.

  • it was overpriced for what we got - (or we got too little for an OK price) - c’mon, 400 people at an average price of 150 EUR, is 60,000 EURos, + sponsors like Sun and Microsoft, and not even a fucking cup of cofee? We organized EuRuKo in Prague last year for 20EUR / dude, had Matz, the creator of Ruby as well as a roster of other Ruby celebrities, conference t-shirts and a slew of other conference souvenirs, industrial strength wifi, catering (several tea/coffe/snack breaks, hot food for lunch) for 2 full days, free coffee and beverages, and even some free beers (cheers for Brightbox) all this in the heart of Prague. I repeat it again - for EUR 20!

  • Little room for socialization (both in physical and abstract sense) - no before-event party (e.g. compare it with Scotland on Rails - three weeks to go, but I know about almost all the attendees, when and where are we going for a whisky (pre-, during- and post-conference), who is staying where, arriving when, going for a sightseeing tour with an option to join them etc. All the organizers did to make this happen was they set up a google groups mailing list and a twitter account, updated with great info every now and then, enabling the attendees to augment it with their own stuff (e.g. when are we going to have a boatload of whisky)) OK, this is not entirely an organizational problem, but still, all the conferences I went to so far addressed socialization in some way.

  • after-party - Some of the guys were raving about the after-party - well, I think it was poorly organized too. I went there on time, and had no idea where the FOWA-party “crowd” is - I have seen random micro-bunches of probably-FOWA attendees scattered around the huge (otherwise excellent) Dandelion bar. Asked a few of them about the party, they were just as clueless as myself. Ok, so I left to grab something to eat to the nearby TGIF, but the situation got even worse when I came back. The dispersion of probably-FOWA-micro-bunches-or-lone-rangers went up significantly, so after a few minutes of strolling around I left. Maybe I was just unlucky and popped up at times when everybody was at toilet / had a quick smoke outside or whatever, but some more info (an A4 sheet of paper with ‘we are here’ perhaps) wouldn’t hurt.

Wow - re reading what I just wrote makes FOWA Dublin look really bad - but unfortunately I don’t know what should I remove from the above. These little (or sometimes not so little) things really added up, and fscked up the whole atmosphere. A little more organization and polishing would have solved 80% of the problems.

I am going to summarize a few of the talks I enjoyed in a follow-up post - now I am too tired for that - spent 6 extremely exhausting days in Dublin so need to get some sleep first!

]]>
http://www.rubyrailways.com/fowa-dublin-a-mixed-blessing/feed/
“I guess Ruby is over: it Was Fun While it Lasted.” http://www.rubyrailways.com/i-guess-ruby-is-over-it-was-fun-while-it-lasted/ http://www.rubyrailways.com/i-guess-ruby-is-over-it-was-fun-while-it-lasted/#comments Thu, 05 Mar 2009 00:15:48 +0000 peter http://www.rubyrailways.com/?p=366 ruby_sad.gifUpdate: As several guys pointed out in the comments, Tim’s remark which basically pulled the trigger was sarcastic - I guess have to re-calibrate my sarcasm meter. So you need to replace “Tim” and whatever he said with a different guy and his random quote. There are plenty of them out there these days, so the choice should be easy :-).

This rant was in the works for quite some time - I ditched it at least two times already, convincing myself that there is no use to get into language wars and similar nonsense… but people didn’t let the issue go (i.e. that Ruby jumped the shark / it started to suck for some reason etc - most recent example being a tweet by @timbray) so get ready for some grandiose rantbling!

Tim Bray: “I guess Ruby is over…”

Srsly? By what measure? Actually when did it start? Why exactly then? Again, by what measure? What does ‘over’ mean at all? Says who?

I am currently reading “The Black Swan: The Impact of the Highly Improbable” from Nassim Taleb. There is a section describing Tim’s logic perfectly:

“By a mental mechanism I call naive empiricism, we have a natural tendency to look for instances to confirm our story … - these instances are always easy to find. You take past instances that corroborate your theories and treat them as evidence… I can find confirmation for just about anything, the way a skilled London cabbie can find traffic to increase the fare, even on a holiday”

… or the way Tim can find a bogus evidence for Ruby’s alleged decline, whatever that means. I am wondering where have the current “ruby jumped the shark” guys been 3 quarters ago when Ruby books have been on a roller coaster riding up with the speed of light?!?!

Naive empiricism is everywhere

Guess what, I am guilty of naive empiricism too: I wrote an article stating the opposite of Tim’s tweet, based on similar, but opposite O’Reilly data (i.e. Ruby book sales on the rise). Why? Because I have been a Ruby/Rails zealot back then already, that’s why! And I wanted to see Ruby on the rise, and did not really care whether my claims were objective (I wanted to see that they were objective - meta-naive empiricism FTW!)

Another great example of naive empiricism is the ‘CDBaby: from Rails to PHP‘ vs ‘MuxTape: from PHP to Rails‘ 2-part saga: the funny thing is that both Derek and Luke argue very convincingly and charismatically about the exact different side of the same coin: why the move from framework X to Y has been the best idea since sliced bread, how it saved their ass, pushed productivity to the ends of the earth… arriving at a total opposite conclusion using the same reasoning.

Another bogus reasoning I hear a lot: Python is used in google so it’s > Ruby! Unfortunately enough for the guys treating this fact as a royal flush , Ruby is used in NASA, by some of the smartest folks in Ruby-land. So what?! Does this mean Ruby > Python (or at least is equal to gogle <=> NASA)? Not at all (In my opinion Ruby > Python actually, but 1) this is a personal preference thing 2) it has nothing to do with google vs NASA 3) is a topic of a different rant, which possibly won’t be written as I grew tired of lang wars fought with flame throwers).

Or take github: currently 31% of the code living there is Ruby (and you can’t really argue that by now, github matters - it’s not just a hobby project of 2 guys tired with their original startup any more). So according to this measure, everyone start learning Ruby!

but Tim argues instead:

“…Everyone start learning C#”

This is the second part of @timbray’s rather questionable tweet… and here is why:

Comparing the need for Ruby workforce to the C# one is like comparing the need for planes to that of cars. No correlation.

C# is usually used…

  • for enterprisey stuff
  • to write big, monolithic apps
  • by big teams for long-term projects
  • by BigCO running on a large budget
  • in M$ shops

Ruby/Rails is the total opposite… it’s usually used…

  • for coding quick web apps / internal DSLs / domain specific stuff
  • to craft lean, focused apps, interoperating with each other
  • by small, agile, flexible teams, sometimes lone rangers
  • Usually smaller budget (direct consequence of the first point)
  • in shops with totally different culture compared to that of M$

Both lists could grow unbounded if I cared to come up with more points.

So Tim is essentially saying ‘no need for agile teams cranking out top notch (usually web-based) software fast - everybody jump on the Titanic (the safe 9-5 world of enterprise apps in one of the cubicles of BigCO). Sorry, but this is utter BS. There will be always a need for lean, agile, quick teams. Following this logic, you should abandon the Python/Django ship too. And btw guess what - the Titanic sunk in the end, no matter how safe it originally was.

So where’s Rails?

It’s not clear to me where is Rails (and a slew of other widely used frameworks/software produced in Ruby) in Tim’s picture. The thing is that Ruby is tied to Rails just like the US economy is tied to just about everyone else’s economy around the world. If Rails prospers, so does Ruby - a kick-ass r41lz h4xx0r is a kick-ass Ruby h4xx0r with knowledge of Rails after all.

However, it looks like there is need for Rails coders: Tom Mornini, one of the founders of Engine Yard, the leading Ruby/Rails hosting states that good Rails developers are very scarce. And while Rails developers will be a scarce commodity, Ruby developers will be too.

Ruby isn’t Fun anymore… wtf?

This is the original part of the rant, from the time when more “ruby/rails sucks” articles popped up in a quick succession, followed by a grandiose trollfest on various social sites, and eventually meta-ranting (my personal favorite).

Apples and Oranges Strike Again

I am a bit confused after reading all this outburst: I seriously think ‘fun’ vs ‘mainstream’, ‘imperfect’ (or even ‘buggy’), ’slow’ etc. are orthogonal problems. Why should be Ruby less fun than it ever was because now it has more acceptance / users / enterprise penetration and/or it’s slow / 1.9 is not a big deal / it leaks memory (fill in the other pain points from the rants)??! This just doesn’t make any sense. Ruby is fun and it has some problems to address. These two are not contradictory statements at all. It’s immense fun to be with my 2-year old daughter, though she is sometimes hard to handle - so I should say it’s no fun anymore?!?

“Ruby isn’t fun any more for me” is a totally different claim from “Ruby isn’t fun any more” (in general). I don’t give a shit if Ruby isn’t fun any more for you, but please, don’t describe it as community- or language-wide phenomenon. kthx.

Conclusion

You like python? Great! Putting bread on the table coding in Java? Cool. You’d like to play around with bleeding edge stuff (clojure/scala/erlang etc.)? All the better.

Ruby is slow? The syntax is obscucre? You don’t like Rails/DHH/fanboys/TextMate/Ruby/arrogant douchebags/whatever? Ruby is not fun for you (any more?) Too bad, so sad - however, this doesn’t alter the fact that Ruby is immense fun for me, and a whole community of people, and no ranting will change that, no matter how hard you are trying.

I am not even arguing that Ruby is better than X - I am far beyond that point already (after having my share with some Java vs Ruby flamewars). I am just arguing that people should stop tweeting / blogging about nonsense underpinned with ‘evidence’ just because they want to see the world that way.

]]>
http://www.rubyrailways.com/i-guess-ruby-is-over-it-was-fun-while-it-lasted/feed/
Advanced Twitter Queries with the Twitter Gem http://www.rubyrailways.com/advanced-twitter-queries-with-the-twitter-gem/ http://www.rubyrailways.com/advanced-twitter-queries-with-the-twitter-gem/#comments Thu, 26 Feb 2009 00:56:32 +0000 peter http://www.rubyrailways.com/?p=360 twitter_post.pngI wanted a reliable way to find out a few things about my twitter account (for example which of the users I am following are not following me back) - unfortunately the third party apps out there are not always very reliable, do not exactly do what I want/as I want so I decided to check out how easy it is to hack up a more advanced query using a Ruby twitter API wrapper. It turned out that it couldn’t be easier!

There are several gems wrapping the Twitter API out there - I started to use the ‘twitter’ gem from John Nunemaker and I am perfectly happy with it so far. John did a great job supporting all the features offered by the API - it’s a different question that the API, like twitter itself, is quite minimalistic. For example I have not found a way to get all my followers/friends easily (drop me a comment if I am missing something) so I monkey-patched this into the module in a generic way:

  1. module Twitter
  2.   class Base
  3.     def all_entries(method, options = {})
  4.       all_entries = [] 
  5.       next_100 = self.send method, {:page => (current_page = 1)}.merge(options)
  6.       while (next_100.size != 0) do
  7.         all_entries << next_100
  8.         next_100 = self.send method, {:page => (current_page += 1)}.merge(options)
  9.       end 
  10.       all_entries.flatten
  11.     end
  12.   end
  13. end

for example you can call connection.all_entries(:friends) to get all of your friends, given that you set up a connection to your account (I found only a method which returns your first 100 friends - didn’t spend too much time with the documentation though - agin, drop me a message if I overlooked something).

I have added a bit of syntactic sugar to be able to call connection.all_friends instead of connection.all_entries(:friends):

  1. module Twitter
  2.   class Base
  3.     alias_method :throw_method_missing, :method_missing
  4.  
  5.     def method_missing(method_name, *args, &bloke)
  6.       if (method_name.to_s =~ /^all_.+/)
  7.         all_entries(method_name.to_s[/all_(.+)/,1], args[0] || {})
  8.       else
  9.         throw_method_missing(method_name, *args, &bloke)
  10.       end
  11.     end
  12.   end
  13. end

Here we ensure that only method calls that start with all_ are handled by all_entries, the rest is throwing a method_missing since we are not interested in handling those messages.

Now it could not be easier to implement the function I originally intended to build: list of users who are not following back.

  1. class Array
  2.   def names
  3.     self.map{|u| u.screen_name}
  4.   end
  5. end
  6.  
  7. module Twitter
  8.   class Base
  9.     def not_following_back
  10.       all_friends.names - all_followers.names
  11.     end
  12.   end
  13. end

That’s all there’s to it (I am not a big fan of monkey patching core classes btw ; but in this case, adding the names() method to the Array class just made the method I intended to originally implement much cleaner so I rolled with it). Note that since subtraction is a non-commutative operation, all_friends.names - all_followers.names is not necessarily the same as allfollowers.names - allfriends.names. This is how the final code looks like:

  1. require ‘rubygems’
  2. require ‘twitter’
  3.  
  4. connection =  Twitter::Base.new(‘yourname’, ‘yourpass’)
  5.  
  6. class Array
  7.   def names
  8.     self.map{|u| u.screen_name}
  9.   end
  10. end
  11.  
  12. module Twitter
  13.   class Base
  14.     alias_method :throw_method_missing, :method_missing
  15.  
  16.     def method_missing(method_name, *args, &bloke)
  17.       if (method_name.to_s =~ /^all_.+/)
  18.         all_entries(method_name.to_s[/all_(.+)/,1], args[0] || {})
  19.       else
  20.         throw_method_missing(method_name, *args, &bloke)
  21.       end
  22.     end
  23.  
  24.     def all_entries(method, options = {})
  25.       all_entries = [] 
  26.       next_100 = self.send method, {:page => (current_page = 1)}.merge(options)
  27.       while (next_100.size != 0) do
  28.         all_entries << next_100
  29.         next_100 = self.send method, {:page => (current_page += 1)}.merge(options)
  30.       end 
  31.       all_entries.flatten
  32.     end
  33.  
  34.     def not_following_back
  35.       all_friends.names - all_followers.names
  36.     end
  37.  
  38.   end 
  39. end 
  40.  
  41. p connection.not_following_back

You can download/check out the code here - do not try to copy & paste it from the text as it will be b0rk3d.

In part 2 I’d like to set up a small Sinatra app showing the above users in a list - displaying their avatar, screen name and real name, plus a link to remove them if you decide so.

]]>
http://www.rubyrailways.com/advanced-twitter-queries-with-the-twitter-gem/feed/
Ruby’s Most Underused Keyword http://www.rubyrailways.com/rubys-most-underused-keyword/ http://www.rubyrailways.com/rubys-most-underused-keyword/#comments Fri, 06 Feb 2009 17:25:00 +0000 peter http://www.rubyrailways.com/?p=343 redo.pngI spent the first 2+ years in Ruby-land without even knowing about the probably most underused (and underrated) keyword of the language: redo. Even after I came across the first example and liked it immensely, I could not come up with another use for it, so I threw it to the bottom of my toolbox. Then I found another example, and another one - so I came to the conclusion that redo might be a valuable keyword in your Ruby arsenal after all - it is one of those things which you rarely need, but if you need it, it’s a perfect solution which would be cumbersome to replace with other constructs.

Break vs Next vs Redo

I am sure everyone is familiar with redo’s cousins: next and break. While next and break allow you to skip an iteration, resp. skip the rest of the remaining iterations altogether, redo does not skip anything - it ‘restarts’ the same iteration. In other words, while next transfers control to the end of the iteration block, redo ‘jumps’ to the beginning of the block. Let’s see an example, where redo is used to recover from an input error (code from “The Ruby Programming Language”):

  1. puts "Please enter the first word you can think of"
  2. words =%w(apple banana cherry)
  3. response = words.collect do |word|
  4.   print word + "> "
  5.   response = gets.chop
  6.   if response.size == 0
  7.     word.upcase!
  8.     redo
  9.   end
  10.   response
  11. end

The trick is that whenever the user enters an empty string, the block is restarted with redo, asking the same ‘question’ until the user enters something that makes sense to the system.

A Real Example - Tail Recursion

As of now, Ruby does not support tail recursion optimization, so you either have to write the function in a non-recursive (i.e. iterative) way yourself, or suffer the consequences of a full stack… or use redo!

I recently came across Magnus Holm’s article on this problem. Magnus provides an elegant solution using redo:

  1. define_method(:acc) do |i, n, result|
  2.   if i == -1
  3.     result
  4.   else
  5.     i, n, result = i - 1, n + result, n
  6.     redo
  7.   end
  8. end
  9.  
  10. def fib(i)
  11.   acc(i, 1, 0)
  12. end

Magnus even worked around a redo perk: “The redo statement restarts the current iteration of a loop or iterator”. That means he couldn’t define a method with “def”, since that neither involves a loop nor an iterator. Maybe a less esoteric way relying on the same fact would be to use a lambda:

  1. def fib(i)
  2.   acc = lambda do |i, n, result|
  3.     if i == -1
  4.       result
  5.     else
  6.       i, n, result = i - 1, n + result, n
  7.       redo
  8.     end
  9.   end.call(i, 1, 0)
  10. end

Golf Time

Here is a Ruby golf riddle, which I have no idea how could be made this short (42 characters) without redo (via coderrr):

"Generate a random string of length 4 or more consisting of only the following 
set of characters: a-z, A-Z, 0-9"

Here is the winner, Magnus Holm’s solution (The name sounds familiar? Right, the previous example was from him too - he understands the power of redo for sure :-)).

  1. (0..9).map{rand(?z).chr[/[^_\W]/]||redo}*""

The above solution might not be instantly crystal clear - so let’s break it down a bit:

  1. rand(?z) is equivalent to rand(122) (but shaves off a character!)
  2. rand(?z).chr turns the random number into a string (equivalent to its ASCII code, i.e. 65.chr == “A” etc)
  3. the regexp /[^_\W]/ means the negation of ‘everything but underscore or non-word character (digits and numbers). To put it another way, accept word characters but not an underscore. (\w includes underscore, so we need to get rid of that)
  4. rand(?z).chr[/[^_\W]/] acts as an identity function for letters and digits, but returns nil for everything else. So “a”[/[^_\W]/] == “a” but “@”[/[^_\W]/] == nil. “_”[/[^_\W]/] also returns nil.
  5. And now comes the redo trick: rand(?z).chr[/[^_\W]/] || redo will restart the block until a random character/letter is not found! w00t!

While one might argue that golfing examples are contrived by definition, I don’t always agree: the [/[^_\W]/] is a neat trick to get numbers/letters from a string only, as well as the use of redo is valid and non-contrived.

Conclusion

As demonstrated above, redo can be used in a variety of situations to produce an elegant solution that would look much more cumbersome without it. Of course all the usual stuff applies: don’t overuse, abuse etc. etc.

If you have any other interesting cases for redo, leave a comment - I’d love to see some more :-)

]]>
http://www.rubyrailways.com/rubys-most-underused-keyword/feed/