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

Craig Demyanovich cdemyanovich at gmail.com
Thu Mar 29 10:45:25 EDT 2007


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?

Craig


More information about the rspec-users mailing list