How do I smell Ruby code?

How do I smell Ruby code?

Understanding the worst of code

This guest post is by Timon Vonk, who is a self-employed Ruby enthusiast and standard nerd with an edge. He has worked with Ruby for several years, but is well-known with many other (programming) languages. Also likes martial arts, loud music, varying quantities of booze and a good scotch.

Introduction

Timon Vonk Writing bad code isn’t a bad thing. Not understanding the problem you’re trying to solve any better after having written that piece of code is. Fortunately, that happens far less often. In this article I hope to give a better understanding of Ruby code by going into Ruby specific code smells. We’ll start with some simple examples that are common in all programming languages – they just need to be covered – and then dive into some Ruby specific smells.

So what is that smell?

The term was coined in the 90s by Kent Beck on WardsWiki (one of the first wikis around) and has been popularized ever since. A code smell is a hunch, not necessarily measurable, that the code you’re looking at can be improved in some way. This process of improvement is called refactoring, as you might know. And as far as refactoring is concerned, there is no time like now, don’t leave open ends; it’s a bad habit.

The Basics

Let us give a quick rundown on the more basic code smells:

  • Duplicated code, if you see any, is almost always a bad thing. We’ll get into this part a little later.
  • Multiple method / class responsibility is always a bad thing. Try factoring out your solution in multiple methods. It will make you’re code more readable and a lot better maintainable. Large methods and classes are a dead giveaway for this as well.
  • A class should never use more methods from other classes than from itself. Why is it even there?
  • A child class should always honor the contract of the parent class, i.e., be a kind of that class. Check out the Liskov substitution principle for more information.
  • If a class hardly does anything, why is it there?
  • Does your solution have a more simple approach? Complexity can be a reason of pride for some – if not most – coders, but too much makes it terrible to understand, especially later on.
  • Non-descriptive or too long identifiers or names are a good sign that either you can’t define the responsibility of the code, or you have a hard time with naming conventions.

Simple, easy smells should give a good start on fine tuning your code. However, every language has its own specific quirks. Let us take a look at Ruby.

Calling eval on user input or unchecked code

input = "'rm -rf /'"
klass =  eval input

Of course this is bad. I hope it doesn’t need any explanation. Try not to use eval, but instance_eval instead. And if you use either, make sure that the code you eval is secure — never eval user input directly.

Nested blocks without added value

array = [["banana", "apple"],["pineapple","beer"]]
# And I want to call reverse on each element, I could do
array.collect { |sub_array| sub_array.collect { |subsub_array| subsub_array.reverse }}
# But this is much nicer
array.collect { |sa| sa.collect(&:reverse) }
# => [["ananab", "elppa"],["elppaenip","reeb"]]

The reason is simple enough. Your code is more readable, and that’s what we all want. So what about nested multi-line blocks? Check it out, big chance your solution is the root of this particular evil.

Code similarity

def post_to_site(data)
  url = build_url(data)
  response = RestClient.post(url)
end

def get_from_site(data)
  url = build_url(data)
  response = RestClient.get(url)
end

def delete_from_site(data)
  url = build_url(data)
  response = RestClient.delete(url)
end

You can easily solve this lump of code by introducing some meta-programming:

def  response_from_site(data, method = :get)
  url = build_url(data)
  response = RestClient.public_send(method, url)
end

This gives you a clean, nicer method. And it’s readable too! Isn’t that nice?

Long, repetitive and cluttering statements

Often enough you have similar parameters that call similar methods. For instance, you might need to check on some parameter and call the associated method. Or even simpler, you might need to check if a certain user input matches your criteria. I prefer a simple rule of thumb, if you’re working with any sort of collection or set, the functional approach is always cleaner, more simple and most definitely faster. The point is not to dictate when and whether you should prefer the functional approach, just that you understand that long lines of repetitive clutter screw up your code.

Take the following example:

input = "english"
case input
when "english"
  puts "English, ***, do you speak it?"
when "french"
  puts "Baguette!"
when "dutch"
  puts "I only smoke *** when it's free."
else
  puts "Dunno"
end

You can imagine in complex applications that this goes on and on. I actually see it happen a lot and it’s not necessarily bad. However, it’s hard to maintain and in more complex situations it can get really hard to read through. I’ve seen loads of Rails applications where they use just this to check on a particular parameter. Really ugly!

Since it seems like you’re white listing, one way to solve it would be to use a hash with input:result.

whitelist = {
  "english" => "English, ***, do you speak it?",
  "french" => "Baguette!",
  "dutch" => "I only smoke *** when it's free.",
  "other" => "Dunno."
}

if whitelist.has_key?(input)
  puts whitelist[input]
else
  puts whitelist[other]
end

It’s always important to be proud of the code you write. It really helps if it doesn’t smell. And I hope this article helped you do that.

Feel free to ask questions and give feedback in the comments section of this post. Thanks!

You might want to read a related article:

Technorati Tags: , ,

Weave Mazes: Your Take?

Later this week I’m going to post an article about how you might implement “weave mazes”, like this one:

weave maze

This is a maze where some of the passages “weave” over or under other passages. It’s a type of 3D maze, but very constrained (mostly for esthetic reasons):

  • Passages may only move under or over each other when they are perpendicular to each other.
  • A passage may not terminate (dead-end) either under or over another passage.
  • Passages may not change direction either over or under another passage.

Before I post my implementation, though, I wanted to get you thinking: how would you implement a weave maze?

#255 Undo with Paper Trail

