Ruby, etc

Learn all the things

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

Testing Routes With RSpec and Minitest

The poor often forgotten routes folder in your tests or specs folder (if you even have one!). People don’t know what goes in them or how to write them. I like to write them because they are pretty easy to write and often a great first-step when it comes to a legacy codebase.

It gives you the chance to get a good look at that routes file and see if there are routes there you really don’t need? Often the resources :whatever is the culprit, the others are either out of date (the controller/action was removed but routes file never updated) .. I wondered why should you only include the routes you need? what harm is there? It make the rake routes file cleaner but are there other reasons to be very specific in routes.rb ?

So I sought the wisdom of twitter:

Peter Harkins @pushcx
Documentation to future coders.
--
Karthik Hariharan @hkarthik 
avoids the "action controller method not found" errors and pushes 
a 404 instead of a 500. Really important with REST APIs.
--
Brad Fults @h3h
FWIW, I highly recommend avoiding `resources` and preferring 
a `get/post/patch` for every route. Much clearer.  
--
Caleb Thompson @calebthompson 
:only 

I got some really good answers!! See all the responses

Avoiding the resources magic is one way to make it very clear:

1
2
3
get "/users", "users#index"
get "/users/:id", "users#show"
post "/users", "users#create"

Verses resources style:

1
resources :users, only: [:index, :show, :create]

Using only is also pretty clear and maybe less messy? This probably come down to personal preference and which way allows you to sleep best at night. Decide with your team so you can be consistant in your routes.rb file.

So how do you test them?

It depends on what test framework you are using. Here’s what I’ve figured it out.

RSpec

1
2
3
4
5
6
7
8
9
10
11
  context "should route to member_sessions" do
    it "should initialize a new session" do
      expect(get: "/member_sessions/new").to route_to(controller: 'member_sessions', action: 'new')
    end
    it "should create a new session" do
      expect(post: "/member_sessions").to route_to(controller: 'member_sessions', action: 'create')
    end
    it "should destroy a session" do
      expect(delete: "/member_sessions/1").to route_to(controller: 'member_sessions', action: 'destroy', id: "1")
    end
  end

This will test that the method, url and params will go to the right controller/action. It seems pretty straight forward right?

Minitest / TestUnit

We have three methods:

  • assert_generates - testing that the provided url, will break down to a controller,action and parameters
  • assert_recognizes - testing that rails will recognize the route, given controller and action, it goes to a certain method and path
  • assert_routing - a combination of the above, almost literally, if you look at the source!

One thing I can’t figure out is how to test the methods along with the routing info like I can with RSpec. We can test in other ways (feature tests), but its not quite as nice as RSpec. I guess that is just a difference in the two frameworks. I found when the same path is common to multiple methods, than assert_generates works and assert_routing does not (and assert_recognizes does not also). For example in the case of Create, Update, Delete and Show they use the same path so I have to use the assert_generates to that the path goes to the right controller.

1
2
3
4
5
6
| method | path          | controller |
| ------ | ------------- | ---------- |
| create | /register/:id |  register  |
| update | /register/:id |  register  |
| delete | /register/:id |  register  |
| show   | /register/:id |  register  |

So once I realized that, I understood (duh) which route testing methods to use. Some might argue these are pointless, but I still think its valuable as it forces you to really think about your routes.

1
2
3
4
5
6
7
8
class RoutingTest < ActionDispatch::IntegrationTest
    it "routes to register index" do
      assert_generates "/register", controller: "register", action: "index"
    end
    it "routes to register show" do
      assert_generates "/register/1", controller: "register", action: "show", id: "1"
    end
  end

These are mostly the same, except for the starting of the test. The testunit style has a class and spec style has a description. The describe string must end in Acceptance Test.

1
2
3
4
5
6
7
8
9
describe "Routing Acceptance Test" do
  it "routes to register index" do
    assert_generates "/register", controller: "register", action: "index"
  end

  it "routes to register show" do
    assert_generates "/register/1", controller: "register", action: "show", id: "1"
  end
