0

私のモデルの 1 つで、文字列とシンボルでも機能するように等価性を定義しました。name 属性が同じ場合、ロールは別のロール (または文字列またはシンボル) と同等です。

class Role
  def == other
    other_name = case other
                 when Role then other.name
                 when String, Symbol then other.to_s
                 end
    name == other_name
  end
end

等価チェックは正しく機能します。

role = Role.create name: 'admin'
role == 'admin' # => true
role == :admin  # => true

しかしRole、has_many 関係でモデルを使用すると、取得したコレクションで、include?この等価性が認識されません。

user = User.create
user.roles << role
User.roles.include? role    # => true
User.roles.include? 'admin' # => false 
User.roles.include? :admin  # => false

これを機能させるには、これを明示的に配列に変換する必要があります。

User.roles.to_a.include? 'admin' # => true
User.roles.to_a.include? :admin  # => true

どうやら Railsinclude?は によって返された配列のメソッドをオーバーライドしますuser.roles。これは最低であり、ruby の仕様Enumerable#include?(「Equailty は」を使用してテストされると明示的に述べています) に反してい==ます。これは、から取得した配列には当てはまりませんuser.roles==呼び出されることさえありません。

指定されたこの変更された動作はどこにありinclude?ますか?

私が見逃した包含をテストする別の方法はありますか? または、毎回to_aの実際のインスタンスを使用する必要がありますか?Role

4

1 に答える 1

0

等価演算子を正しく実装していません。そのはず:

def == other
  other_name = case other
    when Role then other.name
    when String, Symbol then other.to_s
  end
  name == other_name
end
于 2013-05-20T15:57:18.587 に答える