Ruby, etc

Learn all the things

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

Using Jshint

Javascript. It’s a language that some of us love to hate, me occasionally. Here’s a few notes to myself to make JS a little better :)

Use these settings in JSHint to avoid instanity:

1
2
3
4
file: .jshintrc
{
  "flagname" : true
}

If you have settings that apply to only your test environment you can put those in test/.jshintrc (maybe allowing global var for your test function) .. you can extend a confiuration in another file with this option `”extends” : “../.jshintrc”

Sometimes you just can’t please everyone, including the linter. Here’s how to ignore blocks or lines from the linter:

To ignore a block of code use

1
2
3
/* jshint ignore:start */
myBadJsHere
/* jshint ignore:end */

to just ignore a single line:

1
myBadJsHere // jshint ignore:line

Obviously you shouldn’t let the linter ignore code but you may have a good reason to do so.

Handy thing to have in your .jshintrc file:

eqeqeq

1 != “1” right? comparing a number to a string? no, JS says sure its the same using automatic type conversion. Use this flag to warn you and remind you to use triple equals to not do automagic type conversion.

Switch statements

This was just a neat thing I learned today, in JS switch/case statements you need to do a return or break or you will fall through to the next option. Leave a note for the next guy that says you did mean to fall through with a comment /* falls through */ and you will silence the warning from jslint. Kinda cool, huh?

Use Strict

"use strict";

This tells javascript to cut the funny business and not be so helpful and error when stuff should error.

I picked up some of these tips watching Pluralsight: JavaScript Best Practices

Thanks for humoring me as I write these notes to myself :)

Ruby Like Python

I did python.. awhile back, it was like ruby in some ways and in some ways not. So I picked one, I went full blown into Ruby. Recently I’ve seen lots of job postings for Python so I figured I’d give it another go :)

Slicing

In Python:

1
2
3
4
5
6
7
>>> message = "hello world"

>>> message[0:5]
'hello'

>>> message[6:]
'world'

Then in ruby

1
2
3
4
5
6
7
8
2.4.0 :001 > message = "hello world"
 => "hello world"

2.4.0 :002 > message[0..5]
 => "hello "

2.4.0 :003 > message[6..-1]
 => "world"

Eveything in ruby is an object and objects have methods. String has a method slice, aliased to [] (cool!) and the .. is a range. You could use a comma but there is so way to tell it to use the end unless using a range. If you look at the params for the slice method it is a fixnum or fixnum, fixnum or a range. It can also take a string (if you use the method name) but that is a strange use.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
2.4.0 :005 > message
 => "hello world"

2.4.0 :006 > message.slice("ello")
 => "ello"

2.4.0 :007 > message
 => "hello world"

2.4.0 :008 > message.slice!("ello")
 => "ello"

2.4.0 :009 > message
 => "h world"

Unless you use slice! (bang) does it actually change/do anything remotely interesting. Probably I would find a more clear way to do it than using slice with a string.

Well this is just one aspect of the differences and I am not sure if there are differences in the versions of python too.

Setting Up a New Ruby or Rails Project

A checklist to follow when starting a new project if you are using rbenv or rvm:

Make sure this is in your .bashrc or .zshrc

1
alias be="bundle exec"

Then any time you would need bundle exec you can just use be. Or alternatively, Hal Fulton pointed out you can do bundle exec bash to get a bash shell that would be the same as using be each time :)

  1. Create a directory for your project and change into it.
  2. Create a Ruby version file: echo "2.4.0" > .ruby_version.
  3. Change out of directory and back in, and ensure your version of ruby is correct with ruby -v.
  4. Make sure Bundler is installed: gem install bundler.
  5. Create a Gemfile bundle init.
  6. Setup git repo with git init.
  7. Create a README file and put the name of your project and what it is used for.
  8. Add all files git add ..
  9. Commit git commit -m "inital commit".

Then if you are making a ruby gem:

  1. Use bundle gem myawesomegemor do it by hand (helps you to remember.. hehe)
  2. Create a gemspec touch myawesomelibrary.gemspec.
  3. Make directory: mkdir lib.
  4. Make library file: touch lib/myawesomelibrary.rb.
  5. Make test directory: mkdir test.
  6. Make test file: touch test/myawesomelibrary_test.rb.

Gem spec template:

1
2
3
4
5
6
7
8
9
10
11
12
13
Gem::Specification.new do |s|
  s.name        = 'myawesomelibrary'
  s.version     = '0.0.0'
  s.date        = '2017-01-01'
  s.summary     = "My awesome library summary"
  s.description = "My awesome library description"
  s.authors     = ["Awesome Programmer"]
  s.email       = 'myself@awesomeprogramming.com'
  s.files       = ["lib/myawesomelibrary.rb"]
  s.homepage    =
    'http://rubygems.org/gems/myawesomelibrary'
  s.license       = 'MIT'
end

If you are making a rails app:

Add the version of Rails you want to use to the Gemfile ie: rails "5.0.1" and bundle install. Then do rails new . to create a rails app with the same name as current directory.

Enumerable: Any?

This is about the handy any? method in Enumerable

The documentation says

Passes each element of the collection to the given block. The method returns true if the block ever returns a value other than false or nil. If the block is not given, Ruby adds an implicit block of { |obj| obj } that will cause any? to return true if at least one of the collection members is not false or nil.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Taco
  attr_accessor :meat

  def initialize(meat)
    @meat = meat
  end

  def beef?
    @meat == :beef
  end

  def chicken?
    @meat == :chicken
  end

end

Lets test it out

1
2
3
4
5
6
7
8
irb(main):018:0> taco = Taco.new(:beef)
=> #<Taco:0x007fa374070278 @meat=:beef>

irb(main)> taco.beef?
=> true

irb(main)> taco.chicken?
=> false

Lets create two instances

1
2
3
tacos = []
tacos.push(Taco.new(:beef))
tacos.push(Taco.new(:chicken))

Now since the array has enumerable and we made some handy methods to test the meat of our tacos we can easily check our array to see if we have any chicken tacos:

1
tacos.any? { |taco| taco.chicken? }

If all the elements of the array are booleans as in this case we don’t need the block version:

1
2
3
4
5
irb(main)> possible_chicken_tacos = [tacos[0].chicken?, tacos[1].chicken?]
=> [true, false]

irb(main)> possible_chicken_tacos.any?
=> true

Yep, today was definately a chicken taco day. :)

Exploring Arrays Part 6

Continuing on through the array methods… now using ruby 2.2.0preview1 :)

eql?

eql?(other) → true or false
Returns true if self and other are the same object, or are both arrays with the same content (according to Object#eql?).

Lets try it on structs first. A struct is an easy way to make an object in ruby. First I define a struct of a User with two attributes:

1
2
irb(main):001:0>  User = Struct.new(:name, :age)
=> User

Ok now lets create some objects

1
2
3
4
5
6
7
8
irb(main):002:0> bob = User.new("Bob", 35)
=> #<struct User name="Bob", age=35>

irb(main):005:0> bob2 = User.new("Bob", 35)
=> #<struct User name="Bob", age=35>

irb(main):006:0> bob.eql?(bob2)
=> true

Ok we have two objects, same data name and age and eql? returns true.

1
2
3
4
irb(main):007:0> bob3 = User.new("Bob", 32)
=> #<struct User name="Bob", age=32>
irb(main):008:0> bob.eql?(bob3)
=> false

Making a third object with different data returns false as advertised. Lets look at the object_ids for each of these objects:

1
2
3
4
5
6
irb(main):011:0> bob.object_id
=> 70351123976940
irb(main):009:0> bob2.object_id
=> 70351128238140
irb(main):010:0> bob3.object_id
=> 70351124267600

I was curious if the items containing the same values had the same id (probably not..) and it looks like it is not the same object. It looks like the eql? method does compare the values in the attributes of the objects. Cool!

Let’s see what else eql? works on … How about strings:

1
2
3
4
5
6
7
8
9
10
11
irb(main):012:0> s = "what up internet"
=> "what up internet"

irb(main):013:0> s.eql?("blah")
=> false

irb(main):014:0> s.eql?("what up internet")
=> true

irb(main):015:0> s == "what up internet"
=> true

Looks like you can use eql? in place of == if you are doing string equality. Not sure I would do it.. it does look kinda nice but also kind of like java :) Probably I would just use ==. But now I know that if I see it used that way it works as it appears.

Lets try arrays

1
2
3
4
5
6
7
8
9
10
11
irb(main):018:0> colors = %w(red green blue)
=> ["red", "green", "blue"]

irb(main):019:0> colors.eql?(["red", "green", "blue"])
=> true

irb(main):020:0> colors.eql?(["red"])
=> false

irb(main):022:0> colors.eql?(["blue", "red", "green"])
=> false

It works, if the array is an exact match, values and order. That leaves numbers which is pretty obvious, only exact matches since numbers are objects too!

1
"1".eql?(1)

Compare to javascript

1
2
> 1 == "1"
true

:) It’s kinda funny.

fetch

fetch(index) → obj
fetch(index, default) → obj
fetch(index) { |index| block } → obj

I’ve used this method with hashes..ALOT. But looks like it works as advertised. The only reason I can think of needing to use a block to get the default is if maybe I needed to retrieve it from a file or webservice.

1
2
3
4
5
6
7
8
9
irb(main):001:0> colors = %w(red white blue)
=> ["red", "white", "blue"]

irb(main):002:0> colors.fetch(0)
=> "red"

irb(main):003:0> colors.fetch(4, :IDUNNO)
=> :IDUNNO
irb(main):004:0>

Interesting though, if you use a negative number it counts from the end.

1
2
3
4
5
irb(main):004:0> colors.fetch(-1)
=> "blue"

irb(main):005:0> colors.fetch(-2)
=> "white"

Another way I have set a default with getting values is to use the || (pipe pipe) operator, let me try it here:

1
2
3
4
5
6
7
8
irb(main):006:0> colors.fetch(4) || :IDUNNO
IndexError: index 4 outside of array bounds: -3...3
from (irb):6:in `fetch'
from (irb):6
from /Users/nolastowe/.rbenv/versions/2.2.0-preview1/bin/irb:11:in `<main>'

irb(main):007:0> colors[4] || :IDUNNO
=> :IDUNNO

Yikes, so if you want to use fetch and set a default you better pass it as the second parameter :) Alternatively, you could check to see if a value exists and return or default with ||. Probably that is what I would use for an array, but now that I think of it, fetch does make it read better and the default is handy. I should change my thinking on this!

fill

fill(obj) → ary
fill(obj, start [, length]) → ary
fill(obj, range ) → ary
fill { |index| block } → ary
fill(start [, length] ) { |index| block } → ary
fill(range) { |index| block } → ary

This method will set the values in an array to a value. It can take a value to set all to or it can take both a value and index(start end) or range. It can set to a value or via a block. Here’s my experimentation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
irb(main):009:0> weekly_prices = Array.new(7, 49.99)
=> [49.99, 49.99, 49.99, 49.99, 49.99, 49.99, 49.99]

irb(main):012:0> weekly_prices.fill(29.99, 1..6)
=> [49.99, 29.99, 29.99, 29.99, 29.99, 29.99, 29.99]

irb(main):013:0> weekly_prices = Array.new(7, 49.99)
=> [49.99, 49.99, 49.99, 49.99, 49.99, 49.99, 49.99]

irb(main):014:0> weekly_prices.fill(29.99, 1..5)
=> [49.99, 29.99, 29.99, 29.99, 29.99, 29.99, 49.99]

irb(main):015:0> weekly_prices.fill(29.99, 1, 5)
=> [49.99, 29.99, 29.99, 29.99, 29.99, 29.99, 49.99]

irb(main):016:0> weekly_prices.fill(1..5) { 9.99 }
=> [49.99, 9.99, 9.99, 9.99, 9.99, 9.99, 49.99]

irb(main):017:0> weekly_prices.fill(4.99)
=> [4.99, 4.99, 4.99, 4.99, 4.99, 4.99, 4.99]

Probably I would not go looking for such a method on arrays, but I think its a good one to keep in mind. Might be handy to reset an array to default values like for score keeping.

find_index

find_index(obj) → int or nil
find_index { |item| block } → int or nil
find_index → Enumerator

Hmm say you had an array of your books arranged in order of most favorite to favorite..

1
2
3
4
5
irb(main):032:0* favorite_books = ["Eloquent Ruby", "Design Patterns in Ruby", "Growing Rails Applications in Practice"]
=> ["Eloquent Ruby", "Design Patterns in Ruby", "Growing Rails Applications in Practice"]

irb(main):033:0> favorite_books.find_index("Design Patterns in Ruby")
=> 1

You could say “Design Patterns in Ruby” was your second favorite with an index of 1 :)

first

first → obj or nil
first(n) → new_ary

This one is easy, returns the first item in the list or nil if the array is empty.

1
2
3
4
irb(main):032:0* favorite_books = ["Eloquent Ruby", "Design Patterns in Ruby", "Growing Rails Applications in Practice"]
=> ["Eloquent Ruby", "Design Patterns in Ruby", "Growing Rails Applications in Practice"]
irb(main):034:0> favorite_books.first
=> "Eloquent Ruby"

And by the way, “Eloquent Ruby by Russ Olsen” is the bestest book ever about ruby and you should run now and get it.

flatten

flatten → new_ary
flatten(level) → new_ary

I’ve used this one before… let’s try it out:

1
2
3
4
5
irb(main):035:0> ruby_books = ["Eloquent Ruby", "Design Patterns in Ruby", "Growing Rails Applications in Practice"]
=> ["Eloquent Ruby", "Design Patterns in Ruby", "Growing Rails Applications in Practice"]

irb(main):036:0> clojure_books = ["Clojure for the Brave and True", "Clojure Cookbook", "Clojure Applied", "Living Clojure"]
=> ["Clojure for the Brave and True", "Clojure Cookbook", "Clojure Applied", "Living Clojure"]

There are my two arrays containing the names of my favorite books

1
2
irb(main):037:0> favorite_books = [ruby_books, clojure_books]
=> [["Eloquent Ruby", "Design Patterns in Ruby", "Growing Rails Applications in Practice"], ["Clojure for the Brave and True", "Clojure Cookbook", "Clojure Applied", "Living Clojure"]]

Combining both lists into one array results in an array containing two arrays..

1
2
3
4
5
irb(main):038:0> favorite_books.flatten
=> ["Eloquent Ruby", "Design Patterns in Ruby", "Growing Rails Applications in Practice", "Clojure for the Brave and True", "Clojure Cookbook", "Clojure Applied", "Living Clojure"]

irb(main):039:0> favorite_books
=> [["Eloquent Ruby", "Design Patterns in Ruby", "Growing Rails Applications in Practice"], ["Clojure for the Brave and True", "Clojure Cookbook", "Clojure Applied", "Living Clojure"]]

You can see that flatten combines the two arrays and squashes into one array but doesn’t change the actual array. The favorite_books array is still a combination.

However… I did not know about the parameter of level

1
2
3
4
5
6
7
8
9
10
11
irb(main):040:0> one = [1, 2, 3, ['a', 'b']]
=> [1, 2, 3, ["a", "b"]]

irb(main):041:0> two = [5, 6, 7, ['c','d']]
=> [5, 6, 7, ["c", "d"]]

irb(main):042:0> both = [one, two]
=> [[1, 2, 3, ["a", "b"]], [5, 6, 7, ["c", "d"]]]

irb(main):043:0> both.flatten(1)
=> [1, 2, 3, ["a", "b"], 5, 6, 7, ["c", "d"]]

Level allows you to indicate how deep to flatten it, that is cool. I did not know that before now!

flatten!

flatten! → ary
flatten!(level) → ary or nil

Now this, as with all ! (bang) methods, it changes the object instead of only returning the results.

Well, I did learn a few things writing this up and I hope you did too! It really is amazing to find out what you did not know :) Hopefully these tidbits will come in handy in future array manipulations :) :)

Next post on arrays will continue with our journey though arrays and start with Frozen.

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!