[rspec-users] Story Runner, autoincrementing

Pat Maddox pergesu at gmail.com
Sun Sep 23 02:16:31 EDT 2007


On 9/22/07, Andrew WC Brown <omen.king at gmail.com> wrote:
> I've written a story and I run into a snag.
> I've written the create_forum method and told it to set the id to 1
> but when it creates the forum the id is autoincremented.
> My forums table is empty but the id keeps incrementing the newest record on
> creation.
> When I run the story it comes out as something like 59 which fails my story
> because I'm asking it to look at /forums/1
>
> I thought of using my named routes instead of specifying the path as a
> string.
> That worked up until the point when I reached:
>
> When "creating a new topic titled", "Nicks Mom" do |title|
>   post topics(@forum, ??? ), :topic => { :title => title, :body => "She is
> teh hotZ!" }
> end
>
> The problem was since its a nested routed I couldn't complete the post
> request without specifying the topic_id.
> But since the topic hasn't been created yet their is no way (that I know of)
> to pass the id since I don't know what it will be.
>
> I would think the better practice is to state the paths as strings instead
> of using the nested routes.
>
>
>
> require File.join(File.dirname(__FILE__), "helper")
>
> Story "User creates a new topic", %{
>     As a user
>     I want to create a new topic
>     So that I can dicuss Nick's Mom
>   }, :type => RailsStory do
>
>   Scenario "Successfully create a new topic in the 'General' forum" do
>
>     Given "a user named", "Jon" do |login|
>       @user = create_user login
>     end
>     Given "a forum named", "General" do |name|
>       @forum = create_forum name
>       puts @forum.id
>     end
>
>     And "user logged in successfully and was redirect to", "/" do |path|
>       post "/session/create", :login => "Jon", :password => "your_momma"
>       response.should redirect_to("/")
>     end
>
>     And "user is looking at", "/forums/1" do |path|
>       get path
>       response.should be_success
>     end
>
>     When "creating a new topic titled", "Nicks Mom" do |title|
>       post "/forums/1/topics/1/create", :topic => { :id => 1, :title =>
> title, :body => "She is teh hotZ!" }
>     end
>
>     Then "user should be redirected to", "/forums/1/topics/1" do |path|
>       get path
>       response.should be_success
>     end
>
>   end
>
>   Scenario "Failed creating a new topic due to blank fields" do; end
>   Scenario "Sticky a new thread" do; end
>   Scenario "Annoucment as a new thread" do; end
> end
>
> def create_user(login)
>   user = User.create!(
>     :login => login,
>     :email => " your at momma.com",
>     :password => "your_momma",
>     :password_confirmation => "your_momma",
>     :display_name => "Jon")
>   user
>  end
>
> def create_forum(name)
>   forum = Forum.create!(
>     :id => 1,
>     :name => name,
>     :description => "Everything from the latest gossip to the coolest
> youtube videos.")
>   forum
> end
>
>
> How do I stop the incrementing?
>
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>

You don't stop the incrementing (at least afaik).  That's a db thing.
You'd have to drop and recreate the db between runs.  The good news is
that the instance variables that you created are available everywhere
within the Scenario.

I wrote a story that is very similar to yours.  I only rebuilt the
bits that were relevant to the test:

require File.join(File.dirname(__FILE__), "helper")

Story "User creates a new topic", %{
    As a user
    I want to create a new topic
    So that I can dicuss Nick's Mom
  }, :type => RailsStory do

  Scenario "Successfully create a new topic in the 'General' forum" do

    Given "a user named", "Jon" do |login|
      @user = create_user login
    end
    Given "a forum named", "General" do |name|
      @forum = create_forum name
    end

    When "creating a new topic titled", "Nicks Mom" do |title|
      post_via_redirect "/forums/#{@forum.to_param}/topics", :topic =>
{ :title => title }
    end

    Then "user should see", "topics/show" do |template|
      response.should render_template(template)
    end

    And "page should show", "Nicks Mom" do |title|
      response.should have_text(/Title: #{title}/)
    end
  end
end

def create_user(name)
  user = User.create! :name => name
  user
end

def create_forum(name)
  forum = Forum.create!(
    :name => name,
    :description => "Everything from the latest gossip to the coolest
youtube videos.")
  forum
end

You can see I did a couple things differently:

* Use the forum ID in the url
* Use post_via_redirect
* Specify the template and some text that should be shown

The first item solves the problem of the autoincrementing ID, at least
for the forum_id part of the URL.

Your story is actually a bit broken, imo.  You POST the new topic and
then GET a url.  But how does the user know what that URL is?  More
likely you're redirecting them to the right URL.  You should use
post_via_redirect because the user makes a post and then follows the
redirect.

You'll have a controller spec that specifies what the redirect url
should be.  Brief example

it "should redirect to the topic's show page" do
  do_post
  response.should redirect_to(topic_url(@mock_topic))
end

The story allows you to specify the external behavior, which is that
the user POSTs to a url and then gets redirected to a page showing the
topic.  The controller spec lets you specify the internal behavior,
which includes the correct redirect url.

hth

Pat


More information about the rspec-users mailing list