Ruby, etc

Learn all the things

He who enjoys doing and enjoys what he has done is happy. - Fortune Cookie

Book Review: Application Testing With Capybara

If you know me, you know I love testing. Model tests, library tests (typically when poro objects) are the most awesome to test and I love it. Controller tests, well, are less fun and testing routes is not bad either. But my least favorite are integration tests.

Cucumber tests seemed awesome in theory and I remember early days in Chicago ruby group there was development on rspec story runner which I believed was written by Dan North, later rewritten as Cucumber. Wow!! Project owners could write their own tests!! Right… Or maybe they could read the tests and say yeah that’s what I want. Yes, that was 2007. I’ve toyed with cucumber a few times and in frustration gave up. Even when using capybara, it was hard to get the right syntax and find accurate documentation.

Last fall there was a few talks I watched Capybara and Cucumber, Rspec … One project I work on they use Selenium. Ahh so many choices. How do I know what exactly is the difference between each of them and when do I use what?

I was pretty excited to get a review copy of Application Testing with Capybara … ok, lets give this another shot.

The book starts out with installation, then proceeds into an example of using cucumber to run a test on Youtube, I think thats a great start. Lets focus on writing a test for something we didn’t build and get our setup and syntax down. And here is where we see the Capybara uses Selenium as the driver. I was able to follow along and build a test that does a search on youtube. Cool, you know getting something working while you are learning is a great boost!

The second chapter is about Mastering The API … this is where I got hung up on the most, seeing different tutorials, docs, examples with different versions (most examples don’t tell you what version numbers of Capybara is used!) and it is just frustrating. Capybara can use XPath or CSS selectors to locate elements. The author prefers the CSS selector style because he thinks they are more readable, I agree! You can set your preferred style in your env.rb but you can always override it on a case by case basis.

The book continues with examples of all types of selecting items and filling in forms. One thing that I found helpful is it shows the syntax of the example queries and Rspec matchers

1
2
3
4
5
# example selectors
page.has_selector? '#local_results'

# Rspec matchers
page.should have_selector '#local_results'

This is one of the things that I think always tripped me up, I didn’t know there was two ways to do the same thing and they were both correct, it is just different styles. This is a great resource! The book also talks what driver to use when and how to tag tests that would have client side code. Great content.

Today I wrote some Cucumber tests for a project I am working on and I used this book. I got things setup set up correctly and looked up some syntax. I am happy to report success. If you want to work with Capybara be sure to grab a copy of Application Testing with Capybara :) YAY!

Getting Better at Practice

It often surprising to me to find developers who don’t spend time improving their craft. In reading the book The Clean Coder: A Code of Conduct for Professional Programmers (Robert C. Martin Series It states,

Practicing is what you do when you aren’t getting paid. You do it so you will be paid, and paid well.

To put it another way, do you really want a doctor who only uses what he knows from 2005 when he graduated from medical school? NO!! So why not spent some time outside of $dayjob to practice code or other aspects of programming?

Here’s a few things I have found helpful as I strive to be better at practicing:

  1. Learn to type. Seriously. Learn to type. This one is easy! I am guilty of sloppy typing too and I try at least a couple times a week if not daily to practice typing at http://play.typeracer.com … its quick, you can do a few paragraphs a day and I do find myself making less embarrassing typos and faster at typing.

  2. Learn your editor. Need to find file name XYZ? hit a key and type in the name of the file you want, open it. Easy right? OR click folder… click folder….scroll down.. click folder.. oh there’s the file. You could have had it open by now if you had only memorized the keyboard shortcut. And once you got one editor learned, learn another one. Try and learn a new one a couple times a week. A good site to practice keyboard shortcuts is ShortCutFoo they have a great list of shortcuts and you can practice them repeatedly. Another site for shortcuts is http://www.shortcutworld.com/. I would say you should learn vim and one other editor. If you ssh into a server and have to edit a file then you can count on vi being installed.

  3. Pair-program. You don’t have anyone at work to pair with? Not a problem there are several ways to find people to pair with! No excuses! In Austin we have a usergroup AustinRB and we pair program for the second half of the meeting. Maybe you can start up something with your local developers? Here are some ways to find people to pair with:

    • RubyPair - site that Evan Light and I built with some help from community
    • Pair with Me - put a badge on your blog and ask people to pair with you, also has good list of resources
  4. Practice Practice Practice!!! How and how how often? Every day! Ok maybe at least 3 days a week. There is a website called Programming Workout and a talk at Barcelona ruby conf talking about the concept. Athletes workout why not you? ProgrammingWorkout allows you to track your workouts and its pretty cool! Also their message board has some more ideas for practice.

Some ideas for practicing:

  • GitReady - git obviously :)
  • RubyKoans - ruby
  • Railscasts - rails
  • Codeschool - ruby, rails, javascript, dev tools, ios, git
  • Exercism - crowd sourced code reviews on practice problem. Clojure, Coffeescript, Elixir, Go, Haskell, Javascript, PHP, Python, ruby, rust and more added?
  • SoftwareCraftmanship - bunch of katas
  • CodeKata - another bunch of katas
  • BowlingGameKata - one from Uncle Bob
  • PrimeFactorsKata - one from Uncle Bob
  • ProjectEuler - mostly mathematical but cool part is you can check your answers
  • Write tests for your favorite gem, (crazy fun idea: fork the repo, delete all the tests and write some then compare to what was already there)
  • Write some examples for your favorite gem and submit them to the project documentation. Alot of open source projects lack simple examples of how to use it.

