...

суббота, 2 мая 2015 г.

[Перевод] Несколько полезных ruby-трюков, которые (возможно) улучшат ваш код

Скучая в эту дождливую праздничную погоду, наткнулся на занимательную статейку в блоге с говорящим названием Samurails, в которой описываются некоторые интересные ruby трюки, которые наверняка будут интересны новичкам. Итак, приступим

Создаем хэш из массива


Проще простого. Ставим команду Hash перед любым массивом и получаем готовые пары ключ/значение:
Hash['key1', 'value1', 'key2', 'value2']

# => {"key1"=>"value1", "key2"=>"value2"}



Lambda как ->


Возможность проставлять лямбду при помощи -> появилась сравнительно недавно, будем пробовать:
a = -> { 1 + 1 }
a.call
# => 2

a = -> (v) { v + 1 }
a.call(2)
# => 3


Двойная звездочка (**)


Как вам такой метод:
def my_method(a, *b, **c)
  return a, b, c
end



а — это обычный аргумент. *b примет все аргументы после «a» и выведет их массивом, а вот **c принимет только параметры в формате ключ/значение, после чего отдаст нам хэш. Посмотрим примеры:

Один аргумент:

my_method(1)
# => [1, [], {}]



Набор аргументов:
my_method(1, 2, 3, 4)
# => [1, [2, 3, 4], {}]



Набор аргументов + пары ключ/значение
my_method(1, 2, 3, 4, a: 1, b: 2)
# => [1, [2, 3, 4], {:a=>1, :b=>2}]



По-моему круто.

Обращаемся с переменной и с массивом одинаково


Иногда (лишь иногда) у вас может возникнуть желание запустить на объекте какой-либо метод без проверки его типа. То бишь обращаться с массивом так же как, скажем, с обычной переменной. В таких случаях можно пойти двумя путями — использовать [*something] или Array(something).

Давайте попробуем. Назначим две переменные: число и массив чисел

stuff = 1
stuff_arr = [1, 2, 3]



Используя [*] мы можем одинаково успешно итерировать по обеим переменным:
[*stuff].each { |s| s }
[*stuff_arr].each { |s| s }



Идентично:
Array(stuff).each { |s| s }
Array(stuff_arr).each { |s| s }


||=

Отличный ключ к сокращению количества строк нашего кода — использование ||=

Важно понять, что этот оператор работает так:

a || a = b # Верно

А не так:

a = a || b # Неверно!

Этот оператор прекрасно подходит для выполнения математических операций:

def total
  @total ||= (1..100000000).to_a.inject(:+)
end

Теперь мы можем использовать total в других методах, но посчитается он только один раз, что отразится на производительности нашего приложения.

Обязательные хэш-параметры

Совсем новая фича вторых рубей. Вместо того, чтобы определять метод с указанием хэша в качестве принимаемого аргумента:

def my_method({})
end



теперь мы можем четко определить ключи, которые мы ждем на входе. Более того, мы можем определить их значения!

В данном примере a и b являются обязательными ключами:

def my_method(a:, b:, c: 'default')
  return a, b, c
end



Можем попробовать отправить в метод только «а» и нарваться на ошибку:
my_method(a: 1)
# => ArgumentError: missing keyword: b



Так как мы указали значение по умолчанию для «с», нам достаточно предоставить методу ключи «а» и «b»:
my_method(a: 1, b: 2)
# => [1, 2, "default"]



Или же можем отправить все три:
my_method(a: 1, b: 2, c: 3)
# => [1, 2, 3]



Можем быть более лаконичны:
hash = { a: 1, b: 2, c: 3 }
my_method(hash)
# => [1, 2, 3]



Генерируем алфавит или цепочку чисел при помощи range


Трюк достаточно старый, но вдруг кто-то не в курсе.
('a'..'z').to_a
# => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]

(1..10).to_a
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]



Tap


Tap — это отличный метод, способный улучшить читаемость нашего кода. Допустим, у нас есть класс:
class User
  attr_accessor :a, :b, :c
end



Теперь, допустим, нам захотелось создать нового пользователя, с аттрибутами. Можно сделать это так:
def my_method
  o = User.new
  o.a = 1
  o.b = 2
  o.c = 3
  o
end



А можно использовать tap:
def my_method
  User.new.tap do |o|
    o.a = 1
    o.b = 2
    o.c = 3
  end
end

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.

Комментариев нет:

Отправить комментарий