diff options
author | Chris Lasher <chris.lasher@gmail.com> | 2013-03-07 15:23:04 -0500 |
---|---|---|
committer | Raphaël Barrois <raphael.barrois@polyconseil.fr> | 2013-03-11 17:16:30 +0100 |
commit | c5ea364df829974aaee1d84cf70d96a125afe464 (patch) | |
tree | dbc472352efb38342d57ed2e0e76b4179aec311f /docs | |
parent | 114ac649e448e97a210cf8dccc6ba50278645ce6 (diff) | |
download | factory-boy-c5ea364df829974aaee1d84cf70d96a125afe464.tar factory-boy-c5ea364df829974aaee1d84cf70d96a125afe464.tar.gz |
Merge documentation for PostGenerationMethodCall.
This merges in changes provided by gotgenes to the previous
PostGeneration documentation to the new documentation provided by
rbarrois. This documentation relates to the new functionality of
overriding default arguments to declarations of
PostGenerationMethodCall.
Signed-off-by: Raphaël Barrois <raphael.barrois@polyconseil.fr>
Diffstat (limited to 'docs')
-rw-r--r-- | docs/reference.rst | 117 |
1 files changed, 93 insertions, 24 deletions
diff --git a/docs/reference.rst b/docs/reference.rst index 03023fc..70ca38a 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -863,6 +863,7 @@ Some objects expect additional method calls or complex processing for proper def For instance, a ``User`` may need to have a related ``Profile``, where the ``Profile`` is built from the ``User`` object. To support this pattern, factory_boy provides the following tools: + - :class:`PostGenerationMethodCall`: allows you to hook a particular attribute to a function call - :class:`PostGeneration`: this class allows calling a given function with the generated object as argument - :func:`post_generation`: decorator performing the same functions as :class:`PostGeneration` - :class:`RelatedFactory`: this builds or creates a given factory *after* building/creating the first Factory. @@ -1047,60 +1048,121 @@ PostGenerationMethodCall .. class:: PostGenerationMethodCall(method_name, extract_prefix=None, *args, **kwargs) -.. OHAI_VIM* + .. OHAI_VIM* + + The :class:`PostGenerationMethodCall` declaration will call a method on + the generated object just after instantiation. This declaration class + provides a friendly means of generating attributes of a factory instance + during initialization. The declaration is created using the following arguments: + + .. attribute:: method_name + + The name of the method to call on the :attr:`~Factory.FACTORY_FOR` object -The :class:`PostGenerationMethodCall` declaration will call a method on the -generated object just after it being called. + .. attribute:: extract_prefix -Its sole argument is the name of the method to call. -Extra arguments and keyword arguments for the target method may also be provided. + If a string, the keyword argument prefix by which the field will get its + overriding arguments. If ``None``, defaults to the name of the attribute. -Once the object has been generated, the method will be called, with arguments -taken from either the :class:`PostGenerationMethodCall` or prefix-based values: + .. deprecated:: 1.3.0 + Will be removed in 2.0.0 -- If a value was extracted from kwargs (i.e an argument for the name the - :class:`PostGenerationMethodCall` was declared under): + .. attribute:: args - - If the declaration mentionned zero or one argument, the value is passed - directly to the method - - If the declaration used two or more arguments, the value is passed as - ``*args`` to the method + The default set of unnamed arguments to pass to the method given in + :attr:`method_name` -- Otherwise, the arguments used when declaring the :class:`PostGenerationMethodCall` - are used + .. attrinbute:: kwargs -- Keywords extracted from the factory arguments are merged into the defaults - present in the :class:`PostGenerationMethodCall` declaration. + The default set of keyword arguments to pass to the method given in + :attr:`method_name` + +Once the factory instance has been generated, the method specified in +:attr:`~PostGenerationMethodCall.method_name` will be called on the generated object +with any arguments specified in the :class:`PostGenerationMethodCall` declaration, by +default. + +For example, to set a default password on a generated User instance +during instantiation, we could make a declaration for a ``password`` +attribute like below: .. code-block:: python class UserFactory(factory.Factory): FACTORY_FOR = User - password = factory.PostGenerationMethodCall('set_password', password='') + username = 'user' + password = factory.PostGenerationMethodCall('set_password', + 'defaultpassword') + +When we instantiate a user from the ``UserFactory``, the factory +will create a password attribute by calling ``User.set_password('defaultpassword')``. +Thus, by default, our users will have a password set to ``'defaultpassword'``. .. code-block:: pycon - >>> UserFactory() # Calls user.set_password(password='') - >>> UserFactory(password='test') # Calls user.set_password('test') - >>> UserFactory(password__disabled=True) # Calls user.set_password(password='', disabled=True) + >>> u = UserFactory() # Calls user.set_password('defaultpassword') + >>> u.check_password('defaultpassword') + True + +If the :class:`PostGenerationMethodCall` declaration contained no +arguments or one argument, an overriding the value can be passed +directly to the method through a keyword argument matching the attribute name. +For example we can override the default password specified in the declaration +above by simply passing in the desired password as a keyword argument to the +factory during instantiation. + +.. code-block:: pycon + + >>> other_u = UserFactory(password='different') # Calls user.set_password('different') + >>> other_u.check_password('defaultpassword') + False + >>> other_u.check_password('different') + True + +.. note:: For Django models, unless the object method called by + :class:`PostGenerationMethodCall` saves the object back to the + database, we will have to explicitly remember to save the object back + if we performed a ``create()``. + + .. code-block:: pycon + + >>> u = UserFactory.create() # u.password has not been saved back to the database + >>> u.save() # we must remember to do it ourselves -When the :class:`PostGenerationMethodCall` declaration uses two or more arguments, -the extracted value must be iterable: + We can avoid this by subclassing from :class:`DjangoModelFactory`, + instead, e.g., + + .. code-block:: python + + class UserFactory(factory.DjangoModelFactory): + FACTORY_FOR = User + + username = 'user' + password = factory.PostGenerationMethodCall('set_password', + 'defaultpassword') + + +If instead the :class:`PostGenerationMethodCall` declaration uses two or +more positional arguments, the overriding value must be an iterable. For +example, if we declared the ``password`` attribute like the following, .. code-block:: python class UserFactory(factory.Factory): FACTORY_FOR = User + username = 'user' password = factory.PostGenerationMethodCall('set_password', '', 'sha1') +then we must be cautious to pass in an iterable for the ``password`` +keyword argument when creating an instance from the factory: + .. code-block:: pycon >>> UserFactory() # Calls user.set_password('', 'sha1') >>> UserFactory(password=('test', 'md5')) # Calls user.set_password('test', 'md5') - >>> UserFactory(password__disabled=True) # Calls user.set_password('', 'sha1', disabled=True) >>> # Always pass in a good iterable: >>> UserFactory(password=('test',)) # Calls user.set_password('test') @@ -1116,6 +1178,13 @@ the extracted value must be iterable: value to the :class:`PostGenerationMethodCall` declaration (``PostGenerationMethodCall('method', 'x', 'y_that_is_the_default')``) +Keywords extracted from the factory arguments are merged into the +defaults present in the :class:`PostGenerationMethodCall` declaration. + +.. code-block:: pycon + + >>> UserFactory(password__disabled=True) # Calls user.set_password('', 'sha1', disabled=True) + Module-level functions ---------------------- |