I get up most mornings at 6am, practice typing and work on one of these things before going to work. Recently started doing some brain training exercises too from Lumosity or using my 3DS and brain training games. Go forth and practice and Get Better!

Exploring Arrays - Part 4

combination

combination(n) { |c| block } → ary 
combination(n) → an_enumerator

Next method up for discussion is combination, when I saw this my first thought was “OH wow!! I can make games!!”. Being able to generate datasets I think is key to making a game. Being able to make a list of combinations, then pick on at random I think is cool. Lets try it

1
2
3
4
5
6
>> bad_guys = [:ogre, :giant, :zombie]
=> [:ogre, :giant, :zombie]
>> bad_guys.combination(2).to_a
=> [[:ogre, :giant], [:ogre, :zombie], [:giant, :zombie]]
>> bad_guys.combination(2).to_a.sample(1).flatten
=> [:giant, :zombie]

Lets build an array of bad guys, generate all the combinations of 2 badguys, choose a set of 2 at random and flatten it. Here is the list of bad guys for our awesome game. Cool huh? Doesn’t this just make you want to stop everything and make a game now? Ok, maybe it is just me. :)

compact

compact → new_ary 
Returns a copy of self with all nil elements removed.

I recently used this on a project (with help from a friend, Thanks Corey!) where I had 1 or 2 items and if I had two I wanted to be $100-200 but if just one I wanted it to be $100 or $200.

1
2
3
4
5
6
7
8
9
10
11
12
13
>> price_a = "$100"
=> "$100"
>> price_b = "$200"
=> "$200"
>> [price_a, price_b].compact.join("-")
=> "$100-$200"

>> price_a = "$100"
=> "$100"
>> price_b = nil
=> nil
>> [price_a, price_b].compact.join("-")
=> "$100"

Cool huh? previously I had something hideous like

1
2
3
4
5
6
7
8
9
if price_a.present? && price_b.present?
 "#{price_a}-#{price_b}"
elsif price_a.present?
  price_a
elsif price_b.present?
  price_b
else
  ""
end

Gross right? uh. I hate hate if structures like that just for checking if something has value. Following Avdi Grimm and reading his book “Much Ado about Naught” and his Confident Ruby has given me ideas to get around this type of coding! Using compact is great for this since it throws away any nils. Note this returns a copy of the array not changing it (as it would if it was compact!).

compact!

compact! → ary or nil
Removes nil elements from the array. Returns nil if no changes were made, otherwise returns ary.

Here’s what I just said, the ! changes the array and if nothing changed it just returns nil.

concat

concat(other_ary) → ary 
Appends the elements of other_ary to self.

Concatenates one array into the other. Also could use + … let me try it.

1
2
3
4
5
6
7
8
9
10
>> colors = [:red, :green, :blue]
=> [:red, :green, :blue]
>> colors.concat([:yellow, :orange])
=> [:red, :green, :blue, :yellow, :orange]
>> colors
=> [:red, :green, :blue, :yellow, :orange]

>> colors = [:red, :green, :blue] + [:yellow, :orange]
>> colors
=> [:red, :green, :blue, :yellow, :orange]

So, looks like they both will add arrays and the arrays are identical. Depending on the context, I think i might like the concat better.

count

count → int 
count(obj) → int
count { |item| block } → int

I think I knew count could count particular items but I forgot. Trying it out:

1
2
3
4
5
6
>> items = [:potion, :food, :food, :weapon, :potion]
=> [:potion, :food, :food, :weapon, :potion]
>> items.count(:potion)
=> 2
>> items.count(:food)
=> 2

So imagine if you were writing a game, and showing stats for things in your bag you could do something like this. The last one takes a block.

cycle

cycle(n=nil) {|obj| block } → nil 
cycle(n=nil) → an_enumerator

Cycle will iterate through an array going through each item n times or forever

