Edited at

check_boxによって送られてくるパラメータを真偽値として扱う方法

More than 3 years have passed since last update.


はじめに

例えば、以下の様なフォームがあった場合、

<%= form_for @user do |f| %>

<%= f.check_box :enabled %>
<% end %>

チェックの有無に応じて、サーバサイドの処理を分岐させるために以下のようなコードが書きたくなる場合がある。

if params[:user][enabled] == '1' # or 1.to_s

do_something
end

でも、上記のコードだと、特定の文字列リテラルを直接比較に使っているため、次のような意見をもらったりする。


  • Viewが修正されて、'1'ではなく'true'という文字列が渡されてきた時にどうする?


  • '1'がマジックストリング的で意図がわかりにくい
    ※ マジックストリングかどうかは議論の余地あるけど、Rubyだと01も真なので気持ちはわかる

じゃあ、どう書き換えればいいかという話。


Rails 4.2の場合

ActiveRecord::Type::Boolean#type_cast_from_userメソッドが使える。

引数と戻り値は以下のようなパターンになる。

ActiveRecord::Type::Boolean.new.type_cast_from_user(0) # false

ActiveRecord::Type::Boolean.new.type_cast_from_user(1) # true
ActiveRecord::Type::Boolean.new.type_cast_from_user('0') # false
ActiveRecord::Type::Boolean.new.type_cast_from_user('1') # true
ActiveRecord::Type::Boolean.new.type_cast_from_user(false) # false
ActiveRecord::Type::Boolean.new.type_cast_from_user(true) # true
ActiveRecord::Type::Boolean.new.type_cast_from_user('false') # false
ActiveRecord::Type::Boolean.new.type_cast_from_user('true') # true
ActiveRecord::Type::Boolean.new.type_cast_from_user(nil) # nil

冒頭のコードは以下のようになる。

if ActiveRecord::Type::Boolean.new.type_cast_from_user(params[:user][:enabled])

do_something
end


Rails 5の場合

Rails 4.2系で使えた上記メソッドが削除されている。

代わりにActiveRecord::Type::Boolean#castメソッドが使える。

引数と戻り値は以下のようなパターンになる。

ActiveRecord::Type::Boolean#type_cast_from_userと同じ)

ActiveRecord::Type::Boolean.new.cast(0) # false

ActiveRecord::Type::Boolean.new.cast(1) # true
ActiveRecord::Type::Boolean.new.cast('0') # false
ActiveRecord::Type::Boolean.new.cast('1') # true
ActiveRecord::Type::Boolean.new.cast(false) # false
ActiveRecord::Type::Boolean.new.cast(true) # true
ActiveRecord::Type::Boolean.new.cast('false') # false
ActiveRecord::Type::Boolean.new.cast('true') # true
ActiveRecord::Type::Boolean.new.cast(nil) # nil

冒頭のコードは以下のようになる。

if ActiveRecord::Type::Boolean.new.cast(params[:user][:enabled])

do_something
end


所感

マジックストリング(?)は排除できたけど、コードをパット見ても、何をやっているのか少しわかりづらくなった感じがする。

ifの条件式に直接指定するのは気が進まないので、条件判定用のメソッドを切り出す感じにするかなぁ。

def enabled?(user)

ActiveRecord::Type::Boolean.new.cast(user[:enabled])
end

if enabled?(params[:user])
do_something
end

ここまでやる必要があるかについてはわからない。