Tengo una aplicación Rails y estoy usando jQuery para consultar mi vista de búsqueda en segundo plano. Hay campos q(término de búsqueda) start_date, end_datey internal. El internalcampo es una casilla de verificación y estoy usando el is(:checked)método para construir la URL que se consulta:
$.getScript(document.URL + "?q=" + $("#search_q").val() + "&start_date=" + $("#search_start_date").val() + "&end_date=" + $("#search_end_date").val() + "&internal=" + $("#search_internal").is(':checked'));
Ahora mi problema es params[:internal]porque hay una cadena que contiene "verdadero" o "falso" y necesito convertirlo en booleano. Por supuesto que puedo hacerlo así:
def to_boolean(str)
return true if str=="true"
return false if str=="false"
return nil
end
¡Pero creo que debe haber una forma más rubí de lidiar con este problema! ¿No hay ...?
jquery
ruby-on-rails
ruby
ruby-on-rails-3
Davidb
fuente
fuente

ActiveRecord proporciona una forma limpia de hacer esto.
def is_true?(string) ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(string) endActiveRecord::ConnectionAdapters::Column::TRUE_VALUEStiene todas las representaciones obvias de valores verdaderos como cadenas.fuente
ActiveRecord::ConnectionAdapters::Column.value_to_boolean(string)(fuente) apidock.com/rails/v3.0.9/ActiveRecord/ConnectionAdapters/Column/…ActiveRecord::Type::Boolean.new.type_cast_from_user("true")=> verdaderoActiveRecord::Type::Boolean.new.type_cast_from_user("T")=> verdaderoActiveModel::Type::Booleanparece un camino mucho más adecuado - aunqueActiveRecord::ConnectionAdapters::Column::TRUE_VALUEScontiene valores de "veracidad", se podría argumentar que es solo incidentalmente el caso, y que los valores que deberían considerarse veraces para ese caso de uso específico pero no otros podrían incluirse. Por otro lado,ActiveModel::Type::Booleanaparentemente está diseñado para ser utilizado de forma genérica.Aviso de seguridad
Tenga en cuenta que esta respuesta en su forma básica solo es apropiada para el otro caso de uso que se enumera a continuación en lugar del de la pregunta. Si bien en su mayoría se corrigió, ha habido numerosas vulnerabilidades de seguridad relacionadas con YAML que fueron causadas por cargar la entrada del usuario como YAML.
Un truco que utilizo para convertir cadenas en bools es
YAML.load, por ejemplo:YAML.load(var) # -> true/false if it's one of the belowYAML bool acepta muchas cadenas de verdad / falsedad:
y|Y|yes|Yes|YES|n|N|no|No|NO |true|True|TRUE|false|False|FALSE |on|On|ON|off|Off|OFFOtro caso de uso
Suponga que tiene un fragmento de código de configuración como este:
config.etc.something = ENV['ETC_SOMETHING']Y en la línea de comandos:
$ export ETC_SOMETHING=falseAhora, dado que las
ENVvars son cadenas una vez dentro del código,config.etc.somethingel valor de la cadena sería la cadena"false"y se evaluaría incorrectamentetrue. Pero si te gusta esto:config.etc.something = YAML.load(ENV['ETC_SOMETHING'])todo estaría bien. Esto también es compatible con la carga de configuraciones desde archivos .yml.
fuente
No hay ninguna forma incorporada de manejar esto (aunque actionpack podría tener una ayuda para eso). Aconsejaría algo como esto
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) endLo que también funciona es usar 0 y no 0 en lugar de literales falsos / verdaderos:
def to_boolean(s) !s.to_i.zero? endfuente
.matches un poco más fácil de leer.ActiveRecord::Type::Boolean.new.type_cast_from_userhace esto de acuerdo con las asignaciones internas de RailsConnectionAdapters::Column::TRUE_VALUESyConnectionAdapters::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) => falseEntonces podría crear su propio
to_b(to_booloto_boolean) método en un inicializador como este:class String def to_b ActiveRecord::Type::Boolean.new.type_cast_from_user(self) end endfuente
Puedes usar wannabe_bool gem. https://github.com/prodis/wannabe_bool
Esta gema implementa un
#to_bmétodo para las clases String, Integer, Symbol y NilClass.params[:internal].to_bfuente
En Rails 5 puedes usarlo
ActiveRecord::Type::Boolean.new.cast(value)para convertirlo en un booleano.fuente
No creo que nada de eso esté integrado en Ruby. Puede volver a abrir la clase String y agregar el método to_bool allí:
class String def to_bool return true if self=="true" return false if self=="false" return nil end endEntonces puedes usarlo en cualquier lugar de tu proyecto, así:
params[:internal].to_boolfuente
to_boolfunción de retornonil; eso parece incorrecto. Otras funciones de conversión no hacen esto:"a".to_idevuelve0, nonilQuizás
str.to_s.downcase == 'true'para completar. Entonces nada puede fallar incluso sistres nulo o 0.fuente
Mirando el código fuente de Virtus , tal vez haría algo como esto:
def to_boolean(s) map = Hash[%w[true yes 1].product([true]) + %w[false no 0].product([false])] map[s.to_s.downcase] endfuente
Podría considerar agregar solo
internala su URL si es verdadera, luego, si la casilla de verificación no está marcada y no agrega, loparams[:internal]estaríanil, lo que se evalúa como falso en Ruby.No estoy tan familiarizado con el jQuery específico que estás usando, pero ¿hay una forma más limpia de llamar a lo que quieras que construir manualmente una cadena de URL? ¿Has echado un vistazo a
$gety$ajax?fuente
Puede agregar a la clase String para tener el método to_boolean. Entonces podrías hacer 'true' .to_boolean o '1'.to_boolean
class String def to_boolean self == 'true' || self == '1' end endfuente
Me sorprende que nadie haya publicado esta sencilla solución. Eso es si sus cadenas van a ser "verdaderas" o "falsas".
def to_boolean(str) eval(str) endfuente
to_boolean("ActiveRecord::Base.connection.execute('DROP TABLE *')"), destruirá su base de datos (¡y devolverá verdadero!). Diviértete: Dbool = nil; bool = eval(str) if ["true", "false"].include?(str)solo pensé que debería agregar por el bien de las aclaraciones.