1
2
3
4
5
6
7
8
9
10
11
12
>> levels = [:one, :two, :three, :four, :five]
>> levels.cycle(2) { |level| puts "level #{level}" }
level one
level two
level three
level four
level five
level one
level two
level three
level four
level five

This cycles through the array 2 times. Hmm that makes me wonder if I can use this as sort of a state machine?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>> status = [:draft, :review, :publish]
=> [:draft, :review, :publish]
>> status.cycle(1)
=> #<Enumerator: [:draft, :review, :publish]:cycle(1)>
>> states = status.cycle(1)
=> #<Enumerator: [:draft, :review, :publish]:cycle(1)>
>> states.next
=> :draft
>> states.next
=> :review
>> states.next
=> :publish
>> states.next
StopIteration: iteration reached an end
         from (irb):62:in `next'
        from (irb):62
        from /Users/nolastowe/.rvm/rubies/ruby-1.9.3-p392/bin/irb:16:in `<main>'

Hmm interesting. Well maybe needs some work. :) Next is a method for dealing with loops… not sure if its great to be using with cycle, its just something that came to my head when I was playing around.

This is enough for now, next blog post will start with delete.

Exploring Arrays - Part 3

Continuing going through the array methods, using Ruby 1.9.3

Element Reference

ary[index] → obj or nil

ary[start, length] → new_ary or nil

ary[range] → new_ary or nil

slice(index) → obj or nil

slice(start, length) → new_ary or nil

slice(range) → new_ary or nil

Ok, so we’ve got the “normal” way to access an array element, simply using the name of the array, [ index ]. If item is not found at index it returns nil.

Then we have passing a start index and a length. A friend was working on rubykoans.com had question I couldn’t answer - Why is ary[4,0] an empty array and not nil?

1
2
3
4
5
6
7
8
9
10
>> ary = %w(one two three four)
=> ["one", "two", "three", "four"]
>> ary[0,0]    #expected
=> []
>> ary.index(ary.last)    # index of last item is 3
=> 3
>> ary[4,0]    # not expected, no index of 4 exists ?? why return empty array 
=> []
>> ary[5,0]    # expected, no index of 5
=> nil

The docs say

1
Returns nil if the index (or starting index) are out of range.

So yes, thats very confusing… why is it returning an empty array for last_index+1 of the array??

Moving on .. Passing a range is another way to access elements

I tried accessing an index greater than the end and it works as expected

1
2
3
4
5
6
>> ary[0..3]                        # all the elements
=> ["one", "two", "three", "four"]
>> ary[1..2]                        # just index 1 and 2
=> ["two", "three"]
>> ary[1..5]                        # accessing off the end of array
=> ["two", "three", "four"]

It looks as though slice is alias for [ ] … so everything should work the same.

Element Assignment

ary[index] = obj → obj

ary[start, length] = obj or other_ary or nil → obj or other_ary or nil

ary[range] = obj or other_ary or nil → obj or other_ary or nil

1
2
3
4
>> ary[0,2] = %w(uno dos)
=> ["uno", "dos"]
>> ary
=> ["uno", "dos", "three", "four"]

Starting at index 0 and for 2 elements, replace with a new array .. works! Never used that before! Cool

also you can use it to clear out values

1
2
3
4
5
6
>> ary
=> ["uno", "dos", "three", "four"]
>> ary[0,2] = nil
=> nil
>> ary
=> [nil, "three", "four"]

assoc(obj) → new_ary or nil

This works on an array which is a collection of arrays, and this method will find the first array where the first key matches obj. Odd, not sure when I would use this.

at(index) → obj or nil

Same thing as ary[index] .. maybe it would read better, but I’m so used the [ ] syntax, I will probably use that syntax

clear → ary

Clear, removes all elements in the array. Didn’t know this was there.

collect/map

collect {|item| block } → new_ary

map {|item| block } → new_ary

collect → an_enumerator

map → an_enumerator

Not the same collect that is in enumerable, it runs the block for each item in the array and returns an array of results.

1
2
3
4
5
6
7
8
9
10
>> %w(red blue green yellow orange).collect { |w| w.upcase }
=> ["RED", "BLUE", "GREEN", "YELLOW", "ORANGE"]

>> %w(red blue green yellow orange).map(&:upcase)
=> ["RED", "BLUE", "GREEN", "YELLOW", "ORANGE"]

>> %w(red blue green yellow orange).map(&:upcase).object_id
=> 70349437828620
>> %w(red blue green yellow orange).object_id
=> 70349434016460

You can give it a block or a “symbol to proc”, that is the funny &: followed by a method name. When I first saw that I said what the heck is that? and what is it doing? I mean, how do you google for something like that? I finally found out what it was called…”symbol to proc” and now I use it everywhere it makes sense. So Map and Collect appear to be synonyms here. Did not know that… Usually, I use collect over map since that makes more sense to me, you are collecting results.

