У меня есть приложение Rails, и я использую jQuery для запроса своего представления поиска в фоновом режиме. Есть поля q
(поисковый запрос) start_date
,, end_date
и internal
. internal
Поле флажок и я использую is(:checked)
метод для создания URL , который опрашивается:
$.getScript(document.URL + "?q=" + $("#search_q").val() + "&start_date=" + $("#search_start_date").val() + "&end_date=" + $("#search_end_date").val() + "&internal=" + $("#search_internal").is(':checked'));
Теперь моя проблема заключается в том, params[:internal]
что есть строка, содержащая либо «истина», либо «ложь», и мне нужно преобразовать ее в логическое значение. Конечно, я могу сделать это так:
def to_boolean(str)
return true if str=="true"
return false if str=="false"
return nil
end
Но я думаю, что должен быть более рубиновый способ справиться с этой проблемой! Разве нет ...?
ActiveRecord предоставляет простой способ сделать это.
def is_true?(string) ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(string) end
ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES
имеет все очевидные представления истинных значений в виде строк.источник
ActiveRecord::ConnectionAdapters::Column.value_to_boolean(string)
(источник) 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
кажется гораздо более подходящим путем - хотя он иActiveRecord::ConnectionAdapters::Column::TRUE_VALUES
содержит «правдивые» значения, можно утверждать, что это случайный случай, и что значения, которые следует считать правдивыми для этого конкретного варианта использования, но не могут быть включены в другие. С другой стороны,ActiveModel::Type::Boolean
очевидно, что он предназначен для общего использования.Уведомление о безопасности
Обратите внимание, что этот ответ в чистом виде подходит только для другого варианта использования, указанного ниже, а не для указанного в вопросе. Хотя в основном это исправлено, существует множество уязвимостей безопасности, связанных с YAML, которые были вызваны загрузкой пользовательского ввода как YAML.
Уловка, которую я использую для преобразования строк в bools
YAML.load
, например:YAML.load(var) # -> true/false if it's one of the below
YAML bool принимает довольно много правдивых / ложных строк:
y|Y|yes|Yes|YES|n|N|no|No|NO |true|True|TRUE|false|False|FALSE |on|On|ON|off|Off|OFF
Другой вариант использования
Предположим, у вас есть такой фрагмент кода конфигурации:
config.etc.something = ENV['ETC_SOMETHING']
И в командной строке:
$ export ETC_SOMETHING=false
Теперь, поскольку
ENV
vars являются строками внутри кода,config.etc.something
значением будет строка,"false"
и она будет неправильно оцениватьсяtrue
. Но если вам это нравится:config.etc.something = YAML.load(ENV['ETC_SOMETHING'])
все было бы хорошо. Это также совместимо с загрузкой конфигураций из файлов .yml.
источник
Нет встроенного способа справиться с этим (хотя в пакете действий может быть помощник для этого). Я бы посоветовал что-то подобное
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
Что также работает, так это использовать 0 и не-0 вместо литералов false / true:
def to_boolean(s) !s.to_i.zero? end
источник
.match
ее немного легче читать.ActiveRecord::Type::Boolean.new.type_cast_from_user
делает это в соответствии с внутренними сопоставлениями RailsConnectionAdapters::Column::TRUE_VALUES
и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
Таким образом, вы можете создать свой собственный метод
to_b
(илиto_bool
илиto_boolean
) в инициализаторе, например:class String def to_b ActiveRecord::Type::Boolean.new.type_cast_from_user(self) end end
источник
Вы можете использовать гем wannabe_bool. https://github.com/prodis/wannabe_bool
Этот гем реализует
#to_b
метод для классов String, Integer, Symbol и NilClass.params[:internal].to_b
источник
В Rails 5 вы можете использовать
ActiveRecord::Type::Boolean.new.cast(value)
его для преобразования в логическое значение.источник
Я не думаю, что в Ruby встроено что-либо подобное. Вы можете повторно открыть класс String и добавить туда метод to_bool:
class String def to_bool return true if self=="true" return false if self=="false" return nil end end
Затем вы можете использовать его в любом месте вашего проекта, например:
params[:internal].to_bool
источник
to_bool
функция возвращаласьnil
; это кажется неправильным. Другие функции преобразования этого не делают:"a".to_i
возвращает0
, а не возвращаетnil
Возможно
str.to_s.downcase == 'true'
для полноты. Тогда ничего не может вылететь, даже еслиstr
это ноль или 0.источник
Глядя на исходный код Virtus , я, возможно, сделал бы что-то вроде этого:
def to_boolean(s) map = Hash[%w[true yes 1].product([true]) + %w[false no 0].product([false])] map[s.to_s.downcase] end
источник
Вы можете рассмотреть возможность добавления
internal
к своему URL-адресу только в том случае, если он истинен, тогда, если флажок не установлен, и вы не добавляете его, онparams[:internal]
будет иметьnil
значение false в Ruby.Я не так хорошо знаком с конкретным jQuery, который вы используете, но есть ли более чистый способ вызвать то, что вы хотите, чем создание строки URL-адреса вручную? Вы видели
$get
и$ajax
?источник
Вы можете добавить к классу String метод to_boolean. Тогда вы можете сделать 'true'. To_boolean или '1'.to_boolean
class String def to_boolean self == 'true' || self == '1' end end
источник
Я удивлен, что никто не опубликовал это простое решение. Это если ваши строки будут "истинными" или "ложными".
def to_boolean(str) eval(str) end
источник
to_boolean("ActiveRecord::Base.connection.execute('DROP TABLE *')")
, он уничтожит вашу базу данных (и вернет истину!). Удачи: Dbool = nil; bool = eval(str) if ["true", "false"].include?(str)
просто подумал, что стоит добавить для пояснений.