[rspec-users] Is #valid? automatically called?
Scott Taylor
scott at railsnewbie.com
Fri Feb 13 11:41:49 EST 2009
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
More information about the rspec-users
mailing list