That is all for this post, I can replace arrays in to arrays, now I know that collect and map are the same on arrays. Still there is the nagging problem of why on a 4 element array ary[4,0] returns an empty array instead of nil. Anyone know?

Other posts in this series:

Exploring Arrays - Part 2

My second blog post on the topic. Between the writings of this post and part 1 Ruby 2.0 was released on its 20th birthday! But I am going to stick with Ruby 1.9.3 for this series, maybe after I am done I’ll see what changed for 2.0

Array Documentation http://ruby-doc.org/core-1.9.3/Array.html

BTW, to make an array you can use the %w and space separated list of values, I will use that here to save on typing.

ary & other_ary → new_ary

Set Intersection—Returns a new array containing elements common to the two arrays, with no duplicates.

Oooh this sounds like math, specifically Set Theory. I did this in college but didn’t remember the ‘no duplicates’ part so I looked it up. The definition for Intersection from wikipedia is “the intersection of two sets A and B is the set that contains all elements of A that also belong to B (or equivalently, all elements of B that also belong to A), but no other elements.” So no room for duplicates there either.

Lets try it:

1
2
3
4
5
6
7
8
>> cookie_ingredients = %w(butter eggs sugar salt)
=> ["butter", "eggs", "sugar", "salt"]

>> pancake_ingredients = %w(vanilla sugar baking_powder, eggs)
=> ["vanilla", "sugar", "baking_powder,", "eggs"]

>> cookie_ingredients & pancake_ingredients
=> ["eggs", "sugar"]

If I wanted to know what ingredients I need to be sure to get enough of for baking I could make some arrays like that and get the intersection of them. Whoa I thought & for bitwise operation? Well Yes it is!! But that is for Fixnum objects. With arrays the & is an intersection! Cool .. polymorphism for the win!

Next is the * operator with two usages:

ary * int → new_ary

ary * str → new_string

Repetition—With a String argument, equivalent to self.join(str). Otherwise, returns a new array built by concatenating the int copies of self.

Lets try the * int out first:

