Eu tenho um aplicativo Rails e estou usando jQuery para consultar minha visualização de pesquisa em segundo plano. Existem campos q
(termo de pesquisa) start_date
, end_date
e internal
. O internal
campo é uma caixa de seleção e estou usando o is(:checked)
método para construir o url que é consultado:
$.getScript(document.URL + "?q=" + $("#search_q").val() + "&start_date=" + $("#search_start_date").val() + "&end_date=" + $("#search_end_date").val() + "&internal=" + $("#search_internal").is(':checked'));
Agora meu problema é params[:internal]
porque há uma string contendo "true" ou "false" e eu preciso convertê-la em booleano. Claro que posso fazer assim:
def to_boolean(str)
return true if str=="true"
return false if str=="false"
return nil
end
Mas eu acho que deve haver uma maneira mais Ruby de lidar com esse problema! Não há ...?
ActiveRecord fornece uma maneira limpa de fazer isso.
def is_true?(string) ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(string) end
ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES
tem todas as representações óbvias de valores True como strings.fonte
ActiveRecord::ConnectionAdapters::Column.value_to_boolean(string)
(fonte) apidock.com/rails/v3.0.9/ActiveRecord/ConnectionAdapters/Column/…ActiveRecord::Type::Boolean.new.type_cast_from_user("true")
=> trueActiveRecord::Type::Boolean.new.type_cast_from_user("T")
=> trueActiveModel::Type::Boolean
parece um caminho muito mais adequado - emboraActiveRecord::ConnectionAdapters::Column::TRUE_VALUES
contenha valores "verdadeiros", pode-se argumentar que esse é o caso apenas incidentalmente e que valores que devem ser considerados verdadeiros para aquele caso de uso específico, mas não outros, podem ser incluídos. Por outro lado,ActiveModel::Type::Boolean
aparentemente foi projetado para ser usado de forma genérica.Aviso de Segurança
Observe que esta resposta em sua forma simples é apropriada apenas para o outro caso de uso listado abaixo, e não para aquele na pergunta. Embora a maioria tenha sido corrigida, houve inúmeras vulnerabilidades de segurança relacionadas ao YAML, causadas pelo carregamento da entrada do usuário como YAML.
Um truque que uso para converter strings em bools é
YAML.load
, por exemplo:YAML.load(var) # -> true/false if it's one of the below
O bool YAML aceita muitas strings verdadeiras / falsas:
y|Y|yes|Yes|YES|n|N|no|No|NO |true|True|TRUE|false|False|FALSE |on|On|ON|off|Off|OFF
Outro caso de uso
Suponha que você tenha um código de configuração como este:
config.etc.something = ENV['ETC_SOMETHING']
E na linha de comando:
$ export ETC_SOMETHING=false
Agora, como
ENV
vars são strings uma vez dentro do código,config.etc.something
o valor de seria a string"false"
e seria avaliado incorretamente comotrue
. Mas se você gosta disso:config.etc.something = YAML.load(ENV['ETC_SOMETHING'])
tudo ficaria bem. Isso é compatível com o carregamento de configurações de arquivos .yml também.
fonte
Não há nenhuma maneira embutida de lidar com isso (embora o actionpack possa ter um auxiliar para isso). Eu aconselharia algo assim
def to_boolean(s) s and !!s.match(/^(true|t|yes|y|1)$/i) end # or (as Pavling pointed out) def to_boolean(s) !!(s =~ /^(true|t|yes|y|1)$/i) end
O que funciona bem é usar 0 e não-0 em vez de literais falsos / verdadeiros:
def to_boolean(s) !s.to_i.zero? end
fonte
.match
é um pouco mais fácil de ler.ActiveRecord::Type::Boolean.new.type_cast_from_user
faz isso de acordo com os mapeamentos internos do RailsConnectionAdapters::Column::TRUE_VALUES
eConnectionAdapters::Column::FALSE_VALUES
:[3] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("true") => true [4] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("false") => false [5] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("T") => true [6] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("F") => false [7] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("yes") DEPRECATION WARNING: You attempted to assign a value which is not explicitly `true` or `false` ("yes") to a boolean column. Currently this value casts to `false`. This will change to match Ruby's semantics, and will cast to `true` in Rails 5. If you would like to maintain the current behavior, you should explicitly handle the values you would like cast to `false`. (called from <main> at (pry):7) => false [8] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("no") DEPRECATION WARNING: You attempted to assign a value which is not explicitly `true` or `false` ("no") to a boolean column. Currently this value casts to `false`. This will change to match Ruby's semantics, and will cast to `true` in Rails 5. If you would like to maintain the current behavior, you should explicitly handle the values you would like cast to `false`. (called from <main> at (pry):8) => false
Portanto, você pode fazer seu próprio método
to_b
(outo_bool
outo_boolean
) em um inicializador como este:class String def to_b ActiveRecord::Type::Boolean.new.type_cast_from_user(self) end end
fonte
Você pode usar wannabe_bool gem. https://github.com/prodis/wannabe_bool
Esta gema implementa um
#to_b
método para as classes String, Integer, Symbol e NilClass.params[:internal].to_b
fonte
No Rails 5 você pode usar
ActiveRecord::Type::Boolean.new.cast(value)
para convertê-lo em um booleano.fonte
Não acho que algo assim esteja embutido no Ruby. Você pode reabrir a classe String e adicionar o método to_bool lá:
class String def to_bool return true if self=="true" return false if self=="false" return nil end end
Então você pode usá-lo em qualquer lugar em seu projeto, como este:
params[:internal].to_bool
fonte
to_bool
retorno de funçãonil
; isso parece errado. Outras funções de conversão não fazem isso:"a".to_i
retorna0
, nãonil
Talvez
str.to_s.downcase == 'true'
para ser completo. Então, nada pode travar, mesmo sestr
for nulo ou 0.fonte
Olhando para o código-fonte do Virtus , talvez eu faça algo assim:
def to_boolean(s) map = Hash[%w[true yes 1].product([true]) + %w[false no 0].product([false])] map[s.to_s.downcase] end
fonte
Você pode considerar apenas anexar
internal
ao seu url se for verdadeiro; então, se a caixa de seleção não estiver marcada e você não anexar,params[:internal]
serianil
, o que resulta em falso em Ruby.Não estou familiarizado com o jQuery específico que você está usando, mas existe uma maneira mais limpa de chamar o que você deseja do que construir manualmente uma string de URL? Você já deu uma olhada em
$get
e$ajax
?fonte
Você poderia adicionar à classe String para ter o método to_boolean. Então você poderia fazer 'true'.to_boolean ou' 1'.to_boolean
class String def to_boolean self == 'true' || self == '1' end end
fonte
Estou surpreso que ninguém postou esta solução simples. Isso se suas strings forem "verdadeiras" ou "falsas".
def to_boolean(str) eval(str) end
fonte
to_boolean("ActiveRecord::Base.connection.execute('DROP TABLE *')")
, isso destruirá seu banco de dados (e retornará verdadeiro!). Divirta-se: Dbool = nil; bool = eval(str) if ["true", "false"].include?(str)
apenas pensei que deveria acrescentar para esclarecimentos.