Undo and redo behavior is easy to add with a versioning gem such as Paper Trail. Learn how to add an undo link to any model’s flash message.

#255 Undo with Paper Trail

Undo and redo behavior is easy to add with a versioning gem such as Paper Trail. Learn how to add an undo link to any model’s flash message.

16 Ruby and Rails Jobs for February 2011 (including UK and Australia)

It’s been a killer month for new Ruby and Rails jobs over at the Ruby Inside Jobs board so I’m going to cut the filler to a minimum today.. though if you want to learn more about posting one of your own, check our Post A Job page. The current bonus is you’ll get your job ad into the 4000+ subscriber-strong Ruby Weekly for free!

There are a couple of really appealing jobs in here (particularly the first one) and they span the US with a few in the United Kingdom and one in Australia for good measure:

Innovation Developer – San Francisco, California

salesforce.com, inc. is looking for a Innovation Developer – the sort of developer who reads HN and TechCrunch, who’s played with tools like Raphael and CoffeeScript, and who wants to work on interesting prototypes with the latest tools. This sounds like a great position! It’s in downtown SF and you can even get a $100/mo fitness reimbursement — click here to learn more.

Great Ruby Developer Needed – London, UK

Econsultancy is an award-winning online publisher based in London and New York. They’re looking for a developer to work at their London office with general experience of Ruby, Rails and Unix/Linux – salary is up to 60k — click here to learn more.

Ruby on Rails Developer – Pasadena, California

Goldstar is a ticket and entertainment company looking for a full-time Rails developer to join a geographically-dispersed, test-happy, and pair-friendly team of developers building services for 1.2 million members across the US. This job does not demand you be based near Pasadena, CA (though that’s ideal) but at least one visit per year to HQ is required — click here to learn more.

Ruby/Rails Engineers – Edinburgh & Cambridge, UK

FreeAgent is a fast growing and hugely popular UK based startup obsessed with building fantastic online accounting software. They’re a small team of smart people looking to hire productive Ruby and Rails developers in Edinburgh or Cambridge. You’ll be working on adding and maintaining features for our existing applications and making sure their software scales up — click here to learn more.

Ruby on Rails Developer – Boston, Massachusetts

The District Management Council is looking for an experienced Web developer with 2+ years of Rails and JavaScript experience plus MySQL, HTML, and CSS proficiency to work on their Web applications helping to dramatically improve public education in America today — click here to learn more.

Ruby/Java Web Developers – Arlington, Virginia

Healthcentral is an online health information site looking for, ideally, a developer experienced with both Java and Ruby related technologies. A BS/MS in Computer Science is preferred, along with 2-4 years of industry experience preferably in startup environments — click here to learn more.

Ruby Developer – Palo Alto, California

Wildfire Interactive is a rapidly expanding, VC-funded tech startup in the social media marketing space. They’re using Rails and Sinatra and building many ‘pure Ruby’ components so they want Ruby developers with full-stack experience. Oh, and testing is a must — click here to learn more.

Ruby Developer – Lewisville, Texas

Geoforce Inc provides asset visibility to the oil and gas industry through wireless devices feeding data to a Rails-powered SaaS app. They want a developer with 3 years of Rails experience, as well as Postgresql, HTML, and JavaScript experience generally — click here to learn more.

Graduate Rails Developer – London, UK

AlphaSights are looking for a Computer Science graduate (or equivalent) with a passion for Ruby and Rails to work in a small team at their Covent Garden offices. No commercial Rails experience is necessary and a highly competitive salary is offered — click here to learn more.

Rails Developer – Cleveland, Ohio

Within3 is a professional networking site for the top institutions and physicians in the healthcare industry looking for a Rails developer. At least 3-5 years of Ruby experience is needed as well as thorough knowledge of front-end technologies (XHTML, CSS, JavaScript) — click here to learn more.

Senior Ruby (Rails/Sinatra) Developer – Santa Monica, California

TRUECar, Inc. is looking for a Ruby developer with Sinatra experience to work on improving their car price research service. Your TDD and Agile-fu needs to be strong. A highly competitive salary, 100% medical, and equity are offered — click here to learn more.

Sr. Ruby Developer – Coronado, California

StockTwits wants a senior-level Ruby developer with Ruby, Rails (with HAML), TDD and HTML5 experience. A Bachelor’s degree or better in Computer Science or a related technical discipline is required — click here to learn more.

Ruby on Rails Developer – Chicago, Illinois

Obtiva is looking for developers for its Chicago and Denver locations – no ‘rock stars’ or ‘ninjas’ but passionate, friendly team players with Ruby, Rails, and Agile experience — click here to learn more.

Web Developer – San Francisco, California

Do you have a passion for design as well as code? Hybrid Design wants you! They’re working for clients like Apple, Nike, and TED and need a full-time Web developer with both Ruby and design chops — click here to learn more.

Ruby Developer – Evanston, Illinois

Celect builds member-management systems for organizations like churches and fraternities. They need a full-time Ruby developer for their engineering team who has experience with RSpec, Passenger, and PostgreSQL. The job is on-site in Evanston, IL — click here to learn more.

Ruby on Rails Software Engineer – Sterling, Virginia

Grab Networks is looking for analytical individuals with strong computational skills to work on multiple levels of a complex technology stack. You’ll need 5-6 years’ experience developing dynamic, data-driven, commercial web applications — click here to learn more.

Ruby/JRuby Tools Engineer – San Mateo, California

