nicholas a. evans
2007-May-31 20:34 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 5/28/07, David Chelimsky <dchelimsky at gmail.com> wrote:> The behaviour you''re trying to describe is that the User should > require that passwords bear certain qualities - in this case a length > between 5 and 40. So you need to ask yourself how the User should > behave when this requirement is violated, and then specify that it > behaves that way. > > Here''s how I might handle this: > > describe User do > it "should reject a password of length 4" do > User.create(:password => "1234").should have(1).error_on(:password) > end > it "should accept a password of length 5" do > User.create(:password => "12345").should have(0).errors_on(:password) > end... That''s pretty much exactly the pattern that I''ve been doing for specing my model validations... I like it; I think it is the simplest, most useful way of going about validations. But it can get a bit wordy, and the code duplication starts to become painful. I flooded the lists a few weeks back with some ideas for a nicer DSL for model validations, but I never actually followed up with a working implementation, because they all still felt a bit clunky to me... plus I haven''t had any free weekends, nor have I been doing much with model validations at work recently. For some reason, looking at your example here made me want to try for a better DSL again. I like your use of the words "accept" and "reject" (versus "valid"/"invalid"), because they get right to the core of what actually happens, i.e. what the behavior is. And I like the emphasis on the examples (especially since I often think of TDD/BDD as EDD, Example Driven Design). So here''s my latest thought-experiment: http://pastie.caboo.se/66478 And also, a simpler multi-field version: http://pastie.caboo.se/66510 Notice how checking all three sides of each boundary is so simple and succinct that there is almost no excuse not to do so. Also, after noticing how similar the multi-field validation is to a fit-table or some of Brian Marick and zenspider''s recent blog entries, I decided that further simplification was necessary/desirable. :-) Consider this my request for comments on the syntax. Hopefully I''ll have time to put my code where my mouth is and create a rspec extension to do this in the near future. :-) -- Nick
David Chelimsky
2007-May-31 21:56 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 5/31/07, nicholas a. evans <nick at ekenosen.net> wrote:> On 5/28/07, David Chelimsky <dchelimsky at gmail.com> wrote: > > The behaviour you''re trying to describe is that the User should > > require that passwords bear certain qualities - in this case a length > > between 5 and 40. So you need to ask yourself how the User should > > behave when this requirement is violated, and then specify that it > > behaves that way. > > > > Here''s how I might handle this: > > > > describe User do > > it "should reject a password of length 4" do > > User.create(:password => "1234").should have(1).error_on(:password) > > end > > it "should accept a password of length 5" do > > User.create(:password => "12345").should have(0).errors_on(:password) > > end > ... > > That''s pretty much exactly the pattern that I''ve been doing for > specing my model validations... I like it; I think it is the > simplest, most useful way of going about validations. But it can get > a bit wordy, and the code duplication starts to become painful. > > I flooded the lists a few weeks back with some ideas for a nicer DSL > for model validations, but I never actually followed up with a working > implementation, because they all still felt a bit clunky to me... plus > I haven''t had any free weekends, nor have I been doing much with model > validations at work recently. > > For some reason, looking at your example here made me want to try for > a better DSL again. I like your use of the words "accept" and > "reject" (versus "valid"/"invalid"), because they get right to the > core of what actually happens, i.e. what the behavior is. And I like > the emphasis on the examples (especially since I often think of > TDD/BDD as EDD, Example Driven Design). > > So here''s my latest thought-experiment: http://pastie.caboo.se/66478 > And also, a simpler multi-field version: http://pastie.caboo.se/66510 > > Notice how checking all three sides of each boundary is so simple and > succinct that there is almost no excuse not to do so. Also, after > noticing how similar the multi-field validation is to a fit-table or > some of Brian Marick and zenspider''s recent blog entries, I decided > that further simplification was necessary/desirable. :-) > > Consider this my request for comments on the syntax. Hopefully I''ll > have time to put my code where my mouth is and create a rspec > extension to do this in the near future. :-)Really interesting stuff. Thanks! 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 David>> -- > Nick > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Fischer, Daniel
2007-Jun-01 02:10 UTC
[rspec-users] Another attempt for a succinct model validation DSL
I really like the second one! On 5/31/07, David Chelimsky <dchelimsky at gmail.com> wrote:> On 5/31/07, nicholas a. evans <nick at ekenosen.net> wrote: > > On 5/28/07, David Chelimsky <dchelimsky at gmail.com> wrote: > > > The behaviour you''re trying to describe is that the User should > > > require that passwords bear certain qualities - in this case a length > > > between 5 and 40. So you need to ask yourself how the User should > > > behave when this requirement is violated, and then specify that it > > > behaves that way. > > > > > > Here''s how I might handle this: > > > > > > describe User do > > > it "should reject a password of length 4" do > > > User.create(:password => "1234").should have(1).error_on(:password) > > > end > > > it "should accept a password of length 5" do > > > User.create(:password => "12345").should have(0).errors_on(:password) > > > end > > ... > > > > That''s pretty much exactly the pattern that I''ve been doing for > > specing my model validations... I like it; I think it is the > > simplest, most useful way of going about validations. But it can get > > a bit wordy, and the code duplication starts to become painful. > > > > I flooded the lists a few weeks back with some ideas for a nicer DSL > > for model validations, but I never actually followed up with a working > > implementation, because they all still felt a bit clunky to me... plus > > I haven''t had any free weekends, nor have I been doing much with model > > validations at work recently. > > > > For some reason, looking at your example here made me want to try for > > a better DSL again. I like your use of the words "accept" and > > "reject" (versus "valid"/"invalid"), because they get right to the > > core of what actually happens, i.e. what the behavior is. And I like > > the emphasis on the examples (especially since I often think of > > TDD/BDD as EDD, Example Driven Design). > > > > So here''s my latest thought-experiment: http://pastie.caboo.se/66478 > > And also, a simpler multi-field version: http://pastie.caboo.se/66510 > > > > Notice how checking all three sides of each boundary is so simple and > > succinct that there is almost no excuse not to do so. Also, after > > noticing how similar the multi-field validation is to a fit-table or > > some of Brian Marick and zenspider''s recent blog entries, I decided > > that further simplification was necessary/desirable. :-) > > > > Consider this my request for comments on the syntax. Hopefully I''ll > > have time to put my code where my mouth is and create a rspec > > extension to do this in the near future. :-) > > Really interesting stuff. Thanks! > > 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 > > David > > > > > > > -- > > Nick > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-- -Daniel Fischer http://danielfischer.com - Geek Blog http://abigfisch.com - Portfolio http://writersbeat.com - Writing Community
nicholas a. evans
2007-Jun-01 04:06 UTC
[rspec-users] Another attempt for a succinct model validation DSL
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/66679Oh! 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. :-) -- Nick
David Chelimsky
2007-Jun-01 05:00 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/1/07, nicholas a. evans <nick at ekenosen.net> wrote:> 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?I put up a third version: http://pastie.caboo.se/66776 WDYT?> A few more thoughts and questions: > > How about "it_should_validate_that" rather than > "it_should_require_that"?"validate" is fine.> 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.Why not just stick it in a module and let the user decide where to make it available? If you, as a user of this extension, wanted it available to all model examples, you could do this: Spec::Runner.configure do |config| config.include(ModelValidations, :behaviour_type => :model) end> 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?Not yet. I was just bouncing off your proposal. Let''s see how this works in practice before we start creating conventions :)> How could we specify a *default* rejection message (or error count, > etc)? Does "user.default_rejection_message = /the message/" (and so > on) look reasonable?That seems like you''re telling the user to use a specific message rather than generally expecting it, which is what I *think* you mean. Am I missing it?> > 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.I think you can get all that. The #given method has a handle on the object before it yields to the block, the should_reject and should_accept methods can be configured to create examples at run time. Make sense?> > 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?This could get quite complicated. Which is probably why nobody has tackled this in a generic way yet - at least that I''ve seen.> > Thanks for your thoughts... and your improvements on my thoughts. :-)My pleasure. I''m looking forward to seeing how this turns out. Cheers, David> > -- > Nick > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
nicholas a. evans
2007-Jun-01 14:34 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/1/07, David Chelimsky <dchelimsky at gmail.com> wrote:> I put up a third version: http://pastie.caboo.se/66776I looks like you lost the ability to know which field was being validated, so I changed it back to it_should_validate_that :field, "satisfies rule"> Why not just stick it in a module and let the user decide where to > make it available?That makes sense.> Not yet. I was just bouncing off your proposal. Let''s see how this > works in practice before we start creating conventions :)Good point. :-)> That seems like you''re telling the user to use a specific message > rather than generally expecting it, which is what I *think* you mean. > Am I missing it?You''re right... I''ll worry about that feature later, then. :-)> I think you can get all that. The #given method has a handle on the > object before it yields to the block, the should_reject and > should_accept methods can be configured to create examples at run > time. Make sense?Yeah, but we''ve also added a string via "it_should_validate_that"... What would the specdoc look like? We don''t have a mechanism for nesting 3 levels deep, do we?> > 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? > > This could get quite complicated. Which is probably why nobody has > tackled this in a generic way yet - at least that I''ve seen.True... but it feels like we''re getting close to something that is very good and simple. It doesn''t need to solve 100% of the world''s validation needs... just 85% of my rails validation needs. For anything more complicated, I can always fall back on vanilla rspec (still pretty tasty!). For my tastes and intuition, I prefer that validation specs against a single field check only that single field''s validity, and validations specs against multiple fields check the model''s validity. But I would be fine if it were simplified to normally check only the fields under inspection, but could be easily changed to check for any errors on the object. Here are my next several attempts: Playing off of your approach and including a number of proposed specdoc outputs: http://pastie.caboo.se/66855 But here''s my current favorite approach: http://pastie.caboo.se/66862 -- Nick
nicholas a. evans
2007-Jun-01 15:11 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/1/07, nicholas a. evans <nick at ekenosen.net> wrote:> But here''s my current favorite approach: http://pastie.caboo.se/66862Ack! I had some silly/bad ruby syntax in that last pastie. Let''s try that again; now with improved (valid) ruby syntax! http://pastie.caboo.se/66896 -- Nick
Joseph Method
2007-Jun-01 16:17 UTC
[rspec-users] Another attempt for a succinct model validation DSL
What about ''this'' as a reserved name for what''s given? given { User.new } this.should_reject (nil) given { User.new(:name => ''Bob'' } this.should_reject(nil) On 6/1/07, nicholas a. evans <nick at ekenosen.net> wrote:> On 6/1/07, nicholas a. evans <nick at ekenosen.net> wrote: > > But here''s my current favorite approach: http://pastie.caboo.se/66862 > > Ack! I had some silly/bad ruby syntax in that last pastie. > > Let''s try that again; now with improved (valid) ruby syntax! > > http://pastie.caboo.se/66896 > > -- > Nick > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-- -J. Method
nicholas a. evans
2007-Jun-01 17:02 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/1/07, Joseph Method <tristil at gmail.com> wrote:> What about ''this'' as a reserved name for what''s given?I thought about trying something like that, and thus try to get back to the "normal" rspec syntax but it seems to me that "it" better fulfills that role. Here''s my thought on a syntax like that: http://pastie.caboo.se/66937 How close does that compare to what you were thinking of, Joseph? (I prefer to use "specify" rather than "it", when I''m using the generated example string.) Now that I look at it, I actually think this is a rather nice syntax. But it''s a lot more verbose than I''d like... perhaps "it_should_reject(foo)" could simply be shorthand for "specify { it.should reject(foo) }". This also makes it obvious how to override the generated example string. Thoughts? Is it an evil or difficult thing to repurpose "it" to my own dubious ends inside the examples? I really like the idea of "it" simply returning the result of the block that was previously passed to "given" -- Nick> given { User.new } > this.should_reject (nil) > > given { User.new(:name => ''Bob'' } > this.should_reject(nil)
Joseph Method
2007-Jun-01 17:19 UTC
[rspec-users] Another attempt for a succinct model validation DSL
Well, this is what I was thinking: http://pastie.caboo.se/66940> Thoughts?Honestly, the extra depth is a big turn-off for me.> Is it an evil or difficult thing to repurpose "it" to my > own dubious ends inside the examples? I really like the idea of "it" > simply returning the result of the block that was previously passed to > "given" > > -- > NickIt''s not evil, but I don''t know how difficult it is. If it''s not difficult at all, I don''t see why it can''t be it.should_validate :password do -- -J. Method
nicholas a. evans
2007-Jun-01 18:16 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/1/07, Joseph Method <tristil at gmail.com> wrote:> Well, this is what I was thinking: http://pastie.caboo.se/66940I think that I still prefer dedicating the entire behavior to validation of a particular field (that''s what I do in my current specs anyway, albeit with far more lines of code).> > Thoughts? > > Honestly, the extra depth is a big turn-off for me.Strongly agreed in that regard. 10 extra characters on the front (and two on the back), repeated over every example. The whole point of this is to clean up the syntactic noise to highlight the examples themselves. The reasons I see to use that approach: it matches *very* well with the standard rspec way of doing things. At that point, it''s really just the new given/it syntax, and a matcher that looks at some of the behavior options (to see which fields are being spec''d). And it gives an obvious interface for overriding/ignoring the generated example string. Likewise, it gives a nice syntax if I want to do some more advanced assertions on the model with that example. But I think I would use the shorthand version for 95% of my validation examples. And the shorthand could effectively generate the proposed longhand code.> > Is it an evil or difficult thing to repurpose "it" to my > > own dubious ends inside the examples? I really like the idea of "it" > > simply returning the result of the block that was previously passed to > > "given" > > It''s not evil, but I don''t know how difficult it is. If it''s not > difficult at all, I don''t see why it can''t be > > it.should_validate :password doI don''t think it would be right to have the behavior method "it" running double-duty (it is already used to create the examples). Also, I don''t really see much benefit of "it.should_validate" over "it_should_validate". But I do like the idea of the example method "it" getting the results of the "given", and that should be easy (I think). -- Nick
Joseph Method
2007-Jun-01 18:47 UTC
[rspec-users] Another attempt for a succinct model validation DSL
How about this? http://pastie.caboo.se/66977 The strategy is to check if the string argument is :validations (so this would become reserved). If it is, then include ModelValidations. ''it'' without the block returns an object that contains a should method. The block it opens is related to but different from the one that ''it'' opens. given doesn''t seem strictly necessary, since we know what''s being described, but it reads well and is explicit.> I think that I still prefer dedicating the entire behavior to > validation of a particular field (that''s what I do in my current specs > anyway, albeit with far more lines of code).I''m sure we won''t be able to agree on this, but it seems like overkill to me. What if in this proposal there was an option for :validation_of_password, etc.?> I don''t think it would be right to have the behavior method "it" > running double-duty (it is already used to create the examples). > Also, I don''t really see much benefit of "it.should_validate" over > "it_should_validate". But I do like the idea of the example method > "it" getting the results of the "given", and that should be easy (I > think).Yeah, what''s described here might be too evil. In its defense, though, the new 1.0 syntax seems to emphasize subject.should predicate over subject.should_predicate, which is what I''ve tried to preserve.> -- > Nick-- -J. Method
David Chelimsky
2007-Jun-01 22:01 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/1/07, Joseph Method <tristil at gmail.com> wrote:> How about this? > > http://pastie.caboo.se/66977 > > The strategy is to check if the string argument is :validations (so > this would become reserved). If it is, then include ModelValidations. > ''it'' without the block returns an object that contains a should > method. The block it opens is related to but different from the one > that ''it'' opens. > > given doesn''t seem strictly necessary, since we know what''s being > described, but it reads well and is explicit. > > > I think that I still prefer dedicating the entire behavior to > > validation of a particular field (that''s what I do in my current specs > > anyway, albeit with far more lines of code). > > I''m sure we won''t be able to agree on this, but it seems like overkill > to me. What if in this proposal there was an option for > :validation_of_password, etc.? > > > I don''t think it would be right to have the behavior method "it" > > running double-duty (it is already used to create the examples). > > Also, I don''t really see much benefit of "it.should_validate" over > > "it_should_validate". But I do like the idea of the example method > > "it" getting the results of the "given", and that should be easy (I > > think). > > Yeah, what''s described here might be too evil. In its defense, though, > the new 1.0 syntax seems to emphasize subject.should predicate over > subject.should_predicate, which is what I''ve tried to preserve.Well now we''re getting much simpler. Instead of a whole new structure, why not just use a custom matcher? http://pastie.caboo.se/67069> > > -- > > Nick > > -- > -J. Method > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
aslak hellesoy
2007-Jun-01 22:59 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/2/07, David Chelimsky <dchelimsky at gmail.com> wrote:> On 6/1/07, Joseph Method <tristil at gmail.com> wrote: > > How about this? > > > > http://pastie.caboo.se/66977 > > > > The strategy is to check if the string argument is :validations (so > > this would become reserved). If it is, then include ModelValidations. > > ''it'' without the block returns an object that contains a should > > method. The block it opens is related to but different from the one > > that ''it'' opens. > > > > given doesn''t seem strictly necessary, since we know what''s being > > described, but it reads well and is explicit. > > > > > I think that I still prefer dedicating the entire behavior to > > > validation of a particular field (that''s what I do in my current specs > > > anyway, albeit with far more lines of code). > > > > I''m sure we won''t be able to agree on this, but it seems like overkill > > to me. What if in this proposal there was an option for > > :validation_of_password, etc.? > > > > > I don''t think it would be right to have the behavior method "it" > > > running double-duty (it is already used to create the examples). > > > Also, I don''t really see much benefit of "it.should_validate" over > > > "it_should_validate". But I do like the idea of the example method > > > "it" getting the results of the "given", and that should be easy (I > > > think). > > > > Yeah, what''s described here might be too evil. In its defense, though, > > the new 1.0 syntax seems to emphasize subject.should predicate over > > subject.should_predicate, which is what I''ve tried to preserve. > > Well now we''re getting much simpler. Instead of a whole new structure, > why not just use a custom matcher? > > http://pastie.caboo.se/67069 >Brilliant! Aslak> > > > > -- > > > Nick > > > > -- > > -J. Method > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Luis Lavena
2007-Jun-01 23:40 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/1/07, aslak hellesoy <aslak.hellesoy at gmail.com> wrote:> > On 6/1/07, Joseph Method <tristil at gmail.com> wrote: > > > > Well now we''re getting much simpler. Instead of a whole new structure, > > why not just use a custom matcher? > > > > http://pastie.caboo.se/67069 > > > > Brilliant! >I agree with aslak on this! Is descriptive, but not too verbose, is simple but not too cryptic. Translation: Looks good, are you willing to share it? ;-) (David and Aslak, I didn''t found a example on how to implemente a custom matcher like Jospeh did, guess I missed a lot of RDocs :-P -- Luis Lavena Multimedia systems - Leaders are made, they are not born. They are made by hard effort, which is the price which all of us must pay to achieve any goal that is worthwhile. Vince Lombardi
David Chelimsky
2007-Jun-01 23:48 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/1/07, Luis Lavena <luislavena at gmail.com> wrote:> On 6/1/07, aslak hellesoy <aslak.hellesoy at gmail.com> wrote: > > > On 6/1/07, Joseph Method <tristil at gmail.com> wrote: > > > > > > Well now we''re getting much simpler. Instead of a whole new structure, > > > why not just use a custom matcher? > > > > > > http://pastie.caboo.se/67069 > > > > > > > Brilliant! > > > > I agree with aslak on this! > > Is descriptive, but not too verbose, is simple but not too cryptic. > > Translation: Looks good, are you willing to share it? ;-) > > (David and Aslak, I didn''t found a example on how to implemente a > custom matcher like Jospeh did, guess I missed a lot of RDocs :-PCheck this out - I think it''s what you''re looking for. http://blog.davidchelimsky.net/articles/2007/02/18/custom-expectation-matchers Cheers, David> > -- > Luis Lavena > Multimedia systems > - > Leaders are made, they are not born. They are made by hard effort, > which is the price which all of us must pay to achieve any goal that > is worthwhile. > Vince Lombardi > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Luis Lavena
2007-Jun-01 23:54 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/1/07, David Chelimsky <dchelimsky at gmail.com> wrote: [...]> > > > (David and Aslak, I didn''t found a example on how to implemente a > > custom matcher like Jospeh did, guess I missed a lot of RDocs :-P > > Check this out - I think it''s what you''re looking for. > > http://blog.davidchelimsky.net/articles/2007/02/18/custom-expectation-matchers >Thanks David, but I''m already a subscriber of your blog ;-) What I really meant to say is the .as(:attribute).because("message") part of the custom matcher I didn''t fully understand :-P Are examples of that in the repository? -- Luis Lavena Multimedia systems - Leaders are made, they are not born. They are made by hard effort, which is the price which all of us must pay to achieve any goal that is worthwhile. Vince Lombardi
David Chelimsky
2007-Jun-02 04:19 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/1/07, Luis Lavena <luislavena at gmail.com> wrote:> On 6/1/07, David Chelimsky <dchelimsky at gmail.com> wrote: > [...] > > > > > > (David and Aslak, I didn''t found a example on how to implemente a > > > custom matcher like Jospeh did, guess I missed a lot of RDocs :-P > > > > Check this out - I think it''s what you''re looking for. > > > > http://blog.davidchelimsky.net/articles/2007/02/18/custom-expectation-matchers > > > > Thanks David, but I''m already a subscriber of your blog ;-) > > What I really meant to say is the .as(:attribute).because("message") > part of the custom matcher I didn''t fully understand :-P > > Are examples of that in the repository?Take a look at lib/spec/matchers/change.rb. That should give you some direction.> > -- > Luis Lavena > Multimedia systems > - > Leaders are made, they are not born. They are made by hard effort, > which is the price which all of us must pay to achieve any goal that > is worthwhile. > Vince Lombardi > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
nicholas a. evans
2007-Jun-02 14:32 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/1/07, David Chelimsky <dchelimsky at gmail.com> wrote:> Well now we''re getting much simpler. Instead of a whole new structure, > why not just use a custom matcher? > > http://pastie.caboo.se/67069I agree, simpler is better. I intend to start off with just the matcher, and then move towards a shortcut syntax. My nitpick with only doing a matcher and not doing some extras as well: it''s still too verbose for my taste. For example, I''ll be saying "as(:foo)" for every single example within a behavior, or wrapping it inside some examples_array.each loops will feel a bit clunky. The whole point was to cut away as much of the noise as possible, and focus only on the examples (and occasionally, the error messages). At any rate, I just put together my first draft implementation (developed spec-first). It still doesn''t check the error messages yet, and it''s only handling single fields at the moment, but I''ll do those after I get home from the market. After that I''ll figure out how to get it working with my desired "shortcut" syntax. Then I''ll package it up all nicely for anyone to use... it''s all in one file at the moment, so if you are looking to see the syntax that it enables, you''ll have to scroll down to line 109. ;-) http://pastie.caboo.se/67222 I''ve included the output from "spec -f s" in the pastie. -- Nick
nicholas a. evans
2007-Jun-04 02:52 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/2/07, nicholas a. evans <nick at ekenosen.net> wrote:> At any rate, I just put together my first draft implementation > (developed spec-first). It still doesn''t check the error messages > yet, and it''s only handling single fields at the moment, but I''ll do > those after I get home from the market. After that I''ll figure out > how to get it working with my desired "shortcut" syntax.So I haven''t gotten around to my preferred shortcut syntax yet, but I did add support to check for error messages and handle multiple fields, so it should be quite usable now. I took the approach that when specifying single field validations it only checks for errors on that field, but when specifying multi-field validations it checks for any errors on the object. That felt like simplest and least surprising solution to me. My specs assume that you can use sqlite3 (to do an in-memory DB). http://svn.ekenosen.net/public/rspec_validation_matcher/ http://pastie.caboo.se/67509 shows what it currently can do, as well as my current thoughts on how I would *really* like to be doing this. I''m eager to hear any comments on it. :-) -- Nick
David Chelimsky
2007-Jun-04 04:36 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/3/07, nicholas a. evans <nick at ekenosen.net> wrote:> On 6/2/07, nicholas a. evans <nick at ekenosen.net> wrote: > > At any rate, I just put together my first draft implementation > > (developed spec-first). It still doesn''t check the error messages > > yet, and it''s only handling single fields at the moment, but I''ll do > > those after I get home from the market. After that I''ll figure out > > how to get it working with my desired "shortcut" syntax. > > So I haven''t gotten around to my preferred shortcut syntax yet, but I > did add support to check for error messages and handle multiple > fields, so it should be quite usable now. I took the approach that > when specifying single field validations it only checks for errors on > that field, but when specifying multi-field validations it checks for > any errors on the object. That felt like simplest and least > surprising solution to me. My specs assume that you can use sqlite3 > (to do an in-memory DB). > > http://svn.ekenosen.net/public/rspec_validation_matcher/ > > http://pastie.caboo.se/67509 shows what it currently can do, as well > as my current thoughts on how I would *really* like to be doing this. > I''m eager to hear any comments on it. :-)Personally, I think @person.should accept("Danny", "Elfman") ;)> > -- > Nick > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
nicholas a. evans
2007-Jun-04 10:50 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/4/07, David Chelimsky <dchelimsky at gmail.com> wrote:> Personally, I think @person.should accept("Danny", "Elfman") > > ;)I totally agree, but arbitrary examples aren''t my forte. Perhaps I should have stuck with "foo bar", but I had Oingo Boingo on the brain. ;-) -- Nick
David Chelimsky
2007-Jun-04 11:19 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/4/07, nicholas a. evans <nick at ekenosen.net> wrote:> On 6/4/07, David Chelimsky <dchelimsky at gmail.com> wrote: > > Personally, I think @person.should accept("Danny", "Elfman") > > > > ;) > > I totally agree, but arbitrary examples aren''t my forte. Perhaps I > should have stuck with "foo bar", but I had Oingo Boingo on the brain. > ;-)I''m with you re: arbitrary examples. I always have to imagine that "foo" is the "foo" bird from an old joke and "bar" is the local watering hole in order to understand such examples. I''ve you''re going to pick things to reject, maybe they should be stuff we can all agree on: @developer.should reject("Service", "Locator") WDYT?> > -- > Nick > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Martin DeMello
2007-Jun-04 13:05 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/1/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 > > Notice how checking all three sides of each boundary is so simple and > succinct that there is almost no excuse not to do so. Also, after > noticing how similar the multi-field validation is to a fit-table or > some of Brian Marick and zenspider''s recent blog entries, I decided > that further simplification was necessary/desirable. :-)I really like the second one, far more than any of the proposed alternatives (I think succinctness beats out rspecishness in this case). I''d propose one modification: http://pastie.caboo.se/67596 What say? martin
Joseph Method
2007-Jun-04 16:13 UTC
[rspec-users] Another attempt for a succinct model validation DSL
I think Nicholas has moved on to a different approach, but I agree that this approach deserves looking at again, in part because it avoids the opinion about whether a single validation should be a context or a specification. But lo, rspecishness can be preserved: http://pastie.caboo.se/67649 IMO, not doing this makes it look declarative and unit/test-y. It''s the difference between obey!(:me) and you.should obey(:me)> I really like the second one, far more than any of the proposed > alternatives (I think succinctness beats out rspecishness in this > case). I''d propose one modification: > > http://pastie.caboo.se/67596 > > What say? > > martin-- -J. Method
nicholas a. evans
2007-Jun-04 18:03 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/4/07, Joseph Method <tristil at gmail.com> wrote:> I think Nicholas has moved on to a different approach, but I agree > that this approach deserves looking at again,Not yet... I''m just jumping about from one to the other, trying each on for size. ;-) After all of this typing, I wanted to get *something* implemented though. And going with a normal rspec matcher is really the correct starting point. It''s useful even if/when we have an additional shortcut syntax, it should be used to implement the shortcut syntax, and there seemed to be some level of consensus finally settling on what it might look like. I wrote this up several hours ago, but never posted it: http://pastie.caboo.se/67605 It looks a lot like your example (and Martin''s, which prompted me to write it). I''m still avoiding the dot and space notation, because that relies on code that works in the example binding, but I don''t want to mess with in the behavior binding. I''m also avoiding sending a variable into the block because it feels to me like extra verbosity with no extra readability or useful flexibility. I haven''t decided whether I like "should_accept" more than "it_should_accept"... the saved three characters are probably not be worth the delta from the rspec way.> in part because it > avoids the opinion about whether a single validation should be a > context or a specification.That is a good point.> But lo, rspecishness can be preserved: > > http://pastie.caboo.se/67649 > > IMO, not doing this makes it look declarative and unit/test-y. It''s > the difference between > > obey!(:me) > > and > > you.should obey(:me)I strongly agree. I will gladly sacrifice a little bit of concision in order to stay in the rspec readability/behavior/specification paradigm. But I do want to (as much as is possible) remain in The Rspec Way with as little verbosity and noise distracting from the examples as is reasonable. David, Aslak, oh wise guardians and mentors of The Rspec Way, what do you think of my latest pastie? http://pastie.caboo.se/67605 :-) -- Nick
Joseph Method
2007-Jun-04 19:37 UTC
[rspec-users] Another attempt for a succinct model validation DSL
This looks right. One thing: I think validation_for inserts behaviors into the example. I mean, that''s how I think it should be implemented. The question is, how many are there in the first example? How about 3? That is: - Person validates :firstname (not nil, "foo" okay, not "bar") - Person validates :firstname should reject "" with ''can''t be blank'' message - Person "should reject a super long firstname" The .because("should reject a super long firstname") syntax in my example would be equivalent to the third example.> I strongly agree. I will gladly sacrifice a little bit of concision > in order to stay in the rspec readability/behavior/specification > paradigm. But I do want to (as much as is possible) remain in The > Rspec Way with as little verbosity and noise distracting from the > examples as is reasonable. David, Aslak, oh wise guardians and > mentors of The Rspec Way, what do you think of my latest pastie? > http://pastie.caboo.se/67605 :-) > > -- > Nick-- -J. Method
nicholas a. evans
2007-Jun-04 22:45 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/4/07, Joseph Method <tristil at gmail.com> wrote:> This looks right. One thing: I think validation_for inserts behaviors > into the example. I mean, that''s how I think it should be implemented. > The question is, how many are there in the first example? How about 3? > That is: > > - Person validates :firstname (not nil, "foo" okay, not "bar") > - Person validates :firstname should reject "" with ''can''t be blank'' message > - Person "should reject a super long firstname"As I intended it each "it_should_reject" or "it_should_accept" generates a new example (and returns the matcher used in that example, so that the matcher can be modified via "with", etc). If you want to have multiple expectations per example string, then you are free to do so, using the normal rspec matchers. For example: validation_for(:firstname) do it "should validate :firstname (not nil, "foo" okay, not "bar")" do @it.should reject nil @it.should accept "foo" @it.should reject "bar" end end I *strongly* prefer the one assertion/expectation per test/spec/example style, so I really don''t intend to ever do that or have need for something to simplify it. And I recommend against it. Also, I believe that the generated spec strings should be simpler and smaller when using this syntax. I don''t need to or want to mention which fields are being validated on each line (I can do that in the behavior string if necessary). For example, http://pastie.caboo.se/67605 should generate the following specdoc: Person firstname - should reject nil - should reject "" with "can''t be blank" - should accept "foo" - should accept "bar" - should reject a super long firstname Person validation to ensure that Oingo Boingo isn''t used - should accept "Nicholas", "Evans" - should accept "David", "Chelimsky" - should reject "Oingo", "Boingo" - should reject "Danny", "Elfman" FWIW, these names are rejected out of *respect*. Our humble Person model is not deserving of them. They are represented with the MusicalGenius model. ;-)> The .because("should reject a super long firstname") syntax in my > example would be equivalent to the third example.My thought: I don''t like the "because" syntax as you stated it above because it goes outside of the rspec syntax, but it is actually a character longer than doing it the rspec way: it "should fooooo" { @it.should reject(foo) } it_should_reject(foo).because("should fooooo") We might use it instead to append an explanation to the generated example string: ''should reject foo with "bar" because blatz''. But then I have to wonder, why not just have a more descriptive error message that could do the job? If your error message isn''t enough to make sense to your developers and analysts reading the specs, then it must be *really* confusing to the users! So consider me opposed to the "because" syntax. But if you want it, it should be *very* easy for you to add. ;-) -- Nick
David Chelimsky
2007-Jun-04 22:48 UTC
[rspec-users] Another attempt for a succinct model validation DSL
On 6/4/07, nicholas a. evans <nick at ekenosen.net> wrote:> Person validation to ensure that Oingo Boingo isn''t used > - should accept "Nicholas", "Evans" > - should accept "David", "Chelimsky" > - should reject "Oingo", "Boingo" > - should reject "Danny", "Elfman" > > FWIW, these names are rejected out of *respect*. Our humble Person > model is not deserving of them. They are represented with the > MusicalGenius model. ;-)Hmmmm. Genius, perhaps not, but musical I am. Is there a model somewhere between humble Person and MusicalGenius?