emmett-framework / emmett

The web framework for inventors
BSD 3-Clause "New" or "Revised" License
1.06k stars 71 forks source link

Behavior of computed fields #197

Closed josejachuf closed 2 years ago

josejachuf commented 7 years ago

@gi0baro I imagine this behavior is inherited from pydal, but it seems to me that it is incorrect Given:

class Foo(Model):
    name = Field()
    f1 = Field('integer')
    f2 = Field('integer')
    f3 = Field('integer')
    validation = {
        'f3': {'allow': 'empty'},
    }
    @compute('f3')
    def compute_f3(self, row):
        return row.f1 + row.f2

I do not know why it produces the error:

>>> Foo.create(name='aaaa', f1=1, f2=2)
<Row {'id': None, 'errors': {'f3': 'Invalid value'}}>
>>> Foo.create(name='aaaa', f1=1, f2=2, f3=3)
<Row {'id': 1, 'errors': {}}>
>>> db.commit()
>>> f = Foo.get(1)
>>> f
<Row {'id': 1, 'name': 'aaaa', 'f1': 1, 'f2': 2, 'f3': 3}>

If I update without including all fields involved in the computed field, the change in f3 is not reflected:

>>> f.update_record(f1=5)
<Row {'id': 1, 'name': 'aaaa', 'f1': 5, 'f2': 2, 'f3': 3}>
>>> db.commit()
>>> f = Foo.get(1)
>>> f             
<Row {'id': 1, 'name': 'aaaa', 'f1': 5, 'f2': 2, 'f3': 3}>
>>> f.update_record(f1=5, f2=3)
<Row {'id': 1, 'name': 'aaaa', 'f1': 5, 'f2': 3, 'f3': 3}>
>>> db.commit()
>>> f = Foo.get(1)
>>> f
<Row {'id': 1, 'name': 'aaaa', 'f1': 5, 'f2': 3, 'f3': 8}>
gi0baro commented 7 years ago

@josejachuf hmmm, I can't reproduce this. Tested directly in console:

(weppytestpy3) ➜  bloggy git:(release) ✗ python
Python 3.5.2 (default, Oct 11 2016, 05:05:28)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from weppy import App
>>> from weppy.orm import Database, Model, Field, compute
>>> app = App(__name__)
>>>
>>> class Foo(Model):
...     name = Field()
...     f1 = Field('integer')
...     f2 = Field('integer')
...     f3 = Field('integer')
...     validation = {
...         'f3': {'allow': 'empty'},
...     }
...
...     @compute('f3')
...     def compute_f3(self, row):
...         return row.f1 + row.f2
...
>>>
>>> db = Database(app, auto_migrate=True)
>>> db.define_models(Foo)
>>> with db.connection():
...     Foo.create(name='bar', f1=1, f2=2)
...     Foo.get(1)
...
<Row {'id': 1, 'errors': {}}>
<Row {'f2': 2, 'id': 1, 'f3': 3, 'name': 'bar', 'f1': 1}>
gi0baro commented 7 years ago

Regarding the issues on updates:

josejachuf commented 7 years ago

@gi0baro About create row, works for me. It is likely that by the time I tried I still had not put validation: validation = {'f3': {'allow': 'empty'}}

On the update, perhaps in a later version it would be convenient to update the computed fields regardless of whether the fields involved are updated, the current value of these fields should be taken.

Jose