Если строка пуста, вернуть какое-то значение по умолчанию

94

Часто мне нужно проверить, не является ли какое-то значение пустым, и написать вот так: «Нет данных»:

@user.address.blank? ? "We don't know user's address" : @user.address

А когда у нас есть порядка 20-30 полей, которые нужно обрабатывать таким образом, это становится некрасивым.

Я сделал расширенный класс String с orметодом

class String
  def or(what)
    self.strip.blank? ? what : self
  end
end

@user.address.or("We don't know user's address")

Теперь это выглядит лучше. Но он все еще грубый и грубый

Как лучше было бы решить мою проблему. Может быть, было бы лучше расширить ActiveSupport classили использовать вспомогательный метод, миксины или что-то еще. Что мне могут рассказать рубиновая идеология, ваш опыт и лучшие практики.

fl00r
источник

Ответы:

230

ActiveSupport добавляет presenceметод ко всем объектам, который возвращает получателя if present?(противоположность blank?), иnil противном случае.

Пример:

host = config[:host].presence || 'localhost'
Дэвид Филлипс
источник
2
это здорово. Предпочтительнее использовать направляющие по умолчанию. Спасибо!
fl00r
Во-первых, это предпочтительнее, потому что в моем решении я должен как минимум расширить String, Fixnum и NilClass. И здесь я могу просто использовать чистый код без байтов
fl00r
12

Phrogz как бы дал мне идею в комментарии PofMagicfingers, но как насчет переопределения | вместо?

class String
  def |(what)
    self.strip.blank? ? what : self
  end
end

@user.address | "We don't know user's address"
Мэтт Бриггс
источник
2

Поскольку вы делаете это в Ruby on Rails, похоже, что вы работаете с моделью. Если вы хотите , разумное значение по умолчанию везде в вашем приложении, вы можете (например) переопределить addressметод для Userмодели.

Я недостаточно хорошо знаю ActiveRecord, чтобы предоставить для этого хороший код; в сиквеле это будет примерно так:

class User < Sequel::Model
  def address        
    if (val=self[:address]).empty?
      "We don't know user's address"
    else
      val
    end
  end
end

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

Phrogz
источник
Да, устанавливать значения по умолчанию в моделях - плохая идея :) Мои формы будут плакать
fl00r
2

Ваш или метод может иметь некоторые нежелательные побочные эффекты, поскольку альтернативное значение (по умолчанию) всегда оценивается, даже если строка не пуста.

Например

@user.address.or User.make_a_long_and_painful_SQL_query_here

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

class String
  def or what = ""
    self.strip.empty? ? block_given? ? yield : what : self
  end
end

@user.address.or "We don't know user's address"
@user.address.or { User.make_a_long_and_painful_SQL_query_here }
Tonttu
источник
хорошее замечание. Понял. Но почему весь код будет выполнен? посмотрите:a=2 ; a == 2 ? "ok" : @b = 3 ; @b; #=> nil
fl00r
2
Он будет выполнен при выполнении исходного вызова, а не с помощью тернарного оператора. Все аргументы будут оцениваться при вызове метода.
Tonttu
1

Возможно, лучше расширить ActiveRecord или отдельные модели вместо String.

На ваш взгляд, вы могли бы предпочесть более явный шаблон, например

@user.attr_or_default :address, "We don't know the user's address"
maxl0rd
источник
Это часть Active Record? Ссылки не нашел.
cabe56
0

Рубин:

unless my_str.empty? then my_str else 'default' end

RoR:

unless my_str.blank? then my_str else 'default' end
Лючио
источник