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_date
y internal
. El internal
campo 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) end
ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES
tiene 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::Boolean
parece un camino mucho más adecuado - aunqueActiveRecord::ConnectionAdapters::Column::TRUE_VALUES
contiene 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::Boolean
aparentemente 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 below
YAML 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|OFF
Otro 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=false
Ahora, dado que las
ENV
vars son cadenas una vez dentro del código,config.etc.something
el 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) end
Lo que también funciona es usar 0 y no 0 en lugar de literales falsos / verdaderos:
def to_boolean(s) !s.to_i.zero? end
fuente
.match
es un poco más fácil de leer.ActiveRecord::Type::Boolean.new.type_cast_from_user
hace esto de acuerdo con las asignaciones internas de RailsConnectionAdapters::Column::TRUE_VALUES
yConnectionAdapters::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
Entonces podría crear su propio
to_b
(to_bool
oto_boolean
) método en un inicializador como este:class String def to_b ActiveRecord::Type::Boolean.new.type_cast_from_user(self) end end
fuente
Puedes usar wannabe_bool gem. https://github.com/prodis/wannabe_bool
Esta gema implementa un
#to_b
método para las clases String, Integer, Symbol y NilClass.params[:internal].to_b
fuente
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 end
Entonces puedes usarlo en cualquier lugar de tu proyecto, así:
params[:internal].to_bool
fuente
to_bool
función de retornonil
; eso parece incorrecto. Otras funciones de conversión no hacen esto:"a".to_i
devuelve0
, nonil
Quizás
str.to_s.downcase == 'true'
para completar. Entonces nada puede fallar incluso sistr
es 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] end
fuente
Podría considerar agregar solo
internal
a 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
$get
y$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 end
fuente
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) end
fuente
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.