end

As I’ve been writing route tests, I’ve increase the security, clarity and interface to my apps. My routes file has become a very clear documentation of the api of my application. I hope that testing routes becomes as important to you as it is for me!

Leveling Up on Rspec

The other day I saw there was a Rspec option in .rspec I didn’t know about and I thought what else do I not know about Rspec? I set myself to dig around in the command line options and source code to see if I could figure out anything else cool. Here are a few of the things I’ve learned:

Require all the time

This is what triggered my curiosity, finding this in .rspec:

1
--require spec_helper

This will add that require to the top of all your test files, and since all your test files have that require at the top, this cleans up the tests files (and you dont forget it to add it). Cool right? This should go in .rspec in the project folder.

Local Options

I knew about ~/.rspec (in your home directory) and .rspec (in the root of project directory), but digging around in the Rspec source there is also .rspec-local which looks to be the place to put personal preferences for the current project. I imagine this might be useful if the team wanted to use a certain formatter and you liked a different one. According to repo this was added 2 years ago, I had no idea! This would be one of the files you would put in your .gitignore.

Dry Run

Want to see how your wording looks with the format documentation (I like to make it read like a happy ending story).

Use this

1
rspec --dry-run -f documentation

You can also add this into a config file, but most likely you’ll just want to run it occasionally so command line is the way to go here.

Fail Fast

Tired of running the test suite and seeing some pass and some fail, but having to wait till all the tests are done? Add --fail-fast to your command line (or .rspec-local) to have the tests stop after the first failure. This is one option I think would be good to keep in local since it might be personal preference.

Run one test

There are many ways to tell Rspec that you want to just run a single test:

Passing --example and the name of the test (it “test name”)

1
rspec --example "should group in words of 3"

Or just enough of the name to make it unique. Also you can use -e instead of –example

1
rspec -e "should group in"

Or you can specify the line number, but be aware this might change as you modify line above this.

1
rspec spec/lib/memory_spec.rb:11

Run Focus Test

An alternative to Run one test is to use the focus. First set it up in the spec_helper to run only the focus: true if it exists anywhere, otherwise it runs all the specs so you can totally leave this in the spec_helper file all the time if you like it!

1
2
# in spec_helper.rb
config.filter_run :focus

Then in your test add focus: true after the name, like so:

1
it "should group in words of 3", focus: true do

I think in future I am going to use focus: true if i am running tests on the command line as I develop them, would make it easier then running the test name or line number because those might change as I develop.

Test Formatters

The default report style for Rspec is fine, I like format –documentation and some time ago I found this one by Tim Pope Fivemat. Add that to your gem file then add in your Rspec config ‘fivemat’

1
2
3
4
add to .rspec
--format Fivemat
or specify on command line
rspec -f Fivemat

Looks like this:

1
2
3
Memory ............
User ......
Address ..

Name of the class, plus a green dot for each passing test. Also for test failures there is less noise so this is a favorite of mine.

Update, added: NyanCat Formatter

I certainly feel like I’ve Leveled Up my Rspec and hope you have too! :) Code on!!

Exploring Arrays Part 5

BTW Going to use Ruby 2.1.2 from here on out

Yes, it has been awhile but (who has time to dwell on the past?) I haven’t forgotten I was going through each array class! My last post said next was delete, so let’s get to it!

delete

delete(obj) → item or nil 
delete(obj) { block } → item or result of block

Ok first one looks pretty straight forward, it returns item if it found it and nil if it doesn’t. Lets try it out:

1
2
3
4
5
6
7
8
9
10
>> colors = %w(red blue green yellow)
=> ["red", "blue", "green", "yellow"]
>> colors.delete("blue")
=> "blue"
>> colors
=> ["red", "green", "yellow"]
>> colors.delete("can't find me")
=> nil
>> colors
=> ["red", "green", "yellow"]

