Se a string estiver vazia, retorne algum valor padrão

93

Freqüentemente, preciso verificar se algum valor está em branco e escrever "Sem dados presentes" assim:

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

E quando temos cerca de 20-30 campos que precisamos processar dessa forma, fica feio.

O que fiz é uma classe String estendida com ormétodo

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

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

Agora está parecendo melhor. Mas ainda é cru e áspero

Como seria melhor resolver meu problema. Talvez seja melhor estender ActiveSupport classou usar o método auxiliar ou mixins ou qualquer outra coisa. O que a idealogia do Ruby, sua experiência e melhores práticas podem me dizer.

fl00r
fonte

Respostas:

227

ActiveSupport adiciona um presencemétodo a todos os objetos que retorna seu receptor se present?(o oposto de blank?) e nilcaso contrário.

Exemplo:

host = config[:host].presence || 'localhost'
David Phillips
fonte
2
isso é legal. Posibilidades de trilhos padrão são preferidas. Obrigado!
fl00r
Em primeiro lugar, é preferido porque na minha solução devo estender String, Fixnum e NilClass pelo menos. E aqui posso usar o código claro sem
bycles
12

Phrogz meio que me deu a ideia no comentário de PofMagicfingers, mas que tal substituir | em vez de?

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

@user.address | "We don't know user's address"
Matt Briggs
fonte
2

Já que você está fazendo isso em Ruby on Rails, parece que você está trabalhando com um modelo. Se você quiser um valor padrão razoável em todo o seu aplicativo, poderá (por exemplo) substituir o addressmétodo para o seu Usermodelo.

Não conheço ActiveRecord bem o suficiente para fornecer um bom código para isso; no Sequel seria algo como:

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

... mas para o exemplo acima, parece que você estaria misturando a lógica de visualização em seu modelo, o que não é uma boa ideia.

Phrogz
fonte
Sim, é uma má ideia definir padrões nos modelos :) Meus formulários vão chorar
fl00r
2

Seu método ou pode ter alguns efeitos colaterais indesejados, uma vez que o valor alternativo (padrão) é sempre avaliado, mesmo se a string não estiver vazia.

Por exemplo

@user.address.or User.make_a_long_and_painful_SQL_query_here

daria trabalho extra mesmo se o endereço não estivesse vazio. Talvez você possa atualizar isso um pouco (desculpe por ter confundido uma linha, tentando ser breve):

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
fonte
boa observação. Entendi. Mas por que todo código será executado? veja:a=2 ; a == 2 ? "ok" : @b = 3 ; @b; #=> nil
fl00r
2
Será executado ao fazer a chamada original, não com a operadora ternária. Todos os argumentos serão avaliados na chamada do método.
Tonttu
2

Provavelmente, é melhor estender ActiveRecord ou modelos individuais em vez de String.

Em sua opinião, você pode preferir um padrão mais explícito, como

@user.attr_or_default :address, "We don't know the user's address"
maxl0rd
fonte
Isso faz parte do Active Record? Não encontrou nenhuma referência.
cabe56 de
0

Rubi:

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

RoR:

unless my_str.blank? then my_str else 'default' end
Lucio
fonte