Where can you work on challenging engineering problems while saving the planet? At eMeter! eMeter is seeking an Java/Ruby/JRuby Automation/Tools Engineer to drive the development of automation tools — click here to learn more.

Ruby Developer – Melbourne, Australia

TrikeApps is looking for a Ruby Developer to work in their Melbourne, Australia office. Assistance with relocation and visa sponsorship is available for the right candidate wanting to move to Australia. Two years of experience developing webapps is required — click here to learn more.

Ruby on Rails Software Engineer – San Francisco, California

AKQA (one of the world’s most influential creative and technology companies) is looking for a Ruby on Rails Software Engineer with 3 years’ experience of Rails and familiarity with Unix/Linux — click here to learn more.

Rails 3.0.5 has been released!

Aaron Patterson showed us some tenderlove this week by releasing Rails 3.0.5. Have a peek at what got updated.

Bugs Fixed

  • Fix when gzip returns a UTF-8 string on Ruby 1.9, when it is actually binary. commit
  • Active Record limit values will not escape Arel SQL Literal nodes. commit
  • Relation#where calls will always produce AND statements regardless of how conditions hashes behaves (reverting 00693209ecc).
  • Observer callbacks will only be executed once when using STI classes in ActiveRecord. commit

Deprecations Added:

  • Deprecate Relation#& alias for Relation#merge. commit
  • Deprecated support for interpolated association conditions with the
    :conditions => ‘foo = #{bar}’ syntax, and added the new interpolation syntax
    which is :conditions => proc { “foo = #{bar}” }. commit

This is not a complete list of changes. The complete list of changes can be
found here

SHA1 Checksums:

  • actionmailer-3.0.5.gem b25750c8126aa21db27d7b0ee829b2e94e525ebc
  • actionpack-3.0.5.gem 0a6f7f9ac2960ff224c913877a2917e1bea80df3
  • activemodel-3.0.5.gem 1556900a7afa1cdcdf4641edbcdd2c24f98bb2de
  • activerecord-3.0.5.gem 33dd05d7362931564f6f15ea7130cc27a5fc09e8
  • activeresource-3.0.5.gem 758f893cbb7ef945c857bf4ca044b94017bdc437
  • activesupport-3.0.5.gem 195fa3f7fa044134703a655cdb906edb515286c4
  • rails-3.0.5.gem 32322bf9952d76c5fa0054c8533c0c58609f40aa
  • railties-3.0.5.gem 3dddf14736dec991c3dbbe2d89495613e72c19c7

A Review of “Eloquent Ruby” by Russ Olsen – It Rocks!

Eloquent Ruby (Amazon.com – print & Kindle) by Russ Olsen is the first Ruby book I’ve read in its entirety within 24 hours; it’s that good. That may be all you need to know before you buy a copy at Amazon.com, Amazon.co.uk or read it on Safari (if you have an account). If you want to learn more though, keep reading.

What Is “Eloquent Ruby”?

Eloquent Ruby is a book published by Addison Wesley and written by Russ Olsen (who also wrote Design Patterns in Ruby a few years ago). It clocks in at around 400 pages and has 31 chapters clocking in at around a punchy 10 pages each. Each chapter is titled as a guideline you should follow to write “eloquent” Ruby – things like Create Classes That Understand Equality and Write Code That Looks Like Ruby – and typically the claim is explained, some code examples shown and discussed, some real world examples pointed to, and that’s it.

As with Design Patterns in Ruby, Russ adopts a chatty, familiar tone. Reading this book is like reading a book specifically written for you by a friend. He doesn’t shoot off on many unnecessary tangents and he keeps the stories short and sweet but this book certainly couldn’t be called dry.

The book is also notably short of egregious errors or omissions. Even when I don’t read something with a fine-toothed comb on standby, I can usually pick out a laundry list of factual and grammatical errors or omissions (as both Obie Fernandez and my wife will attest) but Eloquent Ruby gave me little to chew on. I can only bring to mind a few spacing and formatting issues and only one true “error”: a > instead of a < in a class definition on a single example.

Russ tries to remain neutral with his choice of Ruby implementations but the book seems to focus primarily on Ruby 1.9 (Ruby 1.9.1 specifically but that’s just due to when he wrote it) while providing useful footnotes in the cases where there are differences to Ruby 1.8. No matter what Ruby implementation you’re using, there’s little to confuse you as most of it is very non-implementation and non-version specific.

I wholeheartedly recommend this book to anyone except those who, well, could have written a similar book themselves. The short punchy chapters make it a delight to read and gives the option of reading it merely 10 minutes at a time before bed or similar. The short chapters also make it useful as a reference if you forget how to do a certain thing like, say, use method_missing, even though it’s not put together as a reference book at all. Lastly, this book is a must read if you’re not confident with Ruby idioms and the best way to structure and lay out your code – Russ’s approaches reinforce the current “standard” way to write Ruby and this alone is worth the price of admission.

Who Should Buy It?

  • Any Ruby developer who doesn’t yet feel like they’re at guru level (that’s most of us!)
  • Anyone who wants to get a feel for the typically undocumented style, syntax, and structural standards of top Ruby developers.

Who Shouldn’t Buy It?

  • Anyone without a sense of humor or who doesn’t like a chatty, familiar type of writing.
  • Matz, Dave Thomas, Chad Fowler, Russ Olsen himself, and a few others.
  • Anyone who’s resistant to change and wants to keep coding Ruby “their way.”

The Chapters

The chapter titles in Eloquent Ruby are useful enough to give you an indication of the level(s) it aims at and whether it would be interesting to you, so here goes:

  1. Write Code That Looks Like Ruby
  2. Choose The Right Control Structure
  3. Take Advantage Of Ruby’s Smart Collections
  4. Take Advantage Of Ruby’s Smart Strings
  5. Find The Right String With Regular Expressions
  6. Use Symbols To Stand For Something
  7. Treat Everything Like An Object – Because It Is
  8. Embrace Dynamic Typing
  9. Write Specs!
  10. Construct Your Classes From Short, Focused Methods
  11. Define Operators Respectfully
  12. Create Classes That Understand Equality
  13. Get The Behavior You Need With Singleton And Class Methods
  14. Use Class Instance Variables
  15. Use Modules As Name spaces
  16. Use Modules As Mixins
  17. Use Blocks To Iterate
  18. Execute Around With A Block
  19. Save Blocks To Execute Later
  20. Use Hooks To Keep Your Program Informed
  21. Use method_missing For Flexible Error Handling
  22. Use method_missing For Delegation
  23. Use method_missing To Build Flexible APIs
  24. Update Existing Classes With Monkey Patching
  25. Create Self Modifying Classes
  26. Create Classes That Modify Their Subclasses
  27. Invent Internal DSLs
  28. Build External DSLs For Flexible Syntax
  29. Package Your Programs As Gems
  30. Know Your Ruby Implementation
  31. Keep An Open Mind To Go With Those Open Classes

There’s something for everyone and it gets progressively more advanced.

How to Get Eloquent Ruby

If you want a print or Kindle copy, head to Amazon.com, Amazon.co.uk, or your other favorite book retailer. If a PDF or EPUB file is more to your taste, InformIT has those for sale (currently for $28.79).

Kindle Preview

Bag O’ Links – 26/2/2011

Yeah, since i’ve been working for fiverr.com it’s been really hard to find the time and compile a decent bag’o’links.. hopefully i’ll get back to that soon along with posting some cool Rails experiences from Fiverr.

Well, back to business:

Links

Treasures

  • Rack-modpagespeed – a rack app that does all kinds of cool things to make your pages load faster.
  • Terminator – ninja command line.
  • Rails cells – not really sure what it’s actually good for.

Bag O’ Links – 26/2/2011

Yeah, since i’ve been working for fiverr.com it’s been really hard to find the time and compile a decent bag’o’links.. hopefully i’ll get back to that soon along with posting some cool Rails experiences from Fiverr.

Well, back to business:

Links

Treasures

  • Rack-modpagespeed – a rack app that does all kinds of cool things to make your pages load faster.
  • Terminator – ninja command line.
  • Rails cells – not really sure what it’s actually good for.

Quick Tip: Sending Google Chart links via email

Recently I had a client who wanted to deliver reports via email that contained a bunch of charts, and we decided on using Google Charts for the chart rendering. I used the googlecharts gem to create the links to Google. I encountered a problem with the charts not showing up in Gmail, even when the exact same code was working when viewing the reports at the site in the browser.

It turns out that the pipe character used to delimit data, options, etc., in Google Charts URLs didn’t play nicely with Gmail. Once they were encoded (converted to %7c), it worked like a champ. So, in my (html) email views, I have this as the src attribute to image tags:


Gchart.line(..., :format => 'url').gsub('|', '%7C')

Problem solved. 🙂

Quick Tip: Sending Google Chart links via email

Recently I had a client who wanted to deliver reports via email that contained a bunch of charts, and we decided on using Google Charts for the chart rendering. I used the googlecharts gem to create the links to Google. I encountered a problem with the charts not showing up in Gmail, even when the exact same code was working when viewing the reports at the site in the browser.

It turns out that the pipe character used to delimit data, options, etc., in Google Charts URLs didn’t play nicely with Gmail. Once they were encoded (converted to %7c), it worked like a champ. So, in my (html) email views, I have this as the src attribute to image tags:


Gchart.line(..., :format => 'url').gsub('|', '%7C')

Problem solved. 🙂

A forum for The Passionate Programmer

I’ve setup a Facebook page for The Passionate Programmer. Please Like it, Share it, and post your own questions, experiences, act-on-it reports, or doubts.

Be Careful Of Who You Work With

You instinctively know that who you associate with matters a lot. Our parents bring us up steering away and toward others who influence us.

But most of us don’t realize just how much those around us influence us.

As I recall in the introduction to The Passionate Programmer, there was one specific event that turned the tide for me. I had been chugging along in my slightly-above-average corporate job and experiencing what I considered to be the height of success. Then I had an intense period during which, for a few months, I had the opportunity to collaborate with a whole new level of software developers. It all came to a head when I went to the eXtreme Programming Immersion that Object Mentor taught. After a week surrounded by brilliant developers and leaders in the field, I knew I had to do something different.

I had to be as much like them as I could.

In The Passionate Programmer, I quote Pat Metheny’s advice to young musicians: always be the worst musician in every band you’re in. As a musician and as a programmer, I’ve tried Pat’s advice. You play with a group of people better than you, and you’ll almost always play better.


http://www.flickr.com/photos/jazzuality/3613370192/

That’s good anecdotal advice. If you don’t trust Pat, how about Nicholas Christakis? Nicholas is a social scientist at Harvard University. Together with James Fowler of UC San Diego, his research focuses on how behavior and then even EMOTION spread through social networks. Can behavior be epidemic?

Here are some things their research has shown to spread through social networks ilke disease: Obesity), Smoking, Alcohol Consumption, and….HAPPINESS! Yes, emotional state is contagious.


