Загрузка...

Ruby & Rails: веб-разработка с удовольствием

Ruby on Rails — фреймворк для создания веб-приложений. Является открытым программным обеспечением (лицензия MIT). Здесь мы обсуждаем новости RoR, делимся учебными материалами и интересными находками С RoR даже сложные веб-приложения могут быть написаны за считанные дни. Это действительно разработка с удовольствием!
     

как сделать что-то массивом

28.07.10, 16:31
Автор ggg

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

  1. если значение единственное - то обрабатывается только оно
  2. если передан массив значений - то обработка должна вестись для каждого элемента массива
Раньше в силу своей неграмотности я делал так:
def foo(arg)
  if arg.is_a?(Array)
    arg.each do |i|
      # do something
    end
  else
    foo([arg])
  end
end
Сегодня я узнал, что есть более простая конструкция, которая помогает в решении поставленной задачи: Array(smth) делает из переданного аргумента массив, если он таковым не является. В противном случае аргумент возвращается как есть:
Array(1)
# получаем массив [1]
Array([1, 2, 3])
# получаем массив [1, 2, 3]
Если переписать представленную выше функцию с использованием данной конструкции то мы получим следующее:
def foo(arg)
  Array(arg).each do |i|
    # do something
  end
end
Эта приятная мелочь поможет сделать ваш код более понятным и лаконичным.

Комментарии

Есть 2 неприятных случая:
– аргументы foo – массивы, т.е. ей на вход передается либо массив, либо массив массивов.
– тип аргументов foo неизвестен (неважен) для foo – в этом случае также нельзя полагаться на то, что они НЕ массивы.

Т.е. надежно различить в этих случаях, один ли аргумент или несколько “имелись в виду”, невозможно.

Мораль: надо писать на языках со статической типизацией ;)

На самом деле, Мораль: do one thing and do it well; не надо писать функции, которые помимо своего основного предназначения еще и гадают, что имел в виду вызывающий их код. Это нихрена, блин, не делает код понятным и лаконичным.

в некоторых случаях да, это неприемлимо, а в некоторых вполне себе понятно и лаконично =)

Очень наглядно получается. Я обычно делал так


a #- массив или не массив
b = [a].flatten # - уже точно массив

Ещё есть такая хитрость:

foo = ‘Smth’
bar = [‘Hi’, ‘How’, ‘Are’, ‘You’]
[*foo] #=> [‘Smth’]
[*bar] #=> [‘Hi’, ‘How’, ‘Are’, ‘You’]

У ментожа есть недостаток — здесь, очевидно, происходит разворачивание массива и если он большой, то это может сказаться на произхводительности.

Недавно столкнулись с тем, что такая конструкция падает если передать прокси ассоциации модели :( Array(Model.has_many_association) Так шо будте осторожны!

Войдите, чтобы оставить комментарий