1
2
3
4
5
>> week = %w(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
=> ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

>> week * 4
=> ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

I made an array for days of the week, then used * 4 to make a 4 week month. Seems pretty awesome to something like this without having to loop to build arrays.. if I didn’t use that I would have to write code like this:

1
2
3
4
5
6
7
8
>> four_week = []
=> []
>> 4.times do
?> four_week << week
>> end

>> four_week
=> [["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]]

Hmm can’t figure out a way to make it a single array, so I call flatten

1
2
>> four_week.flatten
=> ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

That all being said, if you want to combine an array 4 times, use * and it is easy :)

There’s other ways that might be better, but you get the idea. Much shorter to use the * int :) lets try the other version.

1
2
3
4
>> title = %w(Samuel E. Jones)
=> ["Samuel", "E.", "Jones"]
>> title * " "
=> "Samuel E. Jones"

The parameter after the * is the character to join with, basically it is calling join.

1
2
>> title.join(" ")
=> "Samuel E. Jones"

I probably would use join since that makes it more clear to the reader what you are doing and it is more common. But if you are going for ruby golf, then use the * ” ”

ary + other_ary → new_ary

Array concatenation, simply adding two arrays.

1
2
3
4
5
6
>> meals = %w(breakfast lunch dinner)
=> ["breakfast", "lunch", "dinner"]
>> snacks = %w(snack1 snack2)
=> ["snack1", "snack2"]
>> buy_food = meals + snacks
=> ["breakfast", "lunch", "dinner", "snack1", "snack2"]

Easy, next array difference.

ary - other_ary → new_ary

Array Difference---Returns a new array that is a copy of the original array, removing any items that also appear in other_ary. (If you need set-like behavior, see the library class Set.)
1
2
3
4
5
6
>> colors = %w(red purple blue green yellow orange)
=> ["red", "purple", "blue", "green", "yellow", "orange"]
>> primary_colors = %w(red blue yellow)
=> ["red", "blue", "yellow"]
>> secondary_colors = colors - primary_colors
=> ["purple", "green", "orange"]

Also pretty straight forward.

ary << obj → ary

Append—Pushes the given object on to the end of this array. This expression returns the array itself, so several appends may be chained together.

Commonly called the shovel operator you can add something to the end of the array, and since it returns an array you can do it multiple times

1
2
3
4
5
6
7
8
>> colors = []
=> []
>> colors << "red"
=> ["red"]
>> colors << "blue"
=> ["red", "blue"]
>> colors << "green" << "orange"
=> ["red", "blue", "green", "green", "orange"]

Chaining << is just like chaining other methods:

1
2
>> "first name".gsub(" ","_").upcase
=> "FIRST_NAME"

which is basically

1
2
>> colors.<<("red").<<("green")
=> ["red", "green"]

without the extra parenthesis. Cool, I hadn’t realized you could chain << before now!

Next, a method with a funny name. <=>

ary <=> other_ary → -1, 0, +1 or nil

Comparison—Returns an integer (-1, 0, or +1) if this array is less than, equal to, or greater than other_ary. Each object in each array is compared (using <=>). If any value isn’t equal, then that inequality is the return value. If all the values found are equal, then the return is based on a comparison of the array lengths. Thus, two arrays are “equal” according to Array#<=> if and only if they have the same length and the value of each element is equal to the value of the corresponding element in the other array.

I’ve only seen this used when writing custom methods to determine equality, but it seems pretty straight forward. I will play with it when I play around with enumerable.

ary == other_ary → bool

Equality—Two arrays are equal if they contain the same number of elements and if each element is equal to (according to Object.==) the corresponding element in the other array.
1
2
3
4
5
6
>> [1,2] == [2,1]
=> false
>> [1,2,3] == [1,2]
=> false
>> [1,2] == [1,2]
=> true

To be equal they have to have the same number of elements and same ordering of elements. The first and last examples show that.

I didn’t learn anything earth shattering this time, but it is a good review of some basic arrays and set operations.

Exploring Arrays - Part 1

Everytime that I have to lookup something with hashes or arrays, I find lots of methods that I didn’t know about, so I thought I’d do an experiment where I will learn about each one and write some examples and try to understand how to use it. I kind of picture someone sitting next to me as I do this, reading the docs and trying them out with me.

Ruby 1.9.3 Array Documentation

Class Methods

Class methods always start with the name of the class, dot, followed by method name. For example, we can call Time.now as a class method on the Time class, which returns a new Time object initialized with the current time.

Docs say:

[](*args)

[](*args)
Returns a new array populated with the given objects.

There are three usage examples in the docs, lets try them out and see what they do, first:

1
2
3
4
>> Array.[](1)
=> [1]
>> Array.[](1,2,3)
=> [1, 2, 3]

The method name is [] and the params is *args which is the splat operator which takes any number of objects. Interesting I’ve never seen this used in the real world. I am sure its used cleverly, I just don’t see it! I showed this to a friend Danielle Sucher and she said:

I actually always think it’s nifty that something like a[0] can be called with a.send(:[], 0) instead. Makes it possible to do stuff like a.try(:[], 0) or a.tap{}.send(:[], 0).

Thanks!! Moving on..

1
2
>> Array['a','b','c']
=> ["a", "b", "c"]

Returns array with the contents of *args just as it says. This is one way you can be “confident” of your code as Avdi talked about in Confident Coding . If you want an array, make sure its an array! if its not an array it will put it inside an array like this:

1
2
3
4
>> Array(1)
=> [1]
>> Array([1])
=> [1]

Parentheses is optional in ruby so these are the same:

1
2
3
4
5
6
>> Array 1
=> [1]
>> Array [1]
=> [1]
>> Array([1,2,3]) == Array[1,2,3]
=> true

Looks funny without the () doesn’t? I almost always use () for methods. Helps later on if you decided to add more things on that line you don’t have to go back and add them. See Avdi’s RubyTapas Episode 024 Incidental Change $9 a month screencasts that come out 3x week, so good!! Sign up now! :)

And lastly, the way you might normally create arrays, with [ *args ]. I tried to dig through Kernel to see if [] was a method on kernel that would call Array.new but I couldn’t find anything. So I am still puzzled about how this actually works. Maybe a reader has an insight?

1
2
>> [1,2,3]
=> [1, 2, 3]

Array.new

new(size=0, obj=nil)
new(array)
new(size) {|index| block }
Returns a new array.

So if no params, default is size 0 and value of index 0 is nil

1
2
3
4
>> a = Array.new
=> []
>> a[0]
=> nil

Creates an empty array. Default value is nil.

If you pass a single param, it makes an array of that size.

1
2
3
4
>> a = Array.new(5)
=> [nil, nil, nil, nil, nil]
>> a.size
=> 5

Creates an array with 5 elements with the default value is nil

If we pass two params, the second is the default value of the empty elements

1
2
3
4
5
6
7
8
>> a = Array.new(5, "-empty-")
=> ["-empty-", "-empty-", "-empty-", "-empty-", "-empty-"]
>> a[0]
=> "-empty-"
>> a[1]
=> "-empty-"
>> a[0].object_id == a[1].object_id
=> true

So the default value of each element is the string “-empty-” and they are in fact the same object.

Lets create an array of basic family members, adding it to her_side and his_side. Then I added another family member to his_side and prove they are copies of the parents and not the same object.

Second version is passing an array to Array

