public
Description: Word to your object mother.
Homepage: http://nakajima.github.com/fixjour/
Clone URL: git://github.com/nakajima/fixjour.git
nakajima (author)
Tue Dec 30 12:37:20 -0800 2008
commit  2a941df08b78fa512f4f7b63287859d7496f508f
tree    af07e7d5305454f9a9c309f8f9224d5e9d986cf1
parent  db808157dcc3afcd228ea0f7e0a4f2ca724747d4
name age message
file README.textile Loading commit data...
file fixjour.gemspec
directory lib/
directory spec/
README.textile

fixjour

Another fixture replacement. Gets you new_*, create_* and
valid_*_attributes methods that you probably write yourself
anyway.

The focus of this project is liberation through constraints.

It uses the bits of object mother systems that worked well for
me in the past, and actively discourages the bits that have caused
me pain.

What it gets you:

With this setup:

Fixjour do
  define_builder(Person) do |overrides|
    Person.new({
      :name => 'Pat',
      :age => 22
    }.merge(overrides))
  end
end

include Fixjour

You get:

new_person(overrides={})

The new_person method basically just returns the result
of your builder block, which should always return an unsaved
instance of the model class
. You can pass it overrides in a
hash like so: new_person(:name => nil).

create_person(overrides={})

The create_person method calls new_person, passing in any
overrides you pass it, calls save! on the result, and returns
the saved object.

valid_person_attributes(overrides={})

The valid_person_attributes returns a hash of valid person
attributes that are derived from the new_person method, and
ideal for things like testing controllers. It can also take
attribute override options like so: valid_person_attributes(:name => nil).

Usage:

You specify builder sets for your ActiveRecord models in a
Fixjour block using the define_builder helper, which can
be used in one of two ways:

Using a builder block

Pass define_builder a model class for which you want a new set
of creation methods, and a block which returns a new valid
model object. Your block will be passed a hash of attribute
overrides, which you must merge yourself. While this approach
is much more manual than other fixture replacement tools

There are two reasons that you must merge the overrides yourself:

  1. You can delete options out of the hash, allowing you to process
    the attributes overrides a bit (though I’d strongly warn you against
    doing it too much, or else you might as well be using fixtures).
  2. I think it’s clearer to readers of the code.

Example:

define_builder(Person) do |overrides|
  Person.new({ :name => "Pat", :age => 22 }.merge(overrides))
end

Using a default attributes hash

Again, pass define_builder a model class, followed by a hash of
valid attributes for that model. With this approach, the attribute
overrides passed to the creation methods will be merged automatically.

Example:

define_builder(Person, :name => "Pat", :age => 22)

This style is simpler, though you get less flexibility to work
with the overrides hash. I’m not entirely convinced that’s a bad
thing either, since simplicity is key.

Note: Currently, builders defined using a hash cannot specify
associated objects using Fixjour creation methods. Attempting to
do so will raise a NonBlockBuilderReference error.

With Associations

To specify an associated object, you can call that object’s new_* method:

Fixjour do
  define_builder(Post) do |overrides|
    Post.new({ :name => 'a post', :body => 'texted' }.merge(overrides))
  end
  
  define_builder(Comment) do |overrides|
    Comment.new({ :body => 'Oh ok!', :post => new_post })
  end
end

include Fixjour

new_comment.post.name # => 'a post'

Note that it’s never a good idea to use a create_* method in a
build block.

Verifying your setups

Fixjour requires more work on your part, so it also includes a way
to verify that your creation methods are behaving the way they should.
Call Fixjour.verify! to ensure the following things:

  1. Creation methods are returning valid objects by default.
  2. new_* methods are returning new records.
  3. new_* and create_* methods return instances of the correct class.

TODO

  • There has to be a nicer way to merge attribute overrides
  • I don’t like passing in a model class, then having to reference it
    again from within the builder block.

View the CI build.

See Also

I’ve talked to smart people who like these instead:

© Copyright 2008 Pat Nakajima, released under MIT License.