2011-07-17 18 views
1

私はテストが失敗する理由を見つけるためにしようと苦労している:奇妙な関係の挙動レール3とupdate_attribute

describe User, "Instance Methods" do 
    describe "leave_group!" do 
    it "should set group_id to nil" do 
     @user = Factory(:user) 
     @group_2 = Factory(:group, :owner => @user) 

     @user.leave_group! 
     @user.reload.group_id.should be_nil # THIS LINE IS FAILING!!! 
    end 

    it "should assign another owner to group, if owner was user" do 
     @user = Factory(:user) 
     @group = Factory(:group, :owner => @user) 
     1.upto(4) { @group.add_user Factory(:user) } 

     @user.leave_group! 
     @group.reload.owner.should_not eql(@user) 
    end 
    end 
end 

これらは、私が使用しているモデルです。

class User < ActiveRecord::Base 
    # Associations 
    has_one :own_group, :class_name => "Group", :foreign_key => "owner_id" 
    belongs_to :group 

    def leave_group! 
    current_group_id, current_group_owner = self.group.id, self.group.owner 
    self.group_id = nil 
    save! 
    Group.find(current_group_id).randomize_owner! if current_group_owner == self 
    end 
end 

class Group < ActiveRecord::Base 
    # Associations 
    has_many :users 
    belongs_to :owner, class_name: "User" 

    def randomize_owner! 
    current_users = self.users 
    return false unless current_users.length > 1 
    begin 
     new_user = current_users.sort_by { rand }.first 
    end while self.owner == new_user 
    self.owner_id = new_user.id 
    save! 
    end 
end 

私はここで何か間違っていますか?私はそれを改善することができますか?さらに重要なのは、その単一のテストが失敗する理由は何ですか?

はここでその単一のテストをruningてのログ出力です:

SQL (0.2ms) SELECT name 
FROM sqlite_master 
WHERE type = 'table' AND NOT name = 'sqlite_sequence' 

AREL (0.3ms) INSERT INTO "users" ("name", "uid", "provider", "email", "image_url", "group_id", "created_at", "updated_at", "timezone", "public_readings", "is_visible_on_leaderboards", "phone_number") VALUES ('John Doe', '314159265', 'facebook', '[email protected]', NULL, NULL, '2011-07-18 02:02:08.455229', '2011-07-18 02:02:08.455229', NULL, 't', 't', NULL) 
Group Load (0.1ms) SELECT "groups".* FROM "groups" WHERE "groups"."key" = 'SNYEMJ' LIMIT 1 
AREL (0.1ms) INSERT INTO "groups" ("name", "key", "score", "owner_id", "created_at", "updated_at") VALUES ('John''s Group', 'SNYEMJ', 0, 1, '2011-07-18 02:02:08.522442', '2011-07-18 02:02:08.522442') 
AREL (0.0ms) UPDATE "users" SET "group_id" = 1, "updated_at" = '2011-07-18 02:02:08.524342' WHERE "users"."id" = 1 
Group Load (0.1ms) SELECT "groups".* FROM "groups" WHERE "groups"."id" = 1 LIMIT 1 
User Load (0.2ms) SELECT "users".* FROM "users" WHERE ("users".group_id = 1) 
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1 

最後の3行はすべて選択され、予告レールでも、ユーザーからgroup_idのを削除しようとしません。 (2人の挿入があり、テストユーザーには1人、テストグループには1人、テストユーザーにはgroup_idが割り当てられています)。偶然に

+0

SQLクエリを含め、最初のテスト用にlogs/test.logの出力を追加してください。 – Thilo

+0

私はちょうどそれらを追加しました。 2つの更新(ユーザーからgroup_idを削除する場合は1、グループに別のowner_idを割り当てる場合は1)を実行する必要があるにもかかわらず、どのように挿入または更新を実行しようとしていないかに注目してください。 – Lonecat

答えて

1

をテスト中@user.leave_group@user.reloadコールを追加してみてください。

@group_2を工場で作成したときに、ユーザーレコードがDB内のグループで更新されても、私は@userオブジェクトではないと思われます。次にleave_group!@userとし、group IDをnilとすると、オブジェクトは変更されないため、保存は何も行われません。テストの次の行で、@userをリロードします。これには以前に割り当てられたDBのgroup_idがあります。

+0

ありがとうございます!私は@ user.leave_groupを変更しました! 〜@ user.reload.leave_group!それは働いた! :D私はそれを逃した方法を知りません。 – Lonecat

0

試してモデルクラス次のように:

class User < ActiveRecord::Base 
    # Associations 
    has_one :own_group, :class_name => "Group", :foreign_key => "owner_id" 
    belongs_to :group 

    def leave_group! 
    group_randomize_owner 
    self.group.clear 
    end 

    private 

    def group_randomize_owner 
    if group.owner == self 
     group.randomize_owner! 
    end 
    end 
end 
+0

これは動作しません。self.group.clearは、実際にはメソッドではないGroup#clearを呼び出そうとするため、エラーをスローします。しかし、これは次のようなグループで動作します:@ group.users.clearこれは私が解決する必要があるケースではありません。助けてくれてありがとう! – Lonecat