<br><br><div><span class="gmail_quote">On 7/25/07, <b class="gmail_sendername">Mikel Lindsaar</b> <<a href="mailto:raasdnil@gmail.com">raasdnil@gmail.com</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Kyle,<br><br>That is a good point. We are after the behaviour, not the implementation.<br><br>Regards<br><br>Mikel<br><br>On 7/25/07, Daniel N <<a href="mailto:has.sox@gmail.com">has.sox@gmail.com</a>> wrote:<br>>
<br>><br>><br>> On 7/25/07, Kyle Hargraves <<a href="mailto:philodespotos@gmail.com">philodespotos@gmail.com</a>> wrote:<br>> > Daniel N wrote:<br>> > > On 7/25/07, Mikel Lindsaar <<a href="mailto:raasdnil@gmail.com">
raasdnil@gmail.com</a>> wrote:<br>> > >><br>> > >> There would be a different way.<br>> > >><br>> > >> In the idea of "Only test the code you write" all you really need to
<br>> > >> spec is that you have set the right association, because activerecord<br>> > >> has it's own tests to ensure the uniq call works.<br>> > >><br>> > >> You can do this with a call to
<br>> reflect_on_association. Unfortunately<br>> > >> that call does not return a hash, but an association object.<br>> > >><br>> > >> I wrote a blog post on how to do this easily with a spec_helper.rb
<br>> > >> method that adds to_hash to reflect on association.<br>> > >><br>> > >><br>> > >><br>> <a href="http://www.blognow.com.au/q/67540/Reflect_on_association_one_liner_to_check_association_details.html">
http://www.blognow.com.au/q/67540/Reflect_on_association_one_liner_to_check_association_details.html</a><br>> > >><br>> > >><br>> > >> In the end you end up with a spec that looks like this:
<br>> > >><br>> > >> it "should test reflection details" do<br>> > >><br>> > >> association_results = {<br>> > >> :macro => :has_many,<br>
> > >> :options => {:through => :clipping, :uniq => true},<br>> > >> :class_name => "nil"<br>> > >> }<br>> > >><br>> > >>
Book.reflect_on_association (:clip).to_hash.should ==<br>> > >> association_results<br>> > >><br>> > >> end<br>> > >><br>> > >><br>> > >> Of course, you can add whatever values you want into the hash.
<br>> > >><br>> > >> I now have one of these specs at the top of pretty much every model<br>> > >> spec. Just set up the hash with all your association rules and then<br>> > >> this can be checked and kept track of when you are refactoring or
<br>> > >> changing code.<br>> > >><br>> > >> Hope that helps.<br>> > >><br>> > >> Regards<br>> > >><br>> > >> Mikel<br>> > ><br>
> > ><br>> > > Thanx Mikel.<br>> > ><br>> > > I didn't even think of using a uniq on the has_many. I was using a<br>> > > validates_uniquness_of :scope => 'book_id'
<br>> > ><br>> > > I will definitley look into this one.<br>> > ><br>> > > Thankyou<br>> > > Daniel<br>> ><br>> > However you decide to go about solving it, the idiom you hit upon is
<br>> > what, to me, actually describes the behaviour; if the book already has a<br>> > clip once, you can't add it again:<br>> ><br>> > lambda { add_twice }.should change(...).by(1)<br>> >
<br>> > It states very clearly what results you wish to see.<br>> ><br>> > Going through reflect_on_association feels too much like specifying the<br>> > use of a particular implementation, rather than the desired outcome.
<br>> ><br>> > Kyle<br>><br>><br>> It looks much better when you write it like that though ;)<br>><br>><br>></blockquote><div><br>Thanx for the input guys. I wasn''t entirely happy with what I had because it didn't actually test what I wanted. It tests that a duplicate cannot be added. But I specifically wanted to not allow duplicates for a given clip_id
<br><br> it "should have a uniq clip_id for a given book" do<br> lambda do<br> Clipping.create( valid_clipping_attributes )<br> Clipping.create( valid_clipping_attributes )<span class="q"><br> end.should
change( Clipping, :count ).by( 1 )
<br></span> end<br></div><br></div>became<br><br> it "should have a uniq clip_id for a given book" do<br> lambda do<br><br> Clipping.create( valid_clipping_attributes.with( :book => @book, :clip => @clip ) )
<br> clipping = Clipping.create( valid_clipping_attributes.with( :book => @book, :clip => @clip ) )<br><br> clipping.should have(1).error_on( :clip_id )<br> clipping.errors.on( :clip_id ).should match( /(already|duplicate|exists)/i )
<br><br> end.should change( Clipping, :count ).by( 1 )<br> end<br><br>If anyone was interested :P<br><br>Daniel<br>