1
2
3
4
5
6
7
8
9
10
11
12
>> parents = ["mom", "dad"]
=> ["mom", "dad"]
>> her_side = Array.new(parents)
=> ["mom", "dad"]
>> his_side = Array.new(parents)
=> ["mom", "dad"]
>> her_side == his_side
=> true
>> his_side << "grandma"
=> ["mom", "dad", "grandma"]
>> her_side == his_side
=> false

And finally the third form uses a block:

1
2
>> b = Array.new(5) { |index| "-#{index}-" }
=> ["-0-", "-1-", "-2-", "-3-", "-4-"]

Interesting, maybe if you wanted an array like this

1
2
>> b = Array.new(5) { |index| index* 5 }
=> [0, 5, 10, 15, 20]

Cool!

try_convert(obj) -> array or nil

Tries to convert obj into an array, using to_ary method. Returns the converted array or nil if obj cannot be converted for any reason. This method can be used to check if an argument is an array.
1
2
3
4
>> Array.try_convert(1)
=> nil
>> Array.try_convert([1,2,3])
=> [1, 2, 3]

Hmm, so I guess this would be good if you only want to return array if its an array and nil otherwise. Never seen it used myself but it be a way to write confident code if you only want to respond to nil or array and use a bunch of if statements.

Cool, I had fun poking at ruby array class methods and trying things out. Be sure and checkout the gotchas in the docs. I hope I was able to shed some light or at least make you think about some of the public methods of arrays. If you have some insight on how some of these work, please leave a note in the comments.

Thank you to Danielle Sucher @DanielleSucher for helping by proof-reading this post as I am working on improving my writing.

Next post in this series will be on instance methods!

Reading Books Cover-to-Cover

I wanted to buy “Practical Object-Orientated Design in Ruby” by Sandi Metz when it first came out, and I had a hard time justifying it because there are many books I have bought and have not read all the way through. So I thought I’d do an experiment in reading a tech book cover-to-cover and then I’ll buy “poodr”. So my first cover-to-cover read was Eloquent Ruby by Russ Olsen. Not all books should be read cover-to-cover but when you read a book cover-to-cover you’ll discover a few things:

  • what topics are there and how deep they are
  • what topics are not
  • the sequence and structure of the book, about where things are so its easier to flip back to review

And lastly, you’ll be able to speak authoritatively to someone when you say “Read this book!”

I bought Eloquent Ruby perhaps 1.5 years ago, and after the first couple chapters decided it was the most awesome book ever and how much smarter I would have been had I gotten it sooner. I read maybe 1/3 of the way through, I skipped around some, the testing chapters and the metaprogramming. Even with skipping around in the book, I quickly became an evangelist for this book. I told every ruby developer I encountered to buy it, I even got a copy for my last company. It’s just plain good, you’ll learn the ruby idioms and why. I’ve been programming since I was 13 and got pretty good at memorizing the syntax of things, not truly understanding why or how, but “type this thing to do that thing”. But Eloquent Ruby helped me understand why behind the syntax. Now that I understand “why”, it is so much easier to remember without relying on memorization.

That is why I chose this book to read as my first cover-to-cover read.

I needed a way to keep track of my progress since I use different devices and software (mac, iphone, ipad, android nexus) I can’t rely on a cloud service to “sync my place” across all of them. I use an Evernote note with all the chapters as a checkbox list. Plus, I love checking things off a list. I would see my progress and be able to pick back up where I left off each reading session. The chapters in Eloquent Ruby are pretty short, so it was easy to read in small chunks of time. I read it at break at work, on the bike at the gym, riding in car, just about anywhere. It took a couple months to get through all the chapters this way.

It didn’t take long to realize one of the benefits of reading cover-to-cover. When I was almost done with the book, a friend was having problems with some concept in ruby and I remembered there was a chapter about it, near the beginning of the book. I flipped around a few minutes and found the prefect chapter for her to read. Had I not read it cover-to-cover I may not have known that content was there or wouldn’t have been as confident recommending it and my “find it in this chapter” instructions.

My “reward” for finishing Eloquent Ruby was to get Sandi Metz’s book “Practical Object-Orientated Programming in Ruby”.

I followed the same process and created a list of chapters in Evernote, planning to read them in bits at home, gym and work breaks. At only 247 pages, it is quite a bit shorter than Eloquent Ruby with 447 pages so I knew it would take alot less time.

Chapter 1 came easily enough and I checked it off. Then I was surprised to find out what followed was that I could not put the book down. Instead of my next reading time or gym appointment, I read till 2 in the morning, picked back up and finished it the next morning (it probably helped that I was home sick with the weekend to myself). I was so excited about what I was learning, I wanted to stop reading and refactor code I wrote a few days ago. I so wanted to skip ahead to Chapter 9 on tests. However, I stuck to original plan of cover-to-cover and read all the way through. It is an incredible book.

