[rspec-users] Possible improvements to routing spec API

Wincent Colaiuta win at wincent.com
Wed Jul 7 08:39:05 EDT 2010

El 07/07/2010, a las 13:29, David Chelimsky escribió:

> Seems as though this format has been abandoned in this conversation:
>  it { should route(get "/issues/new").to("issues#new") }
>  it { should generate("/issues/new").from("issues#new") }
> I think that verbiage is concise and intention revealing, and keeps the path on the left and the details on the right.

True, but it also looks like it might be a little painful to implement. Seeing as you propose a little further down that we should also be able to do stuff like:

  it { should_not route(get "/issues/new") }

That means that "route" needs to be (or return) a matcher that also, optionally, responds to the "to" message and returns another matcher.

And "generate" needs to return a proxy that responds to "from" and returns the real matcher, but itself raises an exception if the user mistakenly uses it without chaining the "from" onto it.

Seems fairly magical compared to what we have right now, or what I proposed earlier on.

> Supported variants would be:
>  it { should route(:get => "/issues/new") ... # explicit hash for method/path
>  it { should route("/issues/new")...  # defaults to get
>  it { should ...to(:controller => "issues", :action => "new") } # explicit hash for params
> The negative version would be:
>  it { should_not route(get "/issues/new") }
> We could alias route() with recognize() to get:
>  it { should_not recognize(get "/issues/new") }

Sounds sensible.

> We still need to consider output. For example:
>  it { should route("/issues/37").to("issues#show", :id => 37) }
> I think in this case we _might_ be able to figure out that 37 is the value of :id and output
>  should route "/issues/:id" to "issues#show"
> Not sure if that'd be asking for trouble, but it seems feasible/reasonable.

I don't think it's worth it, to be honest. It would add a lot of complexity just to save some characters in the spec output. (Saving characters when _writing_ the specs seems more important.) And I think it's throwing away information, because the user reading the spec now has to mentally unpack the ":id" parameter, but doesn't actually see it. Multiple examples with different :ids in them are now all going to look the same. And what if the user has complex routes with requirements and regexp formats and stuff on them? Won't that be a little hard to handle?

> In terms of the more verbose format for custom messages, we could add a router() method for sugar:
>  it "routes /issues/new to issues#new" do
>    router.should route("/issues/new").to("issues#new") }
>  end

Yeah, adding router() is a good idea.

> And we still need the bi-directional version. I'm really at a loss on this one.

Perhaps something with/like the "have_routing" that Trevor suggested earlier? Possibly:

  it { should have_routing('/issues/new').for('issues#new') }

I've pasted a comparison of the two proposals in their current forms here so we can get a side-by-side (well, above/below) look at them:


Still not convinced about the bi-directional language, though (used "have_routing" in both flavors). If anyone can come up with better language I'll update the comparison.

For my taste, the first one reads nicer for most of the specs, but I like the "router.should_not recognize('foo')" syntax, at least for the GET case. I like it less for the non-GET case, though, where we have to nest another method call (ie. "router.should_not recognize(put '/issues/123')".


More information about the rspec-users mailing list