I deleted “blue” and it found it because it returned “blue”. The array is now changed, contains no “blue”. When you try to delete a value which is not there, “can’t find me” it doesn’t throw an exception, just returns nil and does not change the array. What happens if the array is empty? Lets say I made myself a todo list and deleted thing as I finished them:

1
2
3
4
5
6
7
8
9
10
11
12
>> todo = ["get up", "drink coffee", "study ruby"]
=> ["get up", "drink coffee", "study ruby"]
>> todo.delete("get up")
=> "get up"
>> todo.delete("drink coffee")
=> "drink coffee"
>> todo.delete("study ruby")
=> "study ruby"
>> todo.delete("do it again")
=> nil
>> todo
=> []

So nil is the result when the item is not found OR the array is empty. So, don’t depend on the return value too much since it can be nil for multiple reasons. Delete is not a great method for checking off things in your todo list!

delete_at

delete_at(index) → obj or nil

Where as delete would delete from the array at the value, delete_at will delete at the specified index.

1
2
3
4
5
6
>> colors = %w(red orange yellow green blue)
=> ["red", "orange", "yellow", "green", "blue"]
>> colors.delete_at(3)
=> "green"
>> colors
=> ["red", "orange", "yellow", "blue"]

Pretty simple, let see what happens when you try to delete at an invalid index:

1
2
>> colors.delete_at(100)
=> nil

So once again, if its an invalid index you get nil just like if there is an invalid value, you get nil. Lets move on!

delete_if

delete_if { |item| block } → ary
delete_if → Enumerator

So looks like if takes a block that tells us what items will be deleted from the array. Lets delete all color names that are greater then a length of 5 characters.

1
2
3
4
>> colors = %w(red orange yellow green blue)
=> ["red", "orange", "yellow", "green", "blue"]
>> colors.delete_if { |color| color.length > 5 }
> ["red", "green", "blue"]

So it deletes from the array, every element for which the block is true. And its true for values orange, yellow and green. Leaving us with red, green and blue. The docs say its the same as reject! … yay for being like php!

drop

drop(n) → new_ary

So it takes the array and removes the first N elements and returns the rest.

1
2
3
4
?> colors = %w(red orange yellow green blue)
=> ["red", "orange", "yellow", "green", "blue"]
>> colors.drop(2)
=> ["yellow", "green", "blue"]

We drop the red and orange elements, and return the rest which is yellow, green and blue. Pretty straightforward, Ok, next method!

drop_while

drop_while { |arr| block } → new_ary
drop_while → Enumerator
1
2
3
=> ["red", "orange", "yellow", "green", "blue"]
>> colors.drop_while { |color| color.length != 4 }
=> ["blue"]

This one drops all elements for which the block is NIL or False. So if we wanted all the colors whose length was NOT 4, we would only get one element of blue.

each

each { |item| block } → ary click to toggle source
each → Enumerator

This one is easy, we use it all the time..

1
2
3
4
5
6
7
8
>> colors = %w(red orange yellow green blue)
=> ["red", "orange", "yellow", "green", "blue"]
>> colors.each { |color| puts color }
red
orange
yellow
green
blue

each_index

each_index { |index| block } → ary click to toggle source
each_index → Enumerator

Whereas each gives you the value each time, this gives you the index.

1
2
3
4
5
6
7
8
>> colors = %w(red orange yellow green blue)
=> ["red", "orange", "yellow", "green", "blue"]
>> colors.each_index { |color_index| puts color_index }
0
1
2
3
4

empty?

empty? → true or false

This checks if there are any elements in the array, I experimented with nil, empty or whitespace and the only thing that returns true is no elements.

1
2
3
4
5
6
7
8
?> [nil,nil].empty?
=> false
>> ["",""].empty?
=> false
>> [" "," "].empty?
=> false
>> [].empty?
=> true

This seems like a good place to stop, next blog post will start with eql?

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?

  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 :)
  • [CodeWars)(http://www.codewars.com) - Small problems, edit and test code right in browser!
  • 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.