Tuesday, November 13, 2007
Rails: Enumerable#sum
Documentation
The Enumerable#sum method does exactly what you would expect: Sum the elements of the array.
Test
UsageCalculates a sum from the elements. Examples:
payments.sum { |p| p.price * p.tax_rate }
payments.sum(&:price)
This is instead of payments.inject { |sum, p| sum + p.price }
Also calculates sums without the use of a block:
[5, 15, 10].sum # => 30
The default identity (sum of an empty list) is zero. However, you can override this default:
[].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
The Enumerable#sum method does exactly what you would expect: Sum the elements of the array.
Test
unit_tests do
test "sum the numbers from the array" do
grades = [50, 55, 67, 62, 71, 89, 84, 85, 99]
assert_equal 662, grades.sum
end
endLabels: activesupport, rails
Monday, November 12, 2007
Rails: Enumerable#group_by
Documentation
The Enumerable#group_by method is helpful for grouping elements of an Enumerable by an attribute or an arbitrary grouping. The documentation provides a good example of how to group by an attribute; however, the group_by method can be used logically group by anything returned from the block given to group_by.
Test
Collect an enumerable into sets, grouped by the result of a block. Useful, for example, for grouping records by date.Usage
e.g.latest_transcripts.group_by(&:day).each do |day, transcripts|
p "#{day} -> #{transcripts.map(&:class) * ', '}"
end
"2006-03-01 -> Transcript"
"2006-02-28 -> Transcript"
"2006-02-27 -> Transcript, Transcript"
"2006-02-26 -> Transcript, Transcript"
"2006-02-25 -> Transcript"
"2006-02-24 -> Transcript, Transcript"
"2006-02-23 -> Transcript"
The Enumerable#group_by method is helpful for grouping elements of an Enumerable by an attribute or an arbitrary grouping. The documentation provides a good example of how to group by an attribute; however, the group_by method can be used logically group by anything returned from the block given to group_by.
Test
unit_tests do
test "group by grades" do
grades = [50, 55, 60, 62, 71, 83, 84, 85, 99]
expected = {"A"=>[99], "B"=>[83, 84, 85], "C"=>[71], "D"=>[60, 62], "F"=>[50, 55]}
actual = grades.group_by do |grade|
case
when grade < 60 then "F"
when grade < 70 then "D"
when grade < 80 then "C"
when grade < 90 then "B"
else "A"
end
end
assert_equal expected, actual
end
endLabels: activesupport, rails
Sunday, November 11, 2007
Rails: Enumerable#index_by
Documentation
I've used Enumerable#index_by for 2 different reasons recently. In one instance I needed faster access to find an element in an array. We found that pulling something out of a hash was faster than using the find method of array. We did a few benchmarks similar to the contrived examples below.
The benchmarks for our project revealed even larger gains, thus it made sense to convert our array to a hash and work with that instead of the array.
The other usage we found for index_by was to utilize the fact that index_by overwrites the value instead of appending (which group_by does). We had a list of scores and wanted to group them together. The group_by method could handle that case; however, we only wanted to keep track of the highest score per group. The test below shows an example where a list of grades can be grouped by grade letter and the highest score per grade letter.
Test
UsageConvert an enumerable to a hash. Examples:
people.index_by(&:login)
=> { "nextangle" =>, "chade-" => , ...}
people.index_by { |person| "#{person.first_name} #{person.last_name}" }
=> { "Chade- Fowlersburg-e" =>, "David Heinemeier Hansson" => , ...}
I've used Enumerable#index_by for 2 different reasons recently. In one instance I needed faster access to find an element in an array. We found that pulling something out of a hash was faster than using the find method of array. We did a few benchmarks similar to the contrived examples below.
array = [1..100].to_anote: we couldn't use the
hash = array.index_by { |element| element }
array_bm = Benchmark.measure do
array.find { |element| element = 99 }
end
hash_bm = Benchmark.measure do
hash.include? 99
end
p array_bm.real # => 1.382
p hash_bm.real # => 1.001
include? method for our particular instance, so I left it out of the contrived example.The benchmarks for our project revealed even larger gains, thus it made sense to convert our array to a hash and work with that instead of the array.
The other usage we found for index_by was to utilize the fact that index_by overwrites the value instead of appending (which group_by does). We had a list of scores and wanted to group them together. The group_by method could handle that case; however, we only wanted to keep track of the highest score per group. The test below shows an example where a list of grades can be grouped by grade letter and the highest score per grade letter.
Test
unit_tests do
test "index by highest numeric per grade level" do
grades = [50, 55, 67, 62, 71, 89, 84, 85, 99]
expected = {"A"=>99, "B"=>89, "C"=>71, "D"=>67, "F"=>55}
actual = grades.sort.index_by do |grade|
case
when grade < 60 then "F"
when grade < 70 then "D"
when grade < 80 then "C"
when grade < 90 then "B"
else "A"
end
end
assert_equal expected, actual
end
endLabels: activesupport, rails
Saturday, November 10, 2007
Rails: Integer#even?
Documentation
None
Usage
The Integer#even? method is helpful when adding zebra striping to views.
For example:
Test
None
Usage
The Integer#even? method is helpful when adding zebra striping to views.
For example:
<% @customers.each_with_index do |customer, index| %>
<div style="color:<%= index.even? ? "white" : "gray" %>">
<%= customer.name %>
</div>
<% end %>
Test
unit_tests do
test "10 is even?" do
assert_equal true, 10.even?
end
endLabels: activesupport, rails
Friday, November 09, 2007
Rails: String#each_char
Documentation
The String#each_char method is nice for iterating through a string, one character at a time. I generally use regex for string manipulation; however, when context within the string matters, each_char is helpful.
Test
Yields a single-character string for each character in the string. When $KCODE = ‘UTF8’, multi-byte characters are yielded appropriately.Usage
The String#each_char method is nice for iterating through a string, one character at a time. I generally use regex for string manipulation; however, when context within the string matters, each_char is helpful.
Test
unit_tests do
test "each_char can be used to strip every other charater" do
strip, result = true, ""
"hello world".each_char do |char|
result << char if strip
strip = !strip
end
assert_equal "hlowrd", result
end
endLabels: activesupport, rails
Thursday, November 08, 2007
Rails: Hash#diff
Documentation
None
Usage
The Hash#diff method is helpful for determining the difference between two hashes.
note: The receiver matches on both keys and values. If the pair is not matched it be returned. (for example: {:a => 1, :b => 3}.diff({:a=>2}) # => {:a=>1, :b=>3})
Test
None
Usage
The Hash#diff method is helpful for determining the difference between two hashes.
note: The receiver matches on both keys and values. If the pair is not matched it be returned. (for example: {:a => 1, :b => 3}.diff({:a=>2}) # => {:a=>1, :b=>3})
Test
unit_tests do
test "find the difference between two hashes" do
assert_equal({:b=>3}, {:a => 1, :b => 3}.diff({:a=>1}))
end
endLabels: activesupport, rails
Wednesday, November 07, 2007
Rails: String#constantize
Documentation
Constantize is definitely the most used String method that I utilize while metaprogramming.
Test
Constantize tries to find a declared constant with the name specified in the string. It raises a NameError when the name is not in CamelCase or is not initialized.Usage
Examples
- "Module".constantize #=> Module
- "Class".constantize #=> Class
Constantize is definitely the most used String method that I utilize while metaprogramming.
Test
unit_tests do
end
test "constantize a string representation of a class" do
assert_equal Klass, "Klass".constantize
end
endLabels: activesupport, rails
Tuesday, November 06, 2007
Rails: String#classify
Documentation
The classify method is helpful when metaprogramming. I generally replace "strings".singularize.camelize with "strings".classify (and the classify implementation calls singularize and camelize for me).
Test
Create a class name from a table name like Rails does for table names to models. Note that this returns a string and not a Class. (To convert to an actual class follow classify with constantize.)Usage
Examples
- "egg_and_hams".classify #=> "EggAndHam"
- "post".classify #=> "Post"
The classify method is helpful when metaprogramming. I generally replace "strings".singularize.camelize with "strings".classify (and the classify implementation calls singularize and camelize for me).
Test
unit_tests do
test "singularize and camelize a string via classify" do
assert_equal "Name", "names".classify
end
endLabels: activesupport, rails
Monday, November 05, 2007
Rails: String#singularize
Documentation
I generally use singularize when metaprogrammming to convert from a potentially plural version of a class name to something that I know can be constantized.
Test
The reverse of pluralize, returns the singular form of a word in a string.Usage
Examples
- "posts".singularize #=> "post"
- "octopi".singularize #=> "octopus"
- "sheep".singluarize #=> "sheep"
- "word".singluarize #=> "word"
- "the blue mailmen".singularize #=> "the blue mailman"
- "CamelOctopi".singularize #=> "CamelOctopus"
I generally use singularize when metaprogrammming to convert from a potentially plural version of a class name to something that I know can be constantized.
Test
unit_tests do
test "change plural word to singular word" do
assert_equal "class_name", "class_names".singularize
end
endLabels: activesupport, rails
Sunday, November 04, 2007
Rails: String#pluralize
Documentation
I generally use pluralize for creating nice messages for users. The pluralize method can also be helpful for metaprogramming when converting from a class name to a table name.
Test
Returns the plural form of the word in the string.Usage
Examples
- "post".pluralize #=> "posts"
- "octopus".pluralize #=> "octopi"
- "sheep".pluralize #=> "sheep"
- "words".pluralize #=> "words"
- "the blue mailman".pluralize #=> "the blue mailmen"
- "CamelOctopus".pluralize #=> "CamelOctopi"
I generally use pluralize for creating nice messages for users. The pluralize method can also be helpful for metaprogramming when converting from a class name to a table name.
Test
unit_tests do
test "change singular word to plural word" do
assert_equal "names", "name".pluralize
end
endLabels: activesupport, rails
Saturday, November 03, 2007
Rails: String#camelize
Documentation
I generally use camelize when metaprogrammming to convert from a underscored version of a class name.
Test
By default, camelize converts strings to UpperCamelCase. If the argument to camelize is set to ":lower" then camelize produces lowerCamelCase.Usage
camelize will also convert ’/’ to ’::’ which is useful for converting paths to namespaces
Examples
- "active_record".camelize #=> "ActiveRecord"
- "active_record".camelize(:lower) #=> "activeRecord"
- "active_record/errors".camelize #=> "ActiveRecord::Errors"
- "active_record/errors".camelize(:lower) #=> "activeRecord::Errors"
I generally use camelize when metaprogrammming to convert from a underscored version of a class name.
Test
unit_tests do
test "change underscored word to camelized word" do
assert_equal "AClassName", "a_class_name".camelize
end
endLabels: activesupport, rails
Friday, November 02, 2007
Rails: Hash#assert_valid_keys
Documentation
None
Usage
Hash#assert_valid_keys gives you the ability to verify that each of the keys in the Hash are expected. For example, if you take an options Hash as an argument to a method you may want to validate that only expected options are passed as part of the hash; assert_valid_keys gives you the ability to list the keys you expect.
Test
None
Usage
Hash#assert_valid_keys gives you the ability to verify that each of the keys in the Hash are expected. For example, if you take an options Hash as an argument to a method you may want to validate that only expected options are passed as part of the hash; assert_valid_keys gives you the ability to list the keys you expect.
Test
unit_tests do
test