Ever saw some code like this? def order ORDER_WHITELIST.include?(params[:order]) ? params[:order] : 'title_asc' end How about using .presence_in: def order params[:order].presence_in(ORDER_WHITELIST) || 'title_asc' end 2 / 27
allow passing an array around or a single value. However, you always want to make sure you're dealing with an array. You can use the splat operator. foo = 1 bar = [2, 3] foo_array = [*foo] # => [1] bar_array = [*bar] # => [2, 3] Hint: Array(foo) and Array(bar) also works! 5 / 27
flatten should ring a bell. Make sure to check if you could use flat_map to save some CPU cycles. # not so good [1, 2, 3].map { |x| [x, x+1] }.flatten # better [1, 2, 3].flat_map { |x| [x, x+1] } 7 / 27
clever. For example, trying to find the element of a collection that has the max length. # not so good longest = %w(cat sheep bear).inject do |memo, word| memo.length > word.length ? memo : word end # => "sheep" # better longest = %w(cat sheep bear).max_by(&:length) # => "sheep" 8 / 27
lot of the methods of Enumerable, make sure the standard library does not provide shortcut already. # not so good [1, 2, 3].select { |x| x > 2 }.count # better [1, 2, 3].count { |x| x > 2 } 9 / 27
ugly [1, 2, 3][rand(3)] # still bad [1, 2, 3].shuffle.first # better [1, 2, 3].sample .sample also provides a performance benefit over the other variants! 10 / 27
to traverse a collection in reverse, there is no need to reverse it first and then iterate over it. Just use reverse_each directly. # bad [1, 2, 3].reverse.each { |x| puts x } # good [1, 2, 3].reverse_each { |x| puts x } 14 / 27
of a number in reverse order, so you could do: awesome_number = 12345 p awesome_number.to_s.chars.map(&:to_i).reverse # Result: [5, 4, 3, 2, 1] But, there is .digits: p awesome_number.digits # => [5, 4, 3, 2, 1] 17 / 27
and matching a regular expression inside the block, just use grep. # not so good %w(xml yaml json txt html).select { |w| w =~ /ml$/ } # => ["xml", "yaml", "html"] # better %w(xml yaml json txt html).grep(/ml$/) # => ["xml", "yaml", "html"] There is also .grep_v, which greps all the elements NOT in pattern: (1..10).grep_v 2..5 #=> [1, 6, 7, 8, 9, 10] 18 / 27
you only need to find the first element. # not so good (1..10).select { |num| num % 3 == 0 }.first # => 3 # better (1..10).find { |num| num % 3 == 0 } # => 3 19 / 27
This line is not indented. This one, however, is indented with 2 spaces. EOS # => This line is not indented. # => This one, however, is indented with 2 spaces. # better code identation, preserving the desired indentation of the string puts <<~EOS This line is not indented. This one, however, is indented with 2 spaces. EOS # => This line is not indented. # => This one, however, is indented with 2 spaces. 20 / 27
try unless @number.nil? @number.next end # with try @number.try(:next) Ruby 2.3 introduced the safe navigation operator &., which is quite similar, but NOT the same. >> false.try(:foobar) => nil # vs. >> false&.foobar => NoMethodError: undefined method `foobar' for false:FalseClass 22 / 27
check if there is more than one element <% if user.comment.size > 1 %> ... <% end %> # convenience through ActiveSupport <% if user.comments.many? %> ... <% end %> Can be called with a block too, so to return if more than one person is over 26: people.many? { |p| p.age > 26 } 24 / 27