Как отправить логический параметр в Rails?


я отправляю параметр show_all со значением true. Это значение не связано с моделью.

мой контроллер присваивает этот параметр переменной экземпляра:

@show_all = params[:show_all]

однако, @show_all.is_a? String и if @show_all == true всегда терпит неудачу.

какие значения Rails анализирует как булевы? Как я могу явно указать, что мой параметр является логическим, а не строкой?

9 59

9 ответов:

Я хотел прокомментировать ответ zetetic, но поскольку я еще не могу этого сделать, я опубликую это в качестве ответа.

Если вы используете

@show_all = params[:show_all] == "1"

затем вы можете удалить ? true : false, потому что params[:show_all] == "1" сам оператор будет оцениваться как true или false и, следовательно, тернарный оператор не нужен.

обновление: рельсы 5:

ActiveRecord::Type::Boolean.new.deserialize('0')

обновление: 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

этот вопрос довольно старый, но так как я столкнулся с этой проблемой пару раз, и мне не понравилось ни одно из предложенных решений, я сам взломал что-то, что позволяет использовать несколько строк для правда например, "да", "on", " t " и наоборот для false.

Monkey исправляет строку класса и добавляет метод для преобразования их в boolean, и помещает этот файл в /config/initializers как предложено здесь: обезьяна латая в рельсах 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?

Это довольно аккуратно, и помогает держать контроллеры/модели чистой.

@show_all = params[:show_all] == "1" ? true : false

Это должно работать хорошо, если вы передаете значение из флажка -- отсутствующий ключ в хэше генерирует nil, который оценивается как false в условном.

EDIT

Как указал здесь, тернарный оператор не нужен, так что это может быть просто:

@show_all = params[:show_all] == "1"

вы можете изменить свое утверждение равенства на:

@show_all == "true"

Если вы хотите, чтобы он был логическим, вы можете создать метод в классе string для преобразования строки в логическое значение.

Я думаю, что самое простое решение-проверить "булевы" параметры против их строкового представления.

@show_all = params[:show_all]
if @show_all.to_s == "true"
   # do stuff
end

независимо от того, предоставляет ли Rails параметр в виде строки "true" или "false" или фактического TrueClass или FalseClass, этот тест всегда будет работать.

вы можете конвертировать все ваши логические параметры в реальные логические значения следующим образом:

%w(show_all, show_featured).each do |bool_param|
  params[bool_param.to_sym] = params[bool_param.to_sym] == "true"
end

в этом решении нулевые параметры станут ложными.

другой подход заключается в передаче только ключа без значения. Хотя с помощью ActiveRecord::Type::Boolean.new.type_cast_from_user(value) довольно аккуратно, может возникнуть ситуация, когда присвоение значения ключу param является избыточным.

рассмотрим следующий: В моем представлении индекса продуктов по умолчанию я хочу показать только ограниченную коллекцию продуктов (например, те, которые находятся на складе). То есть если я хочу вернуть все продукты, я могу отправить myapp.com/products?show_all=true и типизировать

вы можете добавить в свою модель следующее:

def show_all= value
  @show_all = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
end