1

Mongoid でサポートされている Rails 3.2.3 アプリで、Capybara を介して Cucumber を使用してシナリオを実行しようとしています。目的は、現在のユーザーに自分のコレクションに本を追加してもらうことです。

すべてうまくいきましたが、書籍の数が 1 になったことを確認する最後のステップの定義が失敗しました。

しかし、アプリコントローラーを確認すると、実際にはサイズが大きくなりました。実際、reloadステップ定義でユーザーに送信すると、次のように渡されます。

user.reload.books(true).size.should == 1

この動作は、本番環境でアプリに害を及ぼす可能性があるのではないかと心配しています。すべてのテストとアプリの動作が一貫していることを確認するためのアドバイスはありますか?

アップデート

test.log をチェックして、何が起こっているかを確認しました。呼び出しreloadて、MongoDB に次のクエリを取得します。

find({"count"=>"books",
"query"=>{:_id=>{"$in"=>[BSON::ObjectId('4f889b473dffd63235000004')]}},
"fields"=>nil}).limit(-1)

リロードなしで私はこれを得る:

find({"count"=>"books", "query"=>{:_id=>{"$in"=>[]}}, "fields"=>nil}).limit(-1)

モデルをリロードしないと実質的にクエリを実行しuserません。これはあまり意味がありません。

4

1 に答える 1

0

以下は私にとってはうまくいきます(実際のキュウリの例で更新されました)

あなたの問題をテストするためにRailsプロジェクトを構築しました.rails 3.2.3、mongoid 2.4.8、mongo 1.6.2、mongodb 2.0.4、cucumber 1.1.9.

次の (関連付けによって生成されたメソッド) は、更新する必要なく、期待どおりに機能します。

user.books << book
book.users << user

それから私は協会を迂回しようとしましたが、それはあなたがやっていることだと思いました.

user.push(:book_ids, book.id)
book.push(:user_ids, user.id)

これらの DO は関連付けをバイパスし、不完全な (双方向ではなく一方向の) 参照になりますが、メモリとデータベースの状態は一貫しています。したがって、あなたが経験していたことについての私の以前の回答での私の推測は間違っていました。リフレッシュは必要なく、おそらく他のことをしているのでしょう。あなた/私たちは不完全な参照を望んでいないことに注意してください.Mongoid参照関係の内部に直接プッシュしないでください.

ユーザーまたはブックを追加するために関連付け追加「<<」を使用していますか? 私の現在の結論は、Mongoid 参照関係は、あなたの問題の私のテストで宣伝されているように機能するということです。リフレッシュの必要はありません。

モデルは次のとおりです。

class User
  include Mongoid::Document
  field :first_name, type: String
  field :last_name, type: String
  has_and_belongs_to_many :books
end

class Book
  include Mongoid::Document
  field :title, type: String
  field :author, type: String
  has_and_belongs_to_many :users
end

きゅうりの特徴

Feature: UserAndBook
  Test adding a book to a user_s books

  Scenario: add_book_to_user
    Given starting with no users and no books
    And a new user
    And that the new user has no books
    And a new book
    And add book to user
    Then I can check that the user has a book

キュウリの手順

require 'test/unit/assertions'
require File.expand_path('../../../test/test_helper', __FILE__)
World(Test::Unit::Assertions)

Given 'starting with no users and no books' do
  User.delete_all
  Book.delete_all
  assert_equal(0, User.count)
  assert_equal(0, Book.count)
end

Given 'a new user' do
  @user = User.create(first_name: 'Gary', last_name: 'Murakami')
end

Given 'that the new user has no books' do
  assert_equal(0, @user.books.count)
end

Given 'a new book' do
  @book = Book.create(title: 'A Tale of Two Cities', author: 'Charles Dickens')
end

Given 'add book to user' do
  @user.books << @book
end

Then 'I can check that the user has a book' do
  assert_equal(1, @user.books.count)
end

お客様の問題に対処するために、引き続き情報を交換させていただきます。

祝福、

-ゲイリー

PS ログを見ると、興味深いのは、user.books.length がローカル配列の長さではなく、実際の db "find count $in" クエリを実行していることです。

前の回答

あなたは自分の質問にほとんど答えました。Rails では、モデルのデータがデータベースで変更されるたびに reload メソッドを使用する必要があります。そうしないと、モデルの以前にロード/インスタンス化/キャッシュされた状態を確認することになります。属性だけを更新すると、かなり一貫しているように見えますが、関連付けはより複雑になり、矛盾がより明白になります。

于 2012-04-05T20:54:20.927 に答える