Model Builders
==============

**PyFactory** is model-agnostic, meaning that it can be used to write
factories for any kind of model or backing store. That means that
**PyFactory** can be used to write factories for Django models, SQLAlchemy,
your custom solution, etc.

The key abstraction which makes this possible is the `model builder`. A
model builder is a class which implements only a few methods which tells
PyFactory how to create models.

Model Builder Interface
-----------------------

The main model builder interface is documented below.

.. py:class:: ModelBuilder

   .. py:function:: build(cls, model_cls, attributes)

      **(classmethod)**

      This method is called when a model needs to be built. The model
      should `not` be persisted to the backing store, in this case. The
      return value of this method should be the instantiated model.

      :Parameters:
        - `model_cls` - This is the model class defined by the factory's
          ``_model`` class variable.
        - `attributes` - This is a dictionary of attributes to initialize
          the model with.

   .. py:function:: create(cls, model_cls, attributes)

      **(classmethod)**

      This method is called when a model needs to be created. The model
      should be created and *saved*. The return value should be the new
      instance of the model.

      :Parameters:
        - `model_cls` - This is the model class defined by the factory's
          ``_model`` class variable.
        - `attributes` - This is a dictionary of attributes to initialize
          the model with.

Example Model Builder
---------------------

Below is an example model builder, which simply sets attributes on objects
as the "model"::

    class MyModelBuilder(object):
        @classmethod
        def build(cls, model_cls, attrs):
            result = model_cls()
            for key,val in attrs.iteritems():
                setattr(result, key, val)

            return result

        @classmethod
        def create(cls, model_cls, attrs):
            result = self.build(model_cls, attrs)
            result.saved = True
            return result

Using Model Builders
--------------------

To use or enable a model builder, specify it via the ``_model_builder``
class variable on the factory. For example, to use our model builder
above::

    class MyFactory(Factory):
        _model = object
        _model_builder = MyModelBuilder

        # ...

The above creates a new factory ``MyFactory`` which will use
``MyModelBuilder`` as the model builder, and ``object`` will
be passed in as the ``model_cls`` to the model builder methods.