http://www.flickr.com/photos/saintbob/165829023/

These aren’t insignificant numbers, either. For example, obesity chances increase 57% if you have a friend who is or becomes obese. And, more disturbing than that, this is an effect that is conducted through more than one node in the social graph. If your friends’ friends’ friends are obese, you are 10% more likely to be obese

If behavior spreads through social networks, then working in a toxic or slow-moving corporate environment is really really bad for you. If you’re a consultant, you MUST fire the clients that bring you down a notch and seek out clients that pull you up. If you’re a teacher, go where the students care about what they’re learning.

Happy 18th Birthday, Ruby!

Yes, I’m sad enough to have had this in my calendar for some time but.. it’s Ruby’s 18th “birthday” today! Happy Birthday Ruby! While this means she can drink, vote, and otherwise join her slightly older friends Perl (24) and Python (21) in the nightclubs of Europe, I was surprised to learn that coming of age in Japan is at 20 years old.

From Wikipedia’s Ruby entry:

The name “Ruby” was decided on during an online chat session between Matsumoto and Keiju Ishitsuka on February 24, 1993, before any code had been written for the language. Initially two names were proposed: “Coral” and “Ruby”, with the latter being chosen by Matsumoto in a later email to Ishitsuka. Matsumoto has later stated that a factor in choosing the name “Ruby” was because it was the birthstone of one of his colleagues.

