Сокращение Ruby для "используйте это, если оно не пустое, иначе используйте это"

У меня есть следующий код:

url = file.s3_url.blank? ? file.url : file.s3_url

Есть ли более короткий способ написать это?

Спасибо!

Ответы

Ответ 1

Ну, вы можете написать метод на любом file экземпляре (скажем S3File):

class S3File 
   def real_url
     self.s3_url.blank? ? self.url : self.s3_url
   end
   #...
end

Тогда он становится реальным простым:

url = file.real_url 

Как сказал @tokland, вы можете использовать патч Object для использования метода or_if, который будет реализован следующим образом:

class Object
   def or_if(method, val = nil)
      self.send(method) ? (block_given? ? yield : val) : self
   end         
end

Таким образом, вы сможете сделать это:

url = file.s3_url.or_if(:blank?) { file.url }

Или это:

url = file.s3_url.or_if(:blank?, file.url)

Ответ 3

Возможно, вы можете сделать следующее:

url = file.s3_url || file.url

Этот код будет использовать file.url, только если file.s3_url равен нулю. Это означает, что пустая строка не будет работать. Если вы хотите убедиться, что пустая строка не используется, как и в вашем примере, тогда нет более короткого способа сделать это.

Ответ 4

Я использую утилитный метод.

def until_not_blank(*args)
  args.find {|a| !a.blank? }
end

url = until_not_blank(file.s3_url, file.url)

Обычно я просто добавляю это в свой ApplicationController и делаю его помощником. Если вы хотите, чтобы он был доступен по всему миру, вы могли бы поместить его в ядро, или вы могли бы патч-арки

class Array
  def first_not_blank
    find {|a| !a.blank?}
  end
end

url = [file.s3_url, file.url].first_not_blank

Ответ 5

url = (file.s3_url.blank? && file.s3_url) || file.url
Выглядит круто, но на самом деле я нахожу это запутанным и предпочитаю старый добрый троичный, если.