I say incredible not just because “I learned the right way” but because it validated so many instincts and gut feelings I have about class design. Having those things in writing gives a source to “cite” in discussions and confidence to say “Yes, this is how we will do this thing”.

So as a result of my experiment I would recommend these two things to anyone wanting to improve their knowledge of ruby:

  1. Get these two books.
  2. Read them cover-to-cover.

I’m confident that you will enjoy both the information and the reading experience.

BTW these are affiliate links, maybe I’ll earn enough to get a cup of coffee eventually.

Simple Breadcrumbs

I needed a simple breadcrumb module/class that would let me set the first crumb and add to it later. I looked at www.ruby-toolbox.com and saw a bunch, none of them looked simple enough for me. I already had a template so I dont care about changing that…so I whipped up my own breadcrumbs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Breadcrumb

  Crumb = Struct.new(:name, :link)

  attr_reader :crumbs

  def initialize(name = "Home", link = "/")
    @crumbs = []
    self.add(name, link)
  end

  def add(name, link)
    @crumbs << Crumb.new(name,link)
  end

end

After watching www.rubytapas.com talk about using Struct (I had never really used it before or understood why not just make a class). At first I defined crumb outside of Breadcrumb, then after I had tests, moved inside and it still worked. It seems a bit odd, to have that inside Breadcrumb, but its only accessible inside Breadcrumb so I guess that is good.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
describe Breadcrumb do

  describe '#new' do

    it 'sets default crumb of Home /' do
      @breadcrumb = Breadcrumb.new
      @breadcrumb.should have(1).crumb
      @breadcrumb.crumbs.first.name.should == 'Home'
      @breadcrumb.crumbs.first.link.should == '/'
    end

    it 'sets initial crumb of Main /main' do
      @breadcrumb = Breadcrumb.new('Main', '/main')
      @breadcrumb.should have(1).crumb
      @breadcrumb.crumbs.first.name.should == 'Main'
      @breadcrumb.crumbs.first.link.should == '/main'
    end

  end

  describe '#add' do

    it 'a second crumb' do
      @breadcrumb = Breadcrumb.new
      @breadcrumb.add('Products', '/products')
      @breadcrumb.should have(2).crumbs
    end

  end

output of spec doc

1
2
3
4
5
6
Breadcrumb
  #new
    sets default crumb of Home /
    sets initial crumb of Main /main
  #add
    a second crumb

I did a codereview on twitter and got some good comments, and my code is better because of it! Thanks @benhamil and @therealadam. See the comments on initial versions of the code.

Using ActiveModel to Validate Input

The other day I was working a project where I had to validate some input before running a query:

Say I have a database of friends and their address, and I want to find all friends with at least 3 letters of the name and an optional zipcode. The controller looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def index
  @name = clean_name(params[:name])
  @zip = params[:zip]
  if @name.present? && @name.size > 2
    if @zip.present? && @zip.match(/^\d{5}$/)
      @friends = Property.where( "name like ?", "%#{@name}%").where("zip_code = ?", @zip)
    else
      @friends = Property.where( "name like ? ", "%#{@name}%")
    end
  else
    @friends = []
  end
end

private

def clean_name(str = "")
  str.gsub(/mrs?|miss|ms|jr|sr/i, "").strip if str.present?
end

Ugly huh? Too many if statement and validation and checking for blanks. I was in a rush, so I was trying to get it out there and move on with life, but when I needed the same validation in another action, I figured it was time to bite the bullet and Do It The Right Way.

I started off with a plain old ruby object (PORO) in lib directory so I can validate the params for a search query there (in past, I’ve put objects like this in models since its sort of a model, just not a database model, so .. I am 50/50 on the issue. Meh. I’ll figure out the best location later if need be).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class SearchParams

  attr_reader :name, :zip_code

  def initialize(args)
    @name = clean_name(args[:name])
    @zip_code = args[:zip_code]
  end

  private

  def clean_name(str = "")
    str.gsub(/mrs?|miss|ms|jr|sr/i, "").strip if str.present?
  end

end

Then for the controller:

1
2
3
4
5
6
7
8
9
10
11
12
def index
  @search_params = SearchParams.new(params)
  if @name.present? && @name.size > 2
    if @zip.present? && @zip.match(/^\d{5}$/)
      @friends = Property.where( "name like ?", "%#{@search_params.name}%").where("zip_code = ?", @search_params.zip)
    else
      @friends = Property.where( "name like ? ", "%#{@search_params.name}%")
    end
  else
    @friends = []
  end
end