Wikipedia

If you’re interested in learning more, this interview with Matz back in 2001 will give you more history and background to the creation of Ruby.

While Matz has said that February 24, 1993 is Ruby’s “birthday” (back when I Will Always Love You by Whitney Houston was topping the charts), the first public release wasn’t until December 21, 1995 when Ruby 0.95 was released and the first mailing list established. Ruby 1.0 followed a year later on December 25, 1996, establishing the tradition of Christmas Day Ruby releases.

Here’s to 18 more, love.

P.S. Before I get any grief for putting a picture of a young woman on this post — it’s happened before *sigh* — this actress played a character called Ruby in the UK’s most popular soap opera and was about 18 at the time. Rock and roll.

Ruby Vulnerabilities

In this episode, Peter and Jason discuss new releases of Ruby, benchmarks, the future of Rubinius, and more.

Programming Language Survey Results

A couple of weeks ago (already!) I asked two simple questions of my Twitter followers: what are (up to) four programming languages that you know and love, and what are (up to) four programming languages that you would like to learn?

Around the time I asked the question, I had almost 4200 followers on Twitter. Of those 4200, 38 responded. That’s almost one percent, and it is most definitely not a large enough sample from which to draw meaningful conclusions! Even if all 4200 of my twitter followers responded, it would still have been a strongly biased survey: most people following me on twitter are (or were) Ruby/Rails programmers, or found me through some other Ruby/Rails programmer. Asking this group what their favorite languages are is bound to have some strong biases.

And, sure enough, the top ten “know-and-love” languages among the 38 respondents were:

  1. ruby (32)
  2. javascript (25)
  3. java (13)
  4. python (9)
  5. c (9)
  6. c# (7)
  7. php (6)
  8. c++ (5)
  9. perl (4)
  10. lisp (4)

Compare that to the top ten “want-to-learn” languages:

  1. erlang (22)
  2. objective-c (12)
  3. clojure (12)
  4. python (12)
  5. lisp (10)
  6. haskell (9)
  7. scala (9)
  8. lua (5)
  9. r (5)
  10. c (5)

