Does RSpec automatically call #valid? on ActiveRecord models? For instance, when this example is run: it ''should reject a nil value'' do @form = TimeShiftForm.new :file => nil puts "@form.errors.count = <<#{@form.errors.count}>>" @form.should have(1).error_on :file puts "@form.errors.count = <<#{@form.errors.count}>>" end This is printed: @form.errors.count = <<0>> @form.errors.count = <<1>> However, I never called @form.valid? , which leads me to believe that RSpec called it for me. If RSpec does in fact call #valid? automatically, should we refrain from manually calling #valid? ? -Nick
On Thu, Feb 12, 2009 at 11:03 AM, Nick Hoffman <nick at deadorange.com> wrote:> Does RSpec automatically call #valid? on ActiveRecord models? > > For instance, when this example is run: > > it ''should reject a nil value'' do > @form = TimeShiftForm.new :file => nil > > puts "@form.errors.count = <<#{@form.errors.count}>>" > @form.should have(1).error_on :file > puts "@form.errors.count = <<#{@form.errors.count}>>" > end > > This is printed: > @form.errors.count = <<0>> > @form.errors.count = <<1>> > > However, I never called @form.valid? , which leads me to believe that RSpec > called it for me. > > If RSpec does in fact call #valid? automatically, should we refrain from > manually calling #valid? ?RSpec doesn''t call #valid? automatically in all cases...but if you look at the source for error(s)_on in spec/rails/extensions/active_record/base.rb you''ll see that it does call #valid? automatically. Pat
On Feb 12, 2009, at 1:03 PM, Nick Hoffman <nick at deadorange.com> wrote:> Does RSpec automatically call #valid? on ActiveRecord models? > > For instance, when this example is run: > > it ''should reject a nil value'' do > @form = TimeShiftForm.new :file => nil > > puts "@form.errors.count = <<#{@form.errors.count}>>" > @form.should have(1).error_on :fileThis matcher, have(1).error_on, does call #valid.> > puts "@form.errors.count = <<#{@form.errors.count}>>" > end > > This is printed: > @form.errors.count = <<0>> > @form.errors.count = <<1>> > > However, I never called @form.valid? , which leads me to believe > that RSpec called it for me.In this case, yes, because the matcher needs that.> If RSpec does in fact call #valid? automatically, should we refrain > from manually calling #valid?The fact that you are asking this shows that we''re violating the principle of least surprise. We could make it so it doesn''t validate, but that would pit the onus on users to validate explicitly (not to mention the upgrade burden). Thoughts? David> > -Nick > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
On Thu, Feb 12, 2009 at 11:59 AM, David Chelimsky <dchelimsky at gmail.com> wrote:> On Feb 12, 2009, at 1:03 PM, Nick Hoffman <nick at deadorange.com> wrote: > >> Does RSpec automatically call #valid? on ActiveRecord models? >> >> For instance, when this example is run: >> >> it ''should reject a nil value'' do >> @form = TimeShiftForm.new :file => nil >> >> puts "@form.errors.count = <<#{@form.errors.count}>>" >> @form.should have(1).error_on :file > > This matcher, have(1).error_on, does call #valid. > >> >> puts "@form.errors.count = <<#{@form.errors.count}>>" >> end >> >> This is printed: >> @form.errors.count = <<0>> >> @form.errors.count = <<1>> >> >> However, I never called @form.valid? , which leads me to believe that >> RSpec called it for me. > > In this case, yes, because the matcher needs that. > >> If RSpec does in fact call #valid? automatically, should we refrain from >> manually calling #valid? > > The fact that you are asking this shows that we''re violating the principle > of least surprise. We could make it so it doesn''t validate, but that would > pit the onus on users to validate explicitly (not to mention the upgrade > burden). > > Thoughts?Yes it''s a surprise, but maybe a pleasant one? I actually didn''t know about this until 2 weeks ago :) One of my coworkers showed me a spec that included error_on but didn''t explicitly call valid? We both scratched our heads a bit, prompting me to check out the code. I think it''ll catch a few people by surprise. I don''t know that it will lead to errors though. And I think it keeps the code a bit cleaner (valid? may be explicit, but it''s noisy as well), still expressing the intent well. Pat
2009-02-12 15:42, Pat Maddox:>> The fact that you are asking this shows that we''re violating the >> principle of least surprise. > > Yes it''s a surpriseHow do you know #errors_on not implicitly validating wouldn''t be bigger surprise? Say 30 (instead of three now surprised) people would be surprised. Would documenting implicit validation on code comments. Now it only says "Extension for should have on AR Model instances" on #errors_on. And imo it could very well say "Calls #valid? before returning list of errors." too, although seeing that yourself from source is only one click away if you you have dug yourself that deep in rspec-rails rdoc. -- Tero Tilus ## 050 3635 235 ## http://tero.tilus.net/
On Thu, Feb 12, 2009 at 8:31 PM, Tero Tilus <tero at tilus.net> wrote:> 2009-02-12 15:42, Pat Maddox: >>> The fact that you are asking this shows that we''re violating the >>> principle of least surprise. >> >> Yes it''s a surprise > > How do you know #errors_on not implicitly validating wouldn''t be > bigger surprise? Say 30 (instead of three now surprised) people would > be surprised.Well, I don''t know. If you''ve used Rails for a while you know that AR objects don''t have errors attached to them until valid? is called. Anyway, I think overall the implicit valid? is a good thing. Pat
It seems logical that #errors_on would call valid? Otherwise, how would it know? ///ark
Mark Wilden wrote:> It seems logical that #errors_on would call valid? Otherwise, how would it know? > >That intuitively makes sense. The reason the whole issue is confusing is because of AR''s behaviour: >> User.new.valid? => false >> User.new.errors.to_a => [] errors_on(:foo) looks like it''ll call errors.on(:foo), which returns nil if valid? isn''t called. Scott> ///ark > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
2009-02-12 21:27, Mark Wilden:> It seems logical that #errors_on would call valid? Otherwise, how > would it know?...and that''s exactly what I thought too. -- Tero Tilus ## 050 3635 235 ## http://tero.tilus.net/
On 12/02/2009, at 2:59 PM, David Chelimsky wrote:> On Feb 12, 2009, at 1:03 PM, Nick Hoffman <nick at deadorange.com> wrote: > >> Does RSpec automatically call #valid? on ActiveRecord models? >> >> For instance, when this example is run: >> >> it ''should reject a nil value'' do >> @form = TimeShiftForm.new :file => nil >> >> puts "@form.errors.count = <<#{@form.errors.count}>>" >> @form.should have(1).error_on :file > > This matcher, have(1).error_on, does call #valid. > >> >> puts "@form.errors.count = <<#{@form.errors.count}>>" >> end >> >> This is printed: >> @form.errors.count = <<0>> >> @form.errors.count = <<1>> >> >> However, I never called @form.valid? , which leads me to believe >> that RSpec called it for me. > > In this case, yes, because the matcher needs that. > >> If RSpec does in fact call #valid? automatically, should we refrain >> from manually calling #valid? > > The fact that you are asking this shows that we''re violating the > principle of least surprise. We could make it so it doesn''t > validate, but that would pit the onus on users to validate > explicitly (not to mention the upgrade burden). > > Thoughts? > > DavidI think it comes down to how much work you expect to have to do yourself, versus how much "magic" you expect will, or would like to, happen in the background. It never crossed my mind that a matcher would call #valid? . My impression of matchers was that they simply reported on whether or not an object had a specific setting/property. I figured the matcher simply checked the AR model object for the specified error, regardless of whether or not I''d called #valid? . Personally, I don''t think that matchers should be modifying the objects that they check. In my mind, a matcher is like an overseer: it reads and reports, but doesn''t tinker. Another reason that I think matchers shouldn''t call #valid? is because of the inconsistencies doing so can produce between spec examples. Examples that use have(X).errors_on won''t have an explicit call to #valid? , while examples that don''t use that matcher, but need #valid? to be called, will have an explicit called to #valid? . That''s my perspective on the matter. However, I''m not necessarily advocating that the current behaviour change. Others have said that they find it logical that #valid? is called for them. Who''s to say who''s right? -Nick
On Feb 13, 2009, at 10:52 AM, Nick Hoffman wrote:> On 12/02/2009, at 2:59 PM, David Chelimsky wrote: >> On Feb 12, 2009, at 1:03 PM, Nick Hoffman <nick at deadorange.com> >> wrote: >> >>> Does RSpec automatically call #valid? on ActiveRecord models? >>> >>> For instance, when this example is run: >>> >>> it ''should reject a nil value'' do >>> @form = TimeShiftForm.new :file => nil >>> >>> puts "@form.errors.count = <<#{@form.errors.count}>>" >>> @form.should have(1).error_on :file >> >> This matcher, have(1).error_on, does call #valid. >> >>> >>> puts "@form.errors.count = <<#{@form.errors.count}>>" >>> end >>> >>> This is printed: >>> @form.errors.count = <<0>> >>> @form.errors.count = <<1>> >>> >>> However, I never called @form.valid? , which leads me to believe >>> that RSpec called it for me. >> >> In this case, yes, because the matcher needs that. >> >>> If RSpec does in fact call #valid? automatically, should we >>> refrain from manually calling #valid? >> >> The fact that you are asking this shows that we''re violating the >> principle of least surprise. We could make it so it doesn''t >> validate, but that would pit the onus on users to validate >> explicitly (not to mention the upgrade burden). >> >> Thoughts? >> >> David > > I think it comes down to how much work you expect to have to do > yourself, versus how much "magic" you expect will, or would like to, > happen in the background. > > It never crossed my mind that a matcher would call #valid? . My > impression of matchers was that they simply reported on whether or > not an object had a specific setting/property. I figured the matcher > simply checked the AR model object for the specified error, > regardless of whether or not I''d called #valid? . > > Personally, I don''t think that matchers should be modifying the > objects that they check. In my mind, a matcher is like an overseer: > it reads and reports, but doesn''t tinker. > > Another reason that I think matchers shouldn''t call #valid? is > because of the inconsistencies doing so can produce between spec > examples. Examples that use have(X).errors_on won''t have an explicit > call to #valid? , while examples that don''t use that matcher, but > need #valid? to be called, will have an explicit called to #valid? . > > That''s my perspective on the matter. However, I''m not necessarily > advocating that the current behaviour change. Others have said that > they find it logical that #valid? is called for them. Who''s to say > who''s right?I must say that I found it a bit surprising when I started using rspec with rails (back in 0.8 or something like that). It''s something I figured out after a bit of head scratching, but I think it''s something my specs are better for in the long run. If it didn''t call valid?, I''d probably end up defining a helper method for my specs that wrapped that behavior. Scott