Как отправить логический параметр в Rails?
Я представляю параметр show_all
со значением true
. Это значение не связано с моделью.
Мой контроллер назначает этот параметр переменной экземпляра:
@show_all = params[:show_all]
Однако @show_all.is_a? String
и if @show_all == true
всегда терпят неудачу.
Какие значения Rails обрабатывают как логические значения? Как я могу явно указать, что мой параметр является логическим, а не строкой?
Ответы
Ответ 1
Я хотел прокомментировать zetetic ответ, но поскольку я не могу этого сделать, я опубликую это как ответ.
Если вы используете
@show_all = params[:show_all] == "1"
то вы можете отказаться от ? true : false
, потому что сам оператор params[:show_all] == "1"
будет оценивать true или false и, следовательно, троичный оператор не нужен.
Ответ 2
UPDATE: Rails 5:
ActiveRecord::Type::Boolean.new.deserialize('0')
UPDATE: Rails 4.2 имеет общедоступный API для этого:
ActiveRecord::Type::Boolean.new.type_cast_from_user("0") # false
ПРЕДЫДУЩИЙ ОТВЕТ:
ActiveRecord поддерживает список представлений для true/false в https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/column.rb
2.0.0-p247 :005 > ActiveRecord::ConnectionAdapters::Column.value_to_boolean("ON")
2.0.0-p247 :006 > ActiveRecord::ConnectionAdapters::Column.value_to_boolean("F")
Это не является частью общедоступного API Rails, поэтому я заключил его в вспомогательный метод:
class ApplicationController < ActionController::Base
private
def parse_boolean(value)
ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
end
end
и добавил базовый тест:
class ApplicationControllerTest < ActionController::TestCase
test "parses boolean params" do
refute ApplicationController.new.send(:parse_boolean, "OFF")
assert ApplicationController.new.send(:parse_boolean, "T")
end
end
Ответ 3
Этот вопрос довольно старый, но так как я пару раз сталкивался с этой проблемой и мне не нравилось предлагаемое решение, я сам что-то взломал, что позволяет использовать несколько строк для истины например, "да", 'on', 't' и наоборот для false.
Обезьяна патёт класс String и добавьте метод для преобразования их в boolean и поместите этот файл в /config/initializers
, как предлагается здесь: Патч обезьяны в Rails 3
class String
def to_bool
return true if ['true', '1', 'yes', 'on', 't'].include? self
return false if ['false', '0', 'no', 'off', 'f'].include? self
return nil
end
end
Обратите внимание, что если значение не является ни одним из действительных значений для true или false, оно возвращает nil. Это не то же самое, что искать ?paid=false
(вернуть все записи не оплачены), чем ?paid=
(я не указываю, нужно ли это платить или нет), поэтому отбросьте это).
Затем, следуя этому примеру, логика вашего контроллера будет выглядеть так:
Something.where(:paid => params[:paid].to_bool) unless params[:paid].try(:to_bool).nil?
Это довольно аккуратно и помогает держать контроллеры/модели чистыми.
Ответ 4
@show_all = params[:show_all] == "1" ? true : false
Это должно работать хорошо, если вы передаете значение из флажка - отсутствующий ключ в хеше генерирует nil, который вычисляет false в условном выражении.
ИЗМЕНИТЬ
Как указано здесь, тернарный оператор не нужен, поэтому это может быть просто:
@show_all = params[:show_all] == "1"
Ответ 5
Вы можете изменить оператор равенства:
@show_all == "true"
Если вы хотите, чтобы он был логическим, вы могли бы создать метод в классе строк для преобразования строки в логическое.
Ответ 6
Я думаю, что самым простым решением является проверка "логических" параметров на их строковое представление.
@show_all = params[:show_all]
if @show_all.to_s == "true"
# do stuff
end
Независимо от того, передает ли Rails параметр в виде строки "true" или "false" или фактического TrueClass или FalseClass, этот тест всегда будет работать.
Ответ 7
Вы можете преобразовать все ваши логические параметры в реальные булевы, как это:
%w(show_all, show_featured).each do |bool_param|
params[bool_param.to_sym] = params[bool_param.to_sym] == "true"
end
В этом решении параметры nil станут ложными.
Ответ 8
Другой подход - передать только ключ без значения. Хотя использование ActiveRecord::Type::Boolean.new.type_cast_from_user(value)
довольно аккуратно, может возникнуть ситуация, когда присвоение значения параметру ключа является избыточным.
Рассмотрим следующее:
По представлению индекса моей продукции по умолчанию я хочу показать только ограниченный набор продуктов (например, те, которые находятся на складе). То есть, если я хочу вернуть все продукты, я могу отправить myapp.com/products?show_all=true
и вывести тип show_all
для логического значения.
Однако противоположный вариант - myapp.com/products?show_all=false
просто не имеет смысла, так как он вернет ту же коллекцию продуктов, что и myapp.com/products
.
Альтернатива:
если я хочу вернуть всю коллекцию без доступа, я отправляю myapp.com/products?all
и в контроллере
private
def show_all?
params.key?(:all)
end
Если ключ присутствует в параметрах, то независимо от его значения, я буду знать, что мне нужно возвращать все продукты, нет необходимости в значениях типа.
Ответ 9
Вы можете добавить в свою модель следующее:
def show_all= value
@show_all = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
end