Ruby didn’t even make that list! (It actually came in at #11.)

So, what I’m trying to say is, the data is strongly slanted toward the preferences of Rails programmers who enjoy Ruby as a programming language. Still, there are some interesting tidbits to find here. I am definitely not a statistician, but here are four points that emerged that I found enlightening:

Every respondent included at least one object-oriented language among their know-and-love’s. For most people, that was Ruby, but Java, Python, C++, Objective-C, and others were mentioned, too. 17 people mentioned two object-oriented languages, and 17 more mentioned three. Three people gave all four of their know-and-love languages as object-oriented languages. What do I take away from this? All we really know is that object-oriented languages are apparently widely taught/learned among my twitter followers. No surprise there!

Only 8 respondents indicated that they know-and-love a functional language. Six people gave only a single functional language among their four know-and-loves, one more gave two, and one more gave three. Is this because people don’t love functional languages? Definitely not. There is simply not enough data to draw any conclusions about why this number is smaller than OO languages, but it does make you wonder, doesn’t it? Are programmers with predominantly OO backgrounds intimidated by functional paradigms? As you’ll see in the next question, it’s definitely not a lack of interest!

The four functional languages that people gave as “know-and-love” are:

  1. lisp (4)
  2. haskell (3)
  3. erlang (3)
  4. clojure (1)

Now, compare that with the next point:

33 of the 38 respondents wanted to learn at least one functional language. That’s almost 87%, versus only 21% that already knew a functional language. There is some serious curiosity there; people know OO, but want to learn functional. And what functional languages are people curious about?

  1. erlang (22)
  2. clojure (12)
  3. lisp (10)
  4. haskell (9)
  5. scheme (2)
  6. ocaml (2)
  7. ml (1)
  8. f# (1)

Erlang, far and away, is the one most people are curious about. Interesting!

The last point: 32 respondents included at least one object-oriented language in their want-to-learn list. 12 people wanted to learn one OO language, 16 wanted to learn two, and four people wanted to learn three OO languages. Which languages?

  1. python (12)
  2. objective-c (12)
  3. scala (9)
  4. lua (5)
  5. ruby (4)
  6. c# (3)
  7. smalltalk (3)
  8. java (2)
  9. javascript (2)
  10. c++ (1)
  11. io (1)
  12. coffeescript (1)
  13. groovy (1)

Curiouser and curiouser! I love that a predominantly Ruby-centric group wants Python and Objective-C above all others. ObjC actually makes sense to me, even aside from the popularity of iOS as a platform. ObjC has many similarities to Ruby, and is a great language for Rubyists. Python, though…I love that it’s tied for #1. It shows a certain open-mindedness in the Ruby community, which gives me warm fuzzies.

Anyway, I’ll say it again: there really wasn’t a large enough sample set to draw meaningful conclusions here. But it’s still fun to look at seeming patterns in the data. Hopefull you’ve found something useful here, too!

#254 Pagination with Kaminari

If you need pagination in Rails 3 try out Kaminari. It is a clean, flexible solution which uses scopes to flow nicely with Active Record queries. Did I mention it also works with Mongoid?

#254 Pagination with Kaminari

If you need pagination in Rails 3 try out Kaminari. It is a clean, flexible solution which uses scopes to flow nicely with Active Record queries. Did I mention it also works with Mongoid?

Give Yourself Constraints

Recently, I had a hernia and surgery to fix it. This knocked me out of the game and onto the couch for a couple weeks. During my recovery, I had a lot of time to think. I also had a lot of time to miss what I do every day.

This was the longest period in several years for me without creating. Once I felt good enough to get back at it, even if only for a few hours, I decided to focus all this pent up energy on something new.

What I wanted to do, was to think through a problem different than I ever have. I have been creating applications pretty much the same way for quite some time. Sure, MongoDB changed my methods a bit, but I knew I had not used it to its full potential, as I typically start all new Mongo projects with MongoMapper.

What to Build

First, I thought about what to build. I have a plethora of “someday” ideas that have never made it out of that stage. One of those ideas was to build a simple analytics program.

Sure, there are a crap ton of analytics apps out there, including Google Analytics, but not a one thus far has hit the sweet spot I am looking for.

The Old Constraint

Back in the day, I would entertain every whim I had. This is great for learning a lot of new things, but I never really focused and finished anything. What I had was a project directory full of half (or less) finished ideas.

When I actually forced myself to work on only a project or two (I chose MongoMapper and Harmony), I noticed that I actually finished things and had something to show for myself.

Important: The constraint of what I could work on made me more productive than working on whatever I was inspired to work on.

That said, rules are made to be broken, right? Plus, this new project was not entirely misguided. Harmony manages websites. Websites need analytics. There is definitely a benefit to Harmony in building an analytics system that can be deeply integrated, so I began work.

The New Constraints

Since I was bending the rules a bit, I decided to give myself different constraints this time. Rather than what I would work on, I focused on what tools I could use to do the work. The thought was that forcing myself to avoid my comfort tools would lead to thinking outside of my usual box.

The first constraint I made was that I could only use the Mongo Ruby driver. No ActiveRecord, MongoMapper or any other object mapper.

Second, no aggregate querying for reports. All of the analytics had to be built on the fly as each hit came in. I told myself I could not even store the individual hit data that was generated each time a page was tracked.

Third, no signup or authentication. I wanted to focus on the core functionality (tracking views) instead of spending my time authenticating users and all that crap.

Fourth, I cannot remember, so lets move on.

The Prototype

Within a few hours, using Sinatra and the MongoDB Ruby driver, I had a little prototype working. Each hit was a single MongoDB operation, an upsert based on the host, with year, month, day, and hour information stored in nested hashes. The nested hashes were updated in the operation using $inc. It did not do much, but it was pretty cool.

I am aware, especially now, how simple that first prototype was, but it felt great to create again. Next, I threw the app up on Heroku and MongoHQ, so I could try it out tracking this site you are reading.

Both are free to try, so it cost me nothing to get something up that I and others could react to. I showed it to the rest of the Ordered List team and every one shared the excitement.

The Result

I am amazed at what we have come up with in such a short amount of time (4 weeks using occasional evenings/weekends). In fact, the constraint of time is why Gauges is where it is today. We were really productive in the hours we snatched to work on it, because they were few and far between.

Steve came up with a great name, found a matching domain (which is a miracle these days) and Gaug.es was born.

Home Page

Dashboard

Note: Holy crap did Steve (@orderedlist on Twitter) knock the design out of the park. Dude has skills!

Conclusion

The last 4 weeks working on Gauges has made me feel, at times, like a kid again. It is almost like we were racing to the next fence post (sue me, I grew up on a farm). Sure, I broke the original constraints I set, but without them, I would never have started.

To break constraint numero uno, I used ToyStore, with my mongo adapter. Any service that involves user input needs validations and the like, and I was not in the mood to build them from scratch.

I actually stuck with constraint number two. All of the tracking code uses upserts with MongoDB modifiers to create and update reports on the fly.

Constraint number three also fell to the wayside. You cannot very well make money on a service that requires no signup (or at least it is increasingly difficult), so you do in fact have to sign up and in to use Gauges. That said, right now we are just testing things out, so we are controlling things with a code.

Whether it be the tools that you use, the projects that you work on, or the people you work with, give yourself constraints. Create something that you have always wanted. Get other people excited about it. Work cannot always be “work”.

P.S. If Gauges is something you are interested in and you would like to be an early tester, let me know. The main goals right now are hosted (no setup/servers), easy sharing with other people, how much traffic, where was it from and where was it to.

Plus, we have a few great ideas for down the road, once we get the basics ironed out. Thus far, Gauges is really scratching an itch I have had for a while and I am stoked.

How To Get Rails 3 and RSpec 2 Running Specs Fast (From Scratch)

Rails 3 is great. RSpec 2 is great. And Ruby 1.9.2 is really great. Getting them all running together and quickly, however, isn’t entirely straightforward. In this post I demonstrate how to get everything ticking over along with automatically running, super-snappy test runs.

The ultimate outcome is using Ruby 1.9.2 (though much of this is relevant to 1.8 still) to create a Rails 3 app, hook up RSpec 2, and be able to run specs quickly. The first two parts are easy(ish) but the “quickly” part requires some tinkering. Grab a coffee and carry on..

Create a new Rails 3 app

Got Rails 3 installed? If not, gem install rails will see you good. Then head on down to your favorite project folder with your shell and create a new Rails 3 app like so:

rails new myapp --skip-test-unit

You can retroactively bring RSpec 2 into an existing Rails 3 project, of course, but it’s easier for this walkthrough to start afresh in case of application-specific issues.

Hooking up RSpec 2 with RSpec-Rails

Edit the Gemfile file in your new Rails project (myapp/Gemfile in this example) and add the following block to the bottom:

group :development, :test do
  gem 'rspec-rails'
end

This tells Bundler (a gem management and dependency tool Rails 3 likes to lean on) we want to use the rspec-rails gem which will get RSpec running with Rails 3.0 for us. Next, we get Bundler to do its thing:

bundle

This will install all of the gems referenced in Gemfile, including rspec-rails. (You can use bundle install instead, if you prefer, but bundle on its own works too.)

Last but not least, we need to run RSpec’s ‘generator’ that rspec-rails has put in place for us:

rails generate rspec:install

The generator creates a few files. Namely:

  • .rspec – a config file where we can store extra command line options for the rspec command line tool. By default it contains --colour which turns on colored output from RSpec.
  • spec – a directory that will store all of the various model, controller, view, acceptance and other specs for your app
  • spec/spec_helper.rb – a file that’s loaded by every spec (not in any automatic way but most have require 'spec_helper' at the top). It sets the test environment, contains app level RSpec configuration items, loads support files, and more.

We still can’t run rake and see anything interesting yet because we don’t have a database or any models initialized.

Creating a model to test

Let’s take the easy way out and use the scaffold generator to flesh out something for us to test (as well as to see what spec files can be generated automatically):

rails generate scaffold Person name:string age:integer zipcode:string

It’s worth noting that when you generate the scaffold numerous spec files are also created (thanks to rspec-rails):

spec/models/person_spec.rb
spec/controllers/people_controller_spec.rb
spec/views/people/edit.html.erb_spec.rb
spec/views/people/index.html.erb_spec.rb
spec/views/people/new.html.erb_spec.rb
spec/views/people/show.html.erb_spec.rb
spec/helpers/people_helper_spec.rb
spec/routing/people_routing_spec.rb
spec/requests/people_spec.rb

Now bring the database up to speed with the migration for the new model:

rake db:migrate

Now let’s run rake – finally! The result:

...............**............

Pending:
  PeopleHelper add some examples to (or delete) /Users/peter/dev/rails/myapp/spec/helpers/people_helper_spec.rb
    # Not Yet Implemented
    # ./spec/helpers/people_helper_spec.rb:14
  Person add some examples to (or delete) /Users/peter/dev/rails/myapp/spec/models/person_spec.rb
    # Not Yet Implemented
    # ./spec/models/person_spec.rb:4

Finished in 0.31043 seconds
29 examples, 0 failures, 2 pending

Rock and roll. We’re up and running. Sort of. Let’s put in some “real” specs to be sure things are working nicely.

Change spec/models/person_spec.rb to the following rather contrived pair of specs:

require 'spec_helper'

describe Person do
  it "can be instantiated" do
    Person.new.should be_an_instance_of(Person)
  end

  it "can be saved successfully" do
    Person.create.should be_persisted
  end
end

Not the most useful things to spec out, admittedly, but you get a little database action and get rid of a pending spec we had cluttering things up. We haven’t got anything else we can seriously test yet anyway.

Now let’s run rake spec:models to focus our efforts on what we’ve just done:

..

Finished in 0.09378 seconds
2 examples, 0 failures

How to have specs run automatically with Watchr

Let’s assume we’ve progressed with developing our app and we’re working on models and controllers, testing along the way. Rather than running rake or bundle exec rspec all of the time, wouldn’t it be great to have the relevant spec run automatically when we either edit the spec or a model/controller that has a spec? Well, with watchr, we can. (Note: Some people prefer autotest. I find watchr more flexible and useful for other things beyond just running specs.)

But if you really want to use autotest, Mike Bethany explains how to set it up in a similar scenario in a post of his own, along with autotest-growl for OS X notifications.

Add watchr to your Gemfile‘s testing and production gem section:

group :development, :test do
  gem 'rspec-rails'
  gem 'watchr'
end

Then run bundle to install it.

Next, create a file called .watchr in your app’s root folder and populate it with this code:

def run_spec(file)
  unless File.exist?(file)
    puts "#{file} does not exist"
    return
  end

  puts "Running #{file}"
  system "bundle exec rspec #{file}"
  puts
end

watch("spec/.*/*_spec\.rb") do |match|
  run_spec match[0]
end

watch("app/(.*/.*)\.rb") do |match|
  run_spec %{spec/#{match[1]}_spec.rb}
end

This ‘watchr script’ directs a running watchr process to do a few things:

  • If any file ending in _spec.rb under the spec/ directory changes, run the run_spec method with its filename.
  • If any .rb file under the app/ directory changes, call the run_spec method with an equivalently named _spec.rb file under spec.
  • run_file accepts a filename for a spec file, checks it exists, and tells the system to run it (using system)

If you now run watchr .watchr to use the .watchr script, not much will happen. But if you make any change (or even just re-save) to, say, spec/models/person_spec.rb, that spec will run automatically. Make a change to app/models/person.rb and it’s the same deal. To stop watchr, CTRL+C saves the day.

Watchr can be used for a lot more than this but this is just for starters 😉

Optionally, you might also like to create lib/tasks/watchr.rake and include the following code so you can just remember to run rake watchr instead (it’s nice to have anything you run within a project contained in one place):

desc "Run watchr"
task :watchr do
  sh %{bundle exec watchr .watchr}
end

How to get faster spec runs with Spork

We’ve got Rails 3 running with RSpec 2 and watchr’s giving us some automatically-running-spec love. But do you notice how slow it is? Specs run quickly once they’re loaded but there are several seconds of waiting beforehand.

If you run time rake spec:models with Ruby 1.9.2, you’ll probably see a wallclock time of over 5 seconds (5.204s on my machine and I’m SSDed up) – holy splingledoops! If not, you’re lucky, but it’s a commonly reported problem with some improvements expected in Ruby 1.9.3. We can’t wait that long though..

Enter Spork. Spork is a tool that loads the Rails environment and then forks each time you want to run some specs (or tests, it can be set up to run with Test::Unit too). In this way, the whole Rails initialization process is skipped, shaving valuable seconds off of your spec runs.

Edit your Gemfile again and include Spork:

gem 'spork', '~> 0.9.0.rc'

Run bundle to install Spork.

Next, Spork needs to make some changes to your spec/spec_helper.rb file. Because it only initializes the Rails environment once and then forks it, you might have initialization features that you need to run on each test run. Spork will let you do this but it needs to make those changes first. Run:

spork --bootstrap

The result:

Using RSpec
Bootstrapping /Users/peter/dev/rails/myapp/spec/spec_helper.rb.
Done. Edit /Users/peter/dev/rails/myapp/spec/spec_helper.rb now with your favorite text editor and follow the instructions.

Bring up spec/spec_helper.rb. All spork --bootstrap has done is add some extra code to the top of the file. Read the comments there to get a better feel for what to do and what Spork requires and keep them in mind as we progress (in case you want to do something differently).

Get rid of require 'rubygems' from the first line – we’re using Bundler so it’s not necessary.

Next, cut and paste all of the ‘old’ contents of spec_helper.rb into the Spork.prefork block. Since we’re running an empty(ish) project, there’s nothing special we’ve added that we need to run on each run using the Spork.each_run block. We can leave that empty.

You’ll end up with a spec_helper.rb file that looks like this:

require 'spork'

Spork.prefork do
  # Loading more in this block will cause your tests to run faster. However, 
  # if you change any configuration or code from libraries loaded here, you'll
  # need to restart spork for it take effect.
  # This file is copied to spec/ when you run 'rails generate rspec:install'
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'

  # Requires supporting ruby files with custom matchers and macros, etc,
  # in spec/support/ and its subdirectories.
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  RSpec.configure do |config|
    # == Mock Framework
    #
    # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
    #
    # config.mock_with :mocha
    # config.mock_with :flexmock
    # config.mock_with :rr
    config.mock_with :rspec

    # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
    config.fixture_path = "#{::Rails.root}/spec/fixtures"

    # If you're not using ActiveRecord, or you'd prefer not to run each of your
    # examples within a transaction, remove the following line or assign false
    # instead of true.
    config.use_transactional_fixtures = true
  end
end

Spork.each_run do
  # This code will be run each time you run your specs.
end

Head back to your shell and the root of your project and run spork:

Using RSpec
Loading Spork.prefork block...
Spork is ready and listening on 8989!

Now we’re cooking with gas. Open another shell, head to the root of your project, and run watchr .watchr too. Then head to spec/models/person_spec.rb in your text editor and re-save it (or even make a change if you want). Your specs run but.. they’re no faster! What’s wrong?

It turns out we need to make another change so that RSpec knows we’re running Spork. Edit the .rspec file (mentioned earlier) and add --drb to the line (so it probably reads --colour --drb). Now, edit the spec again, save, and.. fast!

You should note that if you use rake at this point to run your entire suite, it’ll still not be particularly fast because rake itself is initializing Rails in order to do its job. But if you want to run your entire suite quickly, just run:

rspec spec

With our dummy app and on my machine, this runs in a wallclock time of 0.759s – a serious improvement over 5.2 seconds.

We have Rails 3, RSpec 2, watchr, spork, and SUPER-DUPER FAST SPECS all running on Ruby 1.9.2. Score!

A minor snafu will remain, though. If you update app/models/person.rb, the change won’t take effect in your tests since Spork has the old Person still in memory. One way around this is to edit config/environments/test.rb and change:

config.cache_classes = true

To:

config.cache_classes = false

Now your app’s classes are reloaded when necessary.