Skip to content
This repository has been archived by the owner on Sep 28, 2022. It is now read-only.

Commit

Permalink
Merge pull request #117 from postatum/103410068_update_events
Browse files Browse the repository at this point in the history
Add field to event.fields on set_field_value
  • Loading branch information
jstoiko committed Oct 7, 2015
2 parents 1278051 + 20aad46 commit bd29aa0
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 7 deletions.
8 changes: 5 additions & 3 deletions docs/source/event_handlers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@ There are two types of nefertari events:
* "Before" events, which are run after view class is instantiated, but before view method is run, thus before request is processed.
* "After" events, which are run after view method was called.

All events are named after camel-cased name of view method they are called around and prefixed with "Before" or "After" depending on the place event is triggered from (as described above). E.g. event classed for view method ``update_many`` are called ``BeforeUpdateMany`` and ``AfterUpdateMany``.

Check the API section for a full list of attributes/params events have.

It's recommended to use ``before`` events to:
* Transform input
* Perform validation
* Apply changes to object that is being affected by request using ``event.set_field_value`` method.
* Apply changes to object that is being affected by request using ``event.set_field_value`` method

And ``after`` events to:
* Change DB objects which are not affected by request.
Expand Down Expand Up @@ -48,6 +46,10 @@ Complete list of events:
* AfterItemOptions
* AfterCollectionOptions

Notes:
- All events are named after camel-cased name of view method they are called around and prefixed with "Before" or "After" depending on the place event is triggered from (as described above). E.g. event classed for view method ``update_many`` are called ``BeforeUpdateMany`` and ``AfterUpdateMany``.
- If a field changed via ``event.set_field_value`` is not affected by request, it will be added to ``event.fields`` which will make any field processors which are connected to this field to be triggered, if they are run after this method call (connected to events after handler that performs method call).


Predicates
----------
Expand Down
5 changes: 5 additions & 0 deletions docs/source/field_processors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ To edit other fields of instance, ``event.set_field_value`` method should be use
event.set_field_value('days_left', days_left)
return kwargs['new_value']
Note that if field you change by calling ``event.set_field_value`` is not affected by request, it will be added to ``event.fields`` which will makes field processors which are connected to changed field to be triggered, if they are run after this method call(connected to events after handler that performs method call).

E.g. if in addition to above ``calculate_days_left`` processor we had field processors for ``days_left`` field set up, running ``calculate_days_left`` will make ``days_left`` field processors run, because after ``event.set_field_value`` was called in ``calculate_days_left`` field ``days_left`` is considered "updated/changed".


API
---

Expand Down
15 changes: 14 additions & 1 deletion nefertari/events.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from contextlib import contextmanager

from nefertari.utils import FieldData


class RequestEvent(object):
""" Nefertari request event.
Expand Down Expand Up @@ -34,13 +36,25 @@ def set_field_value(self, field_name, value):
Use this method to apply changes to object which is affected
by request. Values are set on `view._json_params` dict.
If `field_name` is not affected by request, it is added to
`self.fields` which makes field processors which are connected
to `field_name` to be triggered, if they are run after this
method call(connected to events after handler that performs
method call).
:param field_name: Name of field value of which should be set.
Optional if `self.field` is set; in this case `self.field.name`
is used. If `self.field` is None and `field_name` is not
provided, KeyError is raised.
:param value: Value to be set.
"""
self.view._json_params[field_name] = value
if field_name in self.fields:
self.fields[field_name].new_value = value
return

fields = FieldData.from_dict({field_name: value}, self.model)
self.fields.update(fields)


# 'Before' events
Expand Down Expand Up @@ -222,7 +236,6 @@ def trigger_events(view_obj):
:param view_obj: Instance of nefertari.view.BaseView subclass created
by nefertari.view.ViewMapper.
"""
from nefertari.utils import FieldData
request = view_obj.request

view_method = getattr(view_obj, request.action)
Expand Down
22 changes: 19 additions & 3 deletions tests/test_events.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import pytest
from mock import patch, Mock, call

from nefertari import events
Expand All @@ -14,12 +13,29 @@ def test_request_event_init(self):
assert obj.field == 4
assert obj.instance == 5

def test_set_field_value_field_name_provided(self):
def test_set_field_value_field_present(self):
view = Mock(_json_params={})
event = events.RequestEvent(
view=view, model=None, field=None)
view=view, model=None, field=None,
fields={})
event.fields['foo'] = Mock()
event.set_field_value('foo', 2)
assert view._json_params == {'foo': 2}
assert event.fields['foo'].new_value == 2

@patch('nefertari.events.FieldData')
def test_set_field_value_field_not_present(self, mock_field):
mock_field.from_dict.return_value = {'q': 1}
view = Mock(_json_params={})
event = events.RequestEvent(
view=view, model=None, field=None,
fields={})
assert 'foo' not in event.fields
event.set_field_value('foo', 2)
assert view._json_params == {'foo': 2}
mock_field.from_dict.assert_called_once_with(
{'foo': 2}, event.model)
assert event.fields == {'q': 1}

@patch('nefertari.utils.FieldData.from_dict')
def test_trigger_events(self, mock_from):
Expand Down

0 comments on commit bd29aa0

Please sign in to comment.