パラメータを送信していますshow_all
の値はtrue
です。この値はモデルに関連付けられていません。
私のコントローラーはこのパラメーターをインスタンス変数に割り当てています:
@show_all = params[:show_all]
しかしながら、 @show_all.is_a? String
、およびif @show_all == true
は常に失敗します。
Railsブール値として解析しますか?パラメーターが文字列ではなくブール値であることを明示的に指定するにはどうすればよいですか?
私はゼーテティックな回答についてコメントしたかったのですが、まだそれができないので、これを回答として投稿します。
使用する場合
@show_all = params[:show_all] == "1"
その後、? true : false
なぜならparams[:show_all] == "1"
ステートメント自体はtrueまたはfalseに評価されるため、三項演算子は必要ありません。
更新:Rails 5:
ActiveRecord::Type::Boolean.new.deserialize('0')
更新:Rails 4.2にはこのためのパブリックAPIがあります:
ActiveRecord::Type::Boolean.new.type_cast_from_user("0") # false
前の回答:
ActiveRecordは https://github.com/Rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/column.rb でtrue/falseの表現のリストを維持します
2.0.0-p247 :005 > ActiveRecord::ConnectionAdapters::Column.value_to_boolean("ON")
2.0.0-p247 :006 > ActiveRecord::ConnectionAdapters::Column.value_to_boolean("F")
これはRailsのパブリックAPIの一部ではないため、ヘルパーメソッドにラップしました。
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
この質問はかなり古いですが、私はこの問題に何度か遭遇し、提案された解決策のどれも好きではなかったので、trueのために複数の文字列を使用できるように自分で何かをハッキングしました 'yes'、 'on'、 't'など、falseの反対。
モンキーはクラス文字列にパッチを適用し、それらをブール値に変換するメソッドを追加し、このファイルをここで提案されているように/config/initializers
に配置します。 Monkey Patching in Rails =
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 [〜#〜]
here で指摘したように、三項演算子は不要なので、次のようにすることができます。
@show_all = params[:show_all] == "1"
平等ステートメントを次のように変更できます。
@show_all == "true"
ブール値にする場合は、文字列クラスでメソッドを作成して、文字列をブール値に変換できます。
最も単純な解決策は、文字列表現に対して「ブール」パラメータをテストすることだと思います。
@show_all = params[:show_all]
if @show_all.to_s == "true"
# do stuff
end
Railsはパラメータを文字列「true」または「false」として配信するか、実際のTrueClassまたはFalseClassとして配信するかに関係なく、このテストは常に機能します。
別のアプローチは、値なしでキーのみを渡すことです。 ActiveRecord::Type::Boolean.new.type_cast_from_user(value)
を使用することは非常に適切ですが、paramキーに値を割り当てることが冗長な場合があります。
次の点を考慮してください:デフォルトでは、製品のインデックスビューには、スコープ付きの製品のコレクション(在庫がある製品など)のみを表示します。すべての製品を返したい場合は、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
キーがparamsに存在する場合、その値に関係なく、値を型キャストする必要はなく、すべての製品を返す必要があることがわかります。
すべてのブール型パラメーターを次のような実際のブール型に変換できます。
%w(show_all, show_featured).each do |bool_param|
params[bool_param.to_sym] = params[bool_param.to_sym] == "true"
end
このソリューションでは、nilパラメーターはfalseになります。
以下をモデルに追加できます。
def show_all= value
@show_all = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
end