Rails でモデルをテストしていますが、関連付けの 1 つに n 個の項目があることを主張したいと思います。私は、assert_pattern matcher がそれを行うための非常に良い方法であることを発見しました。
assert_pattern do
author.books.to_a =>
[Book,
Book,
Book,
Book,
Book]
end
ただし、そのような項目の大きなリストがあると、読むのが難しい場合があることもわかりました。 Ruby で通常行う方法で配列を拡張してみました。
assert_pattern do
author.books.to_a => [Book]*5
end
ただし、パターン マッチャー内では、これは構文エラーになります。
test/models/book_test.rb:39: syntax error, unexpected '*', expecting `end' or dummy end (SyntaxError)
author.books.to_a => [Book]*5
^
長さに応じたパターンを作成する簡潔な方法はありますか?
私はそうは思わない。 ^(expression) を使用してパターン内で任意の式を使用できますが、マッチングはまったく異なります。
リテラル [pattern, …, *variable] 構文を使用する場合、例:
ary => [Foo, Bar, Baz]
Ruby はまず ary の長さが 3 であることを確認し、次に次のように各要素を個別に照合します。
クラスまたはモジュールの場合、これは is_a? と同等です。チェック。
上の例では、[Foo, Bar, Baz] は実際の配列ではないことに注意してください。パターン マッチングでは配列のような構文を使用するだけです。この構文内では、* をワイルドカードとして使用したり、値を変数にバインドしたりすることもできます。
^(式) 構文を使用する場合、例:
ary => ^([Foo, Bar, Baz])
Ruby はその式の結果を単一の値として扱い、チェックを 1 つだけ実行します。
=== を介して両方の配列を比較することは、各要素を個別にチェックすることと同等ではないため、あなたの場合は機能しないようです。
[Book, Book] === [Book.new, Book.new] #=> false
カスタム === 動作を持つ配列またはマッチャー オブジェクトを構築できます。ただし、その時点では、パターン マッチングの代わりに単純なアサーションを使用する方が簡単でしょう。例:
assert do
author.books.count == 5 && author.books.to_a.all?(Book)
end
(多態性の関連付けや STI を扱っている場合を除き、型チェックは不要になる可能性があります)