And now that it param in its own class, its much easier to test (I personally despise testing controllers)..and that private method is out of the controller, yay!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
describe SearchParams do
  it "should initialize the Search object" do
    @search = SearchParams.new(name: "blah", zip_code: "12345")
    @search.name.should == "blah"
    @search.zip_code.should == "12345"
  end

  context "clean name" do

    it "should clean name modifiers from search query" do
      keywords = %w(mr mrs miss jr sr)
      keywords.each do |keyword|
        @search = SearchParams.new(name: "#{keyword} Bob", zip_code: "12345")
        @search.name.should == "Bob"
      end

      keywords.each do |keyword|
        @search = SearchParams.new(name: "blah #{keyword.upcase!}", zip_code: "12345")
        @search.name.should == "Bob"
      end
    end

  end
end

That first test is just sort of a sanity test, to make sure everything is working. I may delete it later. Then I test cleaning the modifiers both lowercase and uppercase to confirm the case insensitivity of the regex (maybe not necessary). The each loop there actually makes several tests in loop.

Better but not by much. Lets add validations from http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html and see if we can cut down on those ugly if statements.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class SearchParams
  include ActiveModel::Validations
  validates :name, presence: true, length: { minimum: 3 }
  validates :zip_code, format: /^\d{5}$/, allow_blank: true

  attr_reader :name, :zip_code

  def initialize(args)
    @name = clean_name(args[:name])
    @zip_code = args[:zip_code]
  end

  private

  def clean_name(str = "")
    str.gsub(/mrs?|miss|ms|jr|sr/i, "").strip if str.present?
  end
end

Awesome. Now the controller code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def index
  @search_params = SearchParams.new(params)

  if @search_params.valid?
    if @search_params.zip_code.present?
      @friends = Friend.where( "name like ?", "%#{@search_params.name}%").where("zip_code = ?", @search_params.zip_code)
    else
      @friends = Friend.where( "name like ? ", "%#{@search_params.name}%")
    end
  else
    @friends = []
  end

end

Looks better, we can just do a .valid? call to see if the name is of valid length and the zipcode (if its provided) meets the the requirements of 5 digits. Nicely refactored and now its easier to test. Now we can test the validations:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
context "validations" do
  it "should not be valid for name length of 1" do
    @search = SearchParams.new(name: "b")
    @search.should_not be_valid
  end

  it "should be valid for name length of 3" do
    @search = SearchParams.new(name: "bla")
    @search.should be_valid
  end

  it "should allow blank for zip_code" do
    @search = SearchParams.new(name: "blah", zip_code: "")
    @search.should be_valid
  end

  it "should not allow 1 for zip_code" do
    @search = SearchParams.new(name: "blah", zip_code: "1")
    @search.should_not be_valid
  end
end

BTW since there is a method called valid? and it returns a boolean (obviously with the ? at end) in rspec you can just do be_whatever to call that method in your tests.

Beautiful!! … I sleep better tonight knowing I’ve made beautiful code :) :) :) :)

Better Code Through Code Reviews

For one of my projects we have started doing code reviews. We use github, work in a branch, then submit a pull request for review. Looking at github you can see a nice diff of the changes and you are able to add comments. So github is one way. You could also just use

1
git diff  master..myawesomebranch 

And get a decent diff.

I prefer to code review live if the other person is available in person (screensharing would work too). It makes it easy to ask why this, and did you consider this and then after discussion you can make a note of what to change.

Its super easy to nit pick at someones code, after all programming is alot of your personal style. But there are sometimes where you say “umm ok thats different, cool lets move on” and sometimes where you can say “hmm, what do you think of this instead” like for example

1
2
3
  unless something == "something" && !this.method(that) do
     // this awesome thing
  end

yes it works (but I didn’t question if it works or not, I’m thinking of humans reading this code later!), but lets consider:

1
2
3
  if something != "something" && this.method(that) do
     // this awesome thing
  end

I think its a little more readable, but when I make suggestions I like to open the door for discussion, and perhaps I don’t understand all the code and it gives the other person to explain it. Sometimes they answer with “oh well i didn’t write that part” .. That is OK!! when I do a code review I am taking it as you saying “hey this code was my responsibility, I added some code, fixed some confusing parts and submit it you for review.”

I rarely do git blame to see who did something because it doesn’t matter most of the time who did that weird bit of code. Most likely it was a build up of code and the author didn’t stop to think about refactoring, or he/she was under time constraints. That’s the normal evolution of programming and we are trying to break that habit with reviews. But if I find a confusing bit of code that I can’t figure out, then maybe I’ll do git blame to see who last edited that so I can go to them and ask for some help in understanding it. Coding is never a perfect process. This is why code reviews are good.

I like code reviews alot and have done them at a few different companies and with people having the right attitudes it goes a long way to making better code.