when - jquery read if checkbox is checked




String "true" e "false" in booleano (9)

Ho un'applicazione Rails e sto usando jQuery per interrogare la mia vista di ricerca in background. Ci sono campi q (termine di ricerca), start_date , start_date e internal . Il campo internal è una casella di controllo e sto usando il metodo is(:checked) per compilare l'url che viene interrogato:

$.getScript(document.URL + "?q=" + $("#search_q").val() + "&start_date=" + $("#search_start_date").val() + "&end_date=" + $("#search_end_date").val() + "&internal=" + $("#search_internal").is(':checked'));

Ora il mio problema è in params[:internal] perché c'è una stringa che contiene "true" o "false" e ho bisogno di trasmetterla a boolean. Certo che posso farlo in questo modo:

def to_boolean(str)
     return true if str=="true"
     return false if str=="false"
     return nil
end

Ma penso che ci debba essere un modo più rubino per affrontare questo problema! Non c'è ...?


Avviso di sicurezza

Si noti che questa risposta nella sua forma nuda è appropriata solo per l'altro caso d'uso elencato di seguito piuttosto che quello nella domanda. Sebbene siano state risolte per la maggior parte, vi sono state numerose vulnerabilità di sicurezza correlate a YAML che sono state causate dal caricamento di input dell'utente come YAML.

Un trucco che uso per convertire stringhe in YAML.load è YAML.load , ad es .:

YAML.load(var) # -> true/false if it's one of the below

Il bool di YAML accetta un sacco di stringhe di verità / falsi:

y|Y|yes|Yes|YES|n|N|no|No|NO
|true|True|TRUE|false|False|FALSE
|on|On|ON|off|Off|OFF

Un altro caso d'uso

Supponiamo che tu abbia un pezzo di codice di configurazione come questo:

config.etc.something = ENV['ETC_SOMETHING']

E in riga di comando:

$ export ETC_SOMETHING=false

Ora dal momento che ENV vars sono stringhe una volta all'interno del codice, il valore di config.etc.something sarebbe la stringa "false" e sarebbe erroneamente valutato su true . Ma se ti piace questo:

config.etc.something = YAML.load(ENV['ETC_SOMETHING'])

andrebbe tutto bene. Questo è compatibile con il caricamento di configurazioni anche da file .yml.


È possibile aggiungere alla classe String per avere il metodo di to_boolean. Quindi potresti fare 'true'.to_boolean o '1.to_boolean

class String
  def to_boolean
    self == 'true' || self == '1'
  end
end

Forse str.to_s.downcase == 'true' per completezza. Quindi nulla può bloccarsi anche se str è nullo o 0.


Guardando il codice sorgente di Virtus , forse farei qualcosa del genere:

def to_boolean(s)
  map = Hash[%w[true yes 1].product([true]) + %w[false no 0].product([false])]
  map[s.to_s.downcase]
end

Non c'è alcun modo integrato per gestirlo (sebbene actionpack possa avere un aiuto per questo). Consiglierei qualcosa come questo

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

Ciò che funziona bene è usare 0 e non-0 invece di letterali falsi / veri:

def to_boolean(s)
  !s.to_i.zero?
end

Non credo che qualcosa del genere sia integrato in Ruby. Puoi riaprire la classe String e aggiungere il metodo to_bool lì:

class String
    def to_bool
        return true if self=="true"
        return false if self=="false"
        return nil
    end
end

Quindi puoi utilizzarlo ovunque nel tuo progetto, in questo modo: params[:internal].to_bool


Potresti considerare solo l'accodamento internal al tuo url se è vero, quindi se la casella di controllo non è spuntata e non la aggiungi, params[:internal] sarebbe nil , che in Ruby viene valutata come falsa.

Non sono così familiare con il jQuery specifico che stai utilizzando, ma esiste un modo più semplice per chiamare ciò che vuoi rispetto alla creazione manuale di una stringa URL? Hai dato un'occhiata a $get e $ajax ?



ActiveRecord::Type::Boolean.new.type_cast_from_user esegue questa operazione in base ai mapping interni di Rails ConnectionAdapters::Column::TRUE_VALUES e ConnectionAdapters::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

Quindi puoi creare il tuo to_b (o to_bool o to_boolean ) in un inizializzatore come questo:

class String
  def to_b
    ActiveRecord::Type::Boolean.new.type_cast_from_user(self)
  end
end




ruby-on-rails-3