On 3/16/08, David Chelimsky <[EMAIL PROTECTED]> wrote:
> On Fri, Mar 14, 2008 at 8:12 PM, Rick DeNatale <[EMAIL PROTECTED]> wrote:

>  >  2)  Having figured that out and moving on,  I now have another
>  >  problem, which is what's the best way to clean up the database so that
>  >  Scenario A can run again if it assumes that the stuff it put in the DB
>  >  isn't there each time it runs. Cleaning the DB after running the
>  >  scenario won't work since it defeats the purpose of using the scenario
>  >  as a pre-condition.  Cleaning it before is more difficult,
>  >  particularly if I'm using parameterized steps.  It would be nice if I
>  >  could somehow use database transactions, but I don't see a nice way to
>  >  do that either.
>
>
> This should just work. If you look at story_adapter.rb, which defines
>  the RailsStory class (maybe we should align :) ) you'll see that the
>  transaction is opened when the scenario starts and rolled back when it
>  is finished. GivenScenario should not result in a call to any of the
>  scenario finished methods (scenario_succeeded, _pending, _failed), so
>  it should get rolled back.

I've gotten stuck here.

To recap, when I don't make the story a RailsStory, then the the first
scenario (A) works but fails when invoked from B as a GivenScenario.
One of the steps is  failing because of a validates_uniqueness in on
of the models which fails because of stuff left in the DB from the
initial running.

When I change it to a RailsStory then Scenario A fails in the same
step the FIRST time.  In this case it's because records which it needs
aren't there.

The records in question have been loaded by a helper which calls
Fixtures.create_fixtures to load them. These particular tables are
basically 'constants' for the app.

A few more tidbits.

There's are models called Role, Membership, and a join model MembershipRole

Role
   has_many :membership_roles
   has_many :memberships :through => :membership_roles
end

Membership
  has_many :membership_roles
  has_many :membersships, :through => :membership_roles
end

MembershipRole
  belongs_to :membership
  belongs_to :role
  validates uniqueness_of :role_id, :scope => :membership_id
end

Role has a class method get which takes a string and effectivly does this:

def self.get(name)
    @role_objects ||= {}
    @role_objects[name] ||= find_by_name(name)
end

And the method ultimately invoked by the failing step has a skeleton like this:

class Membership < ActiveRecord::Base

def add_role(name)
  if role = Role.get(name)
     ...
  else
    raise "Can't find Role named #{name}
  end
end

If I change the Role.get method to bypass the cache then the exception
gets raised the first time the step is executed for a RailsStory, and
second time for a non-RailsStory.

With that method left alone, the Role objects are found at some time
previous to the step and cached, in which case the failure happens
inside the if where a simplified version of that ... looks like this:

      unless self.roles(true).include(role)
          membership_role = MembershipRole.create(:membership => self,
:role => role)
      end
      role.dependencies.each {|dependency| add_role(dependency)

The problem is that the validates_uniqueness_of in MemberRole is
failing, again the second time the step in question is called for a
non-RailsStory, and the first time for a RailsStory.  The reason is
that the query generated by the roles association is doing a join on
roles and membership roles and the roles aren't in the DB, but then
validates_uniqueness of just checks the membership_id and role_id
fields.

It looks to me as though running as a RailsStory is causing the roles
records to be deleted before the scenario runs, but after the class
cached them.              s

Any ideas?

-- 
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to