[rspec-users] a better "should have valid associations"

David Chelimsky dchelimsky at gmail.com
Thu Mar 29 11:05:00 EDT 2007


On 3/29/07, Craig Demyanovich <cdemyanovich at gmail.com> wrote:
> On Mar 29, 2007, at 10:22 AM, Bryan Helmkamp wrote:
>
> > On 3/29/07, Courtenay <court3nay at gmail.com> wrote:
> >> Thanks to Wilson for converting to the new form. I've added a few
> >> lines.
> >
> > Actually, I converted this to the matcher syntax. Wilson and I are
> > using it on a project we are working on together.
> >
> > While have_valid_associations is useful as a safety net in places
> > where you are otherwise uncovered, I now strongly prefer enumerating
> > the associations that should exist in the spec. To do that, we use the
> > following code:
> >
> > ==========================================
> >
> >   class HaveAssociation
> >     def initialize(association_name)
> >       @association_name = association_name
> >     end
> >
> >     def matches?(model)
> >       @model_class = model.class
> >       success = true
> >       model.send(@association_name.to_sym, true) rescue success =
> > false
> >       success
> >     end
> >
> >     def failure_message
> >       "invalid or nonexistent association \"#{@association_name}\" on
> > #{@model_class}"
> >     end
> >   end
> >
> >   def have_association(association_name)
> >     HaveAssociation.new(association_name)
> >   end
> >
> > ==========================================
> >
> > And then in the model spec (we include ActiveRecordMatchers in the
> > context for all model specs):
> >
> > context "A car" do
> >   setup do
> >     @car = Car.new
> >   end
> >
> >   specify "should have valid associations" do
> >     @car.should have_association(:owner)
> >     @car.should have_association(:insurance)
> >   end
> > end
> >
> > Now we're covered in the case that an association is accidentally
> > removed. The "should have valid associations" specification can get a
> > big long and ugly on more complex classes, so we often use this
> > syntax:
> >
> > context "A car" do
> >   setup do
> >     @car = Car.new
> >   end
> >
> >   %w[owner insurance driver passengers engine].each do |assoc|
> >     specify "should have valid #{assoc} association" do
> >       @car.should have_association(assoc)
> >     end
> >   end
> >
> > This has the added bonus of producing much better specdoc:
> >
> > A car
> > - should have valid owner association
> > - should have valid insurance association
> > - should have valid driver association
> > - should have valid passengers association
> > - should have valid engine association
> >
> > -Bryan
>
> Nice idea, Bryan. It doesn't go far enough for me, though: it
> verifies only the name of the association. I want to verify that I've
> specified the correct macro (e.g., :has_many instead of :has_one),
> class and foreign key. Part of why I want this is because I'm working
> with a legacy database that doesn't follow the Rails conventions at
> all. In addition, though, checking all of the association attributes
> increases my confidence that I'll notice if something about the
> association changes or if I make a mistake defining it, such as
> using :has_one instead of :has_many. For these reasons, I'm doing
> what I posted earlier in this thread. Thoughts?

How about this?

project.should belong_to(:manager)
manager.should have_many(:projects)

etc

This would involve more matchers, but could be implemented in the same
fashion as have_association is above.

David
>
> Craig
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list