Sonntag, 26. April 2015

Compare Ruby objects with Threequals!

Apart from simple comparision with == or eql? there is a another one: Object#=== aka Threequal.
Its intention is to provide "Case Equality". The Documention furthermore states:

For class Object, effectively the same as calling #==, but typically overridden by descendants to provide meaningful semantics in case statements.

It is meant to to be overwritten!
In some classes it is already achieved. For example Range#===:
(1..5) === 3
=> true
So there is a comparision going on between two kind of objects, a Range and a Fixnum. Briefly the Threequal "operator" technically is nothing more than a method expecting a parameter, similar to == or +.
But this one is special. The Threequal also is called when a case statement tries to compare. The Range class once again:
case 24
when 0..18
  'Underweight'
when 18..25
  'Normal weight'
else
  'Adiposity (overweight)'
end
=> 'Normal weight'
...Phew.
Please note, the Threequal has to be overwritten in the when-branches-object class, not in the one the case statement tries to compare.
So whenever semantic comparision is required overwriting Object#=== totally makes sense. Semantic comparision is emphasized. A Ruby On Rails example:
But setting up the models first:
rails g model Category name:string
rails g model Language name:string category_id:integer
class Category  < ActiveRecord::Base
  def self.[] name
    where(name: name).first
  end
 
  def === language
    language.category == self
  end
end

class Language < ActiveRecord::Base
  belongs_to :category
end
A language can belong to a category. The catogory Threequal method compares the assigned language category with itself. The class method Category#[] finds the corresponding object.
Creating a dynamic language:
ruby = Language.create name: 'Ruby', 
  category: Category.dynamic
and comparing it somewhere else:
case ruby
  when Category[:dynamic] then 'Awesome!'
  when Category[:static] then 'Huh.'
  else 'Anyway.'
end
=> "Awesome!"
returns the right answer.

Supported by Ruby 2.2.1 and Ruby on Rails 4.2.0

Sonntag, 19. April 2015

Follow the Ruby styleguide entirely! pt. 2

Programming styleguides are less a matter of taste. They are way more a matter of optimizing code readability. And following styleguides reveals own perception that others will read the code.
Code is communication. So programming styleguides are important!

1. Ternary Operator

Favor the ternary operator(?:) over if/then/else/end constructs for one liners. It is more common and obviously more concise.
# bad
result = if language.dynamic? then 'Awesome!' else 'Huh.' end

# good
result = language.dynamic? ? 'Awesome!' : 'Huh.'

2. Preprocess variables

Use &&= to preprocess variables that may or may not exist. Using &&= will change the value only if it exists, removing the need to check its existence with if.
# bad
if name
  name = name.downcase
end

# bad (even worse)
name = name ? name.downcase : nil

# ok
name = name.downcase if name

# good
name = name && name.downcase

# better
name &&= name.downcase

3. Indent case whens

Indent when as deep as case. It is the style established in the "Programming Ruby" (aka the Pickaxe book).
# bad
case language
  when 'Ruby'
    puts 'Awesome!'
  when 'Java'
    puts 'Huh.'
  else
    puts 'Let me see.'
end

# good
case language
when 'Ruby'
  puts 'Awesome!'
when 'Java'
  puts 'Huh.'
else
  puts 'Let me see.'
end

4. Constant references

Use :: only to reference constants (this includes classes and modules) and constructors (like Array() or Nokogiri::HTML()). Do not use :: for regular method invocation.
# bad
ActiveRecord::Base::reflections
Hash::new::keys

# good
ActiveRecord::Base.reflections
Hash.new.keys
ActiveRecord::Reflection::AssociationReflection::VALID_AUTOMATIC_INVERSE_MACROS
Nokogiri::HTML()

5. Procs

Prefer proc over Proc.new.
# bad
Proc.new { |n| puts n }

# good
proc { |n| puts n }

6. Array check

Use [*var] or Array() instead of explicit Array check, when dealing with a variable you want to treat as an Array, but you are not certain it is an array. [link]
# bad
paths = [paths] unless paths.is_a? Array
paths.each { |path| do_something(path) }

# good
[*paths].each { |path| do_something(path) }

# good (and a bit more readable)
Array(paths).each { |path| do_something(path) }

7. Parameter whitespaces

Use spaces around the = operator when assigning default values to method parameters: [link]
# bad
def do_something(arg1=:default, arg2=nil, arg3=[])
  # do something...
end

# good
def do_something(arg1 = :default, arg2 = nil, arg3 = [])
  # do something...
end
While several Ruby books suggest the first style, the second is much more prominent in practice (and arguably a bit more readable).

8. Multi line method chaning

Adopt a consistent multi-line method chaining style. Use trailing chaining.
When continuing a chained method invocation on another line, include the . on the first line to indicate that the expression continues:
# bad - need to read ahead to the second line to know that 
# the chain continues
one.two.three
  .four

# good - it's immediately clear that the expression continues 
# beyond the first line
one.two.three.
  four

9. Multi line Array literals

Align the elements of array literals spanning multiple lines.
# bad - single indent
languages = ['Ruby', 'Python', 'Java', 'C#', 'Scala',
  'CSS3', 'HTML5', 'XML', 'Javascript']

# good
languages = [
  'Ruby', 'Java', 'C#', 'Scala',
  'CSS3', 'HTML5', 'XML', 'Javascript'
]

# good
languages = 
  ['Ruby', 'Python', 'Java', 'C#', 'Scala',
   'CSS3', 'HTML5', 'XML', 'Javascript']

10. Use && and ||

The and and or keywords are banned. It is just not worth it. Always use && and || instead.
# bad
# boolean expression
if language.dynamic? and language.awesome?
  puts "It must be Ruby"
end

# control flow
language.dynamic? or language.awesome?

# good
# boolean expression
if language.dynamic? && language.awesome?
  puts "It must be Ruby"
end

# control flow
language.dynamic? || language.awesome?

Further articles of interest:

Supported by Ruby 2.2.1 and Ruby on Rails 4.2.0

Sonntag, 12. April 2015

Follow the Ruby styleguide! pt. 1

It is important to follow the Ruby styleguide. Some styles are controversial, but the most really make sense. Following them makes coding Ruby in a team a lot easier.

1. Indentation

Use two spaces per indentation level (aka soft tabs). No hard tabs:
# bad - four spaces
def some_method
    do_something
end

# good
def some_method
  do_something
end
it is one line in the VIM configuration file .vimrc:
set shiftwidth=2
and you are done.

2. Spaces

Use spaces around operators, after commas, colons and semicolons, around { and before }. Whitespace might be (mostly) irrelevant to the Ruby interpreter, but its proper use is the key to writing easily readable code:
# bad - missing whitespaces
sum=1+2
hash = {one:1,two:2,three:3}
a,b = 1,2
[1,2,3].each {|number| puts number}
class FooError<StandardError;end

# good
sum = 1 + 2
hash = { one: 1, two: 2, three: 3 }
a, b = 1, 2
[1, 2, 3].each { |e| puts e }
class FooError < StandardError; end
There are some exceptions:
# the exponent operator:
result = 2 ** 2 # instead of 2**2

# embedded expressions:
"string#{expr}" # instead of "string#{ expr }"

# array brackets:
[1, 2, 3] # instead of [ 1, 2, 3 ]

# method call:
do_something(:special) # instead of do_something( :special )

# negation:
!number? # instead of ! number?

# ranges:
1..5 # instead of 1 .. 5

3. Limited line length

Limit lines to 80 characters.

4. Parameter alignment

Align the parameters of a method call if they span more than one line. When aligning parameters is not appropriate due to line-length constraints, single indent for the lines after the first is also acceptable:
# starting point (line is too long)
def send_mail(source)
  Mailer.deliver(to: 'bob@example.com', from: 'us@example.com', subject: 'Important message', body: source.text)
end

# bad (double indent)
def send_mail(source)
  Mailer.deliver(
      to: 'bob@example.com',
      from: 'us@example.com',
      subject: 'Important message',
      body: source.text)
end

# good (normal indent)
def send_mail(source)
  Mailer.deliver(
    to: 'bob@example.com',
    from: 'us@example.com',
    subject: 'Important message',
    body: source.text
  )
end

5. Large numeric literals

Add underscores to large numeric literals to improve their readability:
# bad - how many 0s are there?
num = 1000000

# good - much easier to parse for the human brain
num = 1_000_000

6. Method arguments definition

Use def with parentheses when there are arguments. Omit the parentheses when the method doesn't accept any arguments:
# bad
def do_somthing()
 # do something
end

# good
def do_somthing
 # do something
end

# bad
def do_somthing_with_arguments arg1, arg2
 # do something
end

# good
def do_somthing_with_arguments(arg1, arg2)
 # do something
end

7. Expression result

Leverage the fact that if and case are expressions which return a result:
# bad
if condition
  result = x
else
  result = y
end

# good
result =
  if condition
    x
  else
    y
  end

8. Assignment operators

Use shorthand self assignment operators whenever applicable
# bad
x = x + y
x = x**y
x = x / y
x = x && y

# good
x += y
x **= y
x /= y
x &&= y

9. Variable initialization

Use ||= to initialize variables only if they are not already initialized:
# bad
language = language ? language : 'Ruby'
language = 'Ruby' unless language

# good - set language to Ruby, only if it's nil or false
language ||= 'Ruby'
But beware using ||= for initializing boolean variables. Consider what would happen if the current value happened to be false. Take a look:
# bad - would set enabled to true even if it was false
enabled ||= true

# good
enabled = true if enabled.nil?

10. Hashes

Use the Ruby 1.9 hash literal syntax when your hash keys are symbols:
# bad
hash = { :one => 1, :two => 2, :three => 3 }

# good
hash = { one: 1, two: 2, three: 3 }

Further articles of interest:

Supported by Ruby 2.1.1

Sonntag, 5. April 2015

Find the Rails easter egg!

Great software comes with an easter egg.
Beginning with the mozilla firefox, typing about:robots:
about:robots
into the address bar sends warm greetings.
The bash people on the other hand like to moo their cows around:
apt-get moo
and way more fun:
cowsay -p -f head-in Aaargh
The greatest editor (VIM) on earth helps to find the meaning of life by typing:
:help 42
Google is well known for easter eggs like their Google search (try to search anything).
Google Streetview also hides funny easter eggs. For example in the boondocks of the southpole you can see some nice pingings. And pingings are awesome.
But what about Ruby on Rails? It is great for sure, but where is their easter egg?
You can find it by typing:
(1..43).to_a.forty_two
into the rails console.
It is in Array and also in ActiveRecord::FinderMethods

Supported by Ruby 2.1.1 and Ruby on Rails 4.1.8