Forum: RSpec Is #valid? automatically called?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (nickh)
on 2009-02-12 20:30
(Received via mailing list)
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
39100495c9937c39b2e0c704444e1b4a?d=identicon&s=25 Pat Maddox (Guest)
on 2009-02-12 21:18
(Received via mailing list)
On Thu, Feb 12, 2009 at 11:03 AM, Nick Hoffman <nick@deadorange.com>
wrote:
> 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
5d38ab152e1e3e219512a9859fcd93af?d=identicon&s=25 David Chelimsky (Guest)
on 2009-02-12 21:39
(Received via mailing list)
On Feb 12, 2009, at 1:03 PM, Nick Hoffman <nick@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
39100495c9937c39b2e0c704444e1b4a?d=identicon&s=25 Pat Maddox (Guest)
on 2009-02-13 01:18
(Received via mailing list)
On Thu, Feb 12, 2009 at 11:59 AM, David Chelimsky <dchelimsky@gmail.com>
wrote:
>>  @form.should have(1).error_on :file
>>
> 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
95a6493586dcb150d4fb4aec8f81b766?d=identicon&s=25 Tero Tilus (Guest)
on 2009-02-13 05:56
(Received via mailing list)
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.

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.
48641c4be1fbe167929fb16c9fd94990?d=identicon&s=25 Mark Wilden (Guest)
on 2009-02-13 06:30
(Received via mailing list)
It seems logical that #errors_on would call valid? Otherwise, how would
it know?

///ark
39100495c9937c39b2e0c704444e1b4a?d=identicon&s=25 Pat Maddox (Guest)
on 2009-02-13 06:30
(Received via mailing list)
On Thu, Feb 12, 2009 at 8:31 PM, Tero Tilus <tero@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
369b9fd2a0d9e7cdbc60907a2a056ad9?d=identicon&s=25 Scott Taylor (Guest)
on 2009-02-13 06:58
(Received via mailing list)
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
95a6493586dcb150d4fb4aec8f81b766?d=identicon&s=25 Tero Tilus (Guest)
on 2009-02-13 07:24
(Received via mailing list)
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.
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (nickh)
on 2009-02-13 16:58
(Received via mailing list)
On 12/02/2009, at 2:59 PM, David Chelimsky wrote:
>> @form.should have(1).error_on :file
>>
> 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?
-Nick
369b9fd2a0d9e7cdbc60907a2a056ad9?d=identicon&s=25 Scott Taylor (Guest)
on 2009-02-13 17:57
(Received via mailing list)
On Feb 13, 2009, at 10:52 AM, Nick Hoffman wrote:

>>>
>>> @form.errors.count = <<0>>
>> The fact that you are asking this shows that we're violating the
> happen in the background.
>
> 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
This topic is locked and can not be replied to.