[rspec-users] Validations based on associations

Pat Maddox pergesu at gmail.com
Thu Jan 4 23:22:22 EST 2007


On 1/1/07, David Chelimsky <dchelimsky at gmail.com> wrote:
> On 1/1/07, Pat Maddox <pergesu at gmail.com> wrote:
> > My model is very simple, it's mostly just a join table that represents
> > which tournaments a user has registered for.
> >
> > class Registration < ActiveRecord::Base
> >   belongs_to :user
> >   belongs_to :tournament
> >
> >   validates_presence_of :user_id, :tournament_id
> >   validates_uniqueness_of :user_id, :scope => :tournament_id
> > end
> >
> > the validates_uniqueness checks to make sure there's no record that
> > has the same user_id and tournament_id.
> >
> > Is there a relatively easy way to specify this behavior?  The only way
> > that I know is to do something like
> >
> > context "A Registration with a User and Tournament" do
> >   setup do
> >     @user = User.new
> >     @user.save false
> >     @tournament = Tournament.new
> >     @tournament.save false
> >     @reg = Registration.new(:user => @user, :tournament => @tournament)
> >   end
> >
> >   specify "should be valid" do
> >     @reg.should_be_valid
> >   end
> >
> >   specify "should not be valid if a registration with the same details
> > already exists" do
> >     @reg.save
> >     Registration.new(:user => @user, :tournament =>
> > @tournament).should_not_be_valid
> >   end
> > end
>
> Geez, ActiveRecord models are SUCH a violation of SRP! I realize that
> this is the rails way, and that there are great productivity benefits
> we glean from AR, but having a model that validates both at both the
> instance level (validates_presence_of) and the class level
> (validates_uniqueness_of) is a pain in the ass. It's confusing because
> both sorts of validations look the same, but they are really
> fundamentally different.
>
> Ranting aside, there are a couple of different ways you can view this.
> To be the most clear, I'd probably spec the class level validations
> separately from instance level validations. The uniqueness spec might
> look like this:
>
> context "The Registration model class" do
>   setup do
>     @user1 = User.new
>     @user2 = User.new
>     @tournament = Tournament.new
>
>     [@user1, @user2, @tournament].each {|model| model.save(false)}
>   end
>
>   specify "should permit registrations with different users" do
>     Registration.create(:user => @user1, :tournament => @tournament)
>     Registration.new(:user => @user2, :tournament =>
> @tournament).should_be_valid
>   end
>
>   specify "should deny multiple registrations with the same user" do
>     Registration.create(:user => @user1, :tournament => @tournament)
>     Registration.new(:user => @user1, :tournament =>
> @tournament).should_not_be_valid
>   end
> end
>
> WDYT?

That makes a lot of sense.  I'm finding that, as productive as I am
with Rails, RSpec is helping me find a lot of deficiencies in the
Rails philosophy, but far more importantly in my own thinking.

I've learned that I have to pay a LOT more attention than I have been
when coding...and I consider myself a mindful programmer to begin
with.  I know it sounds obvious that you have to pay attention, but it
can be tough in practice.

Anyway I'm loving RSpec, if only because I'm asking more design
questions than I was before.  Whenever a spec is awkward to write or
implement, it's time to investigate further.

Thanks a lot for the input.

Pat


More information about the rspec-users mailing list