[rspec-users] Another attempt for a succinct model validation DSL

nicholas a. evans nick at ekenosen.net
Fri Jun 1 00:06:09 EDT 2007

On 5/31/07, David Chelimsky <dchelimsky at gmail.com> wrote:
> On 5/31/07, nicholas a. evans <nick at ekenosen.net> wrote:
> > So here's my latest thought-experiment: http://pastie.caboo.se/66478
> > And also, a simpler multi-field version: http://pastie.caboo.se/66510

> I took at a shot at something that feels more like the rest of RSpec.
> It's admittedly more verbose than your examples, but I also think it
> speaks well and aligns with everything else in rspec. WDYT?
> http://pastie.caboo.se/66679

Oh!  I like it a *lot*.  Yes, it's more verbose on each example than I
prefer (8 characters plus two indentation levels plus the length of
the block variable).  But it does read more fluidly, and in many ways
it looks much simpler.  My "default_params" is simply your input to
"given".  My "columns" or "field_to_validate", is simply the
argument(s) to "it_should_require_that".  Likewise, "as" reads more
naturally than :msg (although I had been thinking of using
"with_message", which feels a bit more readable).

I have only one real objection/concern:

"given User.new" would pass in an object that would get reused for
each accept/reject line in the block.  I prefer the approach of
creating a new/fresh object for each example.  Perhaps it could accept
a Proc or a symbol representing a method name, searching first for an
instance method in the behavior, and then a class method on the class
being described.

"given :new" would get a different object from User.new before each example.
"given User.new" would reuse the same new User object for all of the examples.
"given :user_with_full_access" would call "user_with_full_access"
(defined in that behavior or on User) before each example.
"given user_with_full_access" would reuse the same object for all examples.

What do you think?  Is there a better way?

A few more thoughts and questions:

How about "it_should_validate_that" rather than
"it_should_require_that"?  That feels more explicit and to-the-point,
to me.  At that point, the ":behavior_type => :validation" becomes
redundant.  "it_should_validate_that" could simply be available to all
model behaviors.

What else could "given" be used for?  It seems like this could become
a pattern/approach that could extend beyond model validations...  Have
you thought about using it for anything else yet?

How could we specify a *default* rejection message (or error count,
etc)?  Does "user.default_rejection_message = /the message/" (and so
on) look reasonable?

I did like that the each example/assertion got its own entry in the
specdoc with my approach...  Do you think that it is best to sum it up
to the rule?  Either way, I presume that a failure should still run
all of examples to give a full report, rather than stop at the first
wrong one.

My approach assumed that if you were only working with one field, we
should only check for errors on that one field (it's okay if the
object is otherwise invalid).  But if you are working with multiple
fields, you should check to see if the entire object is valid, and
check against all error messages.  Do you think that is a safe and
reasonable convention?

Thanks for your thoughts... and your improvements on my thoughts.  :-)


More information about the rspec-users mailing list