web-dev-qa-db-ja.com

Railsでブールパラメータを送信するにはどうすればよいですか?

パラメータを送信していますshow_allの値はtrueです。この値はモデルに関連付けられていません。

私のコントローラーはこのパラメーターをインスタンス変数に割り当てています:

@show_all = params[:show_all]

しかしながら、 @show_all.is_a? String、およびif @show_all == trueは常に失敗します。

Railsブール値として解析しますか?パラメーターが文字列ではなくブール値であることを明示的に指定するにはどうすればよいですか?

68
nfm

私はゼーテティックな回答についてコメントしたかったのですが、まだそれができないので、これを回答として投稿します。

使用する場合

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

その後、? true : falseなぜならparams[:show_all] == "1"ステートメント自体はtrueまたはfalseに評価されるため、三項演算子は必要ありません。

68
Uģis Ozols

更新: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
92

この質問はかなり古いですが、私はこの問題に何度か遭遇し、提案された解決策のどれも好きではなかったので、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?

それはかなりきちんとしていて、コントローラ/モデルをきれいに保つのに役立ちます。

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

チェックボックスから値を渡す場合、これはうまく機能するはずです-ハッシュのキーが欠落しているとnilが生成され、条件付きでfalseと評価されます。

[〜#〜] edit [〜#〜]

here で指摘したように、三項演算子は不要なので、次のようにすることができます。

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

17
zetetic

平等ステートメントを次のように変更できます。

@show_all == "true"

ブール値にする場合は、文字列クラスでメソッドを作成して、文字列をブール値に変換できます。

4
benr75

最も単純な解決策は、文字列表現に対して「ブール」パラメータをテストすることだと思います。

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

Railsはパラメータを文字列「true」または「false」として配信するか、実際のTrueClassまたはFalseClassとして配信するかに関係なく、このテストは常に機能します。

3
Jeremy Burton

別のアプローチは、値なしでキーのみを渡すことです。 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に存在する場合、その値に関係なく、値を型キャストする必要はなく、すべての製品を返す必要があることがわかります。

1
chaimann

すべてのブール型パラメーターを次のような実際のブール型に変換できます。

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

このソリューションでは、nilパラメーターはfalseになります。

0
fisherwebdev

以下をモデルに追加できます。

def show_all= value
  @show_all = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
end
0
mohamed-ibrahim