16

いくつかの属性と仮想属性を持つモデルがあります。この仮想属性は、作成フォームにチェックボックスを作成するために使用されます。

class Thing < ActiveRecord::Base
  attr_accessor :foo
  attr_accessible :foo
end

フィールドはフォームのチェックボックスであるため、属性はorを値としてfoo受け取ります。次のコードのため、ブール値にしたいと思います。'0''1'

class Thing < ActiveRecord::Base
  attr_accessor :foo
  attr_accessible :foo

  before_validation :set_default_bar

  private

  def set_default_bar
    self.bar = 'Hello' if foo
  end
end

ここでの問題は、 is の場合でも条件が true になることfooです'0'。ActiveRecord 型のキャスト メカニズムを使用したいのですが、それができることがわかったのは次の 1 つだけです。

class Thing < ActiveRecord::Base
  attr_reader :foo
  attr_accessible :foo

  before_validation :set_default_bar

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


  private

  def set_default_bar
    self.bar = 'Hello' if foo
  end
end

でも、そんなことをすると汚い気がする。変換方法を書き直さずに、より良い代替手段はありますか?

ありがとう

4

4 に答える 4

15

元の投稿からのあなたの解決策は、私にとって最良の解決策のように見えます。

class Thing < ActiveRecord::Base
  attr_reader :foo
  def foo=(value)
    @foo = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
  end
end

少し整理したい場合は、foo=を使用してライター メソッドを定義するヘルパー メソッドをいつでも作成できますvalue_to_boolean

bool_attr_accessorモデルを単純化して次のようにできるように、メソッドが呼び出されたモジュールを作成する可能性があります。

class Thing < ActiveRecord::Base
  bool_attr_accessor :foo
end

仮想属性が「実際の」(ActiveRecord に永続化された) 属性のように機能するように、ActiveModel はこのようなものを提供する必要があるようです。この型キャストは、フォームから送信されたブール型の仮想属性がある場合に不可欠です。

Railsにパッチを提出する必要があるかもしれません...

于 2012-10-22T21:43:30.547 に答える
1

validates_acceptance_ofコードを見てください([ソースを表示] をクリックします)。彼らはそれを「0」と比較して実装しました。

私はこの方法で登録フォームでそれを使用しています:

class User < ActiveRecord::Base
  validates_acceptance_of :terms_of_service
  attr_accessible :terms_of_service
end

本当に文字列などからキャストしたい場合は、これを使用できます:

def foo=(value)
  self.foo=(value == true || value==1 || value =~ (/(true|t|yes|y|1)$/i)) ? true:false
end

または、クラスに typecast メソッドを追加Stringして、モデルで使用します。

class String
 def to_bool
   return true if self == true || self =~ (/(true|t|yes|y|1)$/i)
   return false if self == false || self.blank? || self =~ (/(false|f|no|n|0)$/i)
   raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
 end
end
于 2012-07-19T13:29:12.933 に答える
0

なぜあなたはこれをしないのですか:

def foo=(value)
  @foo = value
  @bar = 'Hello' if value == "1"
end
于 2012-07-19T13:16:17.110 に答える