Nozbe / WatermelonDB

🍉 Reactive & asynchronous database for powerful React and React Native apps ⚡️
https://watermelondb.dev
MIT License
10.62k stars 600 forks source link

Automatic create/update tracking not working in react native 0.73.1 #1753

Closed faisal-rehman19 closed 8 months ago

faisal-rehman19 commented 8 months ago

I have added Automatic create/update tracking as per the documentation but it is not working for me. It just shows 0 for both created_at and updated_at. Here is my schema code:

import {appSchema, tableSchema} from '@nozbe/watermelondb';

export const mySchema = appSchema({
  version: 14,
  tables: [
    tableSchema({
      name: 'dampers',
      columns: [
        {name: 'damper_inspection_id', type: 'number'},
        {name: 'building_id', type: 'number'},
        {name: 'building_code', type: 'string'},
        {name: 'inspection_id', type: 'number'},
        {name: 'building_name', type: 'string'},
        {name: 'damper_type', type: 'string', isOptional: true},
        {name: 'access_door_type', type: 'string', isOptional: true},
        {name: 'access_type', type: 'string', isOptional: true},
        {name: 'closed_picture', type: 'string', isOptional: true},
        {name: 'damper_id', type: 'number'},
        {name: 'failed_picture2', type: 'string', isOptional: true},
        {name: 'failed_picture3', type: 'string', isOptional: true},
        {name: 'failed_picture4', type: 'string', isOptional: true},
        {name: 'failed_picture5', type: 'string', isOptional: true},
        {name: 'label_picture', type: 'string', isOptional: true},
        {name: 'open_picture', type: 'string', isOptional: true},
        {name: 'reason', type: 'string', isOptional: true},
        {name: 'result', type: 'string', isOptional: true},
        {name: 'repairs', type: 'string', isOptional: true},
        {name: 'floor', type: 'string', isOptional: true},
        {name: 'location', type: 'string', isOptional: true},
        {name: 'location_type', type: 'string', isOptional: true},
        {name: 'number', type: 'string', isOptional: true},
        {name: 'smokenote', type: 'string', isOptional: true},
        {name: 'unit', type: 'string', isOptional: true},
        {name: 'is_synced', type: 'boolean', isOptional: true},
        {name: 'notes', type: 'string', isOptional: true},
        {name: 'created_at', type: 'number'},      // <-------- Changes
        {name: 'updated_at', type: 'number'},     // <-------- Changes
      ],
    }),
  ],
});

Here is how my damper model class looks like:

import {Model} from '@nozbe/watermelondb';
import {date, field, readonly} from '@nozbe/watermelondb/decorators';

export default class Damper extends Model {
  static table = 'dampers';

  @readonly @date('created_at') created_at;          // <--------- Changes
  @readonly @date('updated_at') updated_at;       // <--------- Changes

  @field('damper_inspection_id') damper_inspection_id;
  @field('building_id') building_id;
  @field('building_code') building_code;
  @field('building_name') building_name;
  @field('inspection_id') inspection_id;
  @field('damper_type') damper_type;
  @field('access_door_type') access_door_type;
  @field('access_type') access_type;
  @field('closed_picture') closed_picture;
  @field('damper_id') damper_id;
  @field('failed_picture2') failed_picture2;
  @field('failed_picture3') failed_picture3;
  @field('failed_picture4') failed_picture4;
  @field('failed_picture5') failed_picture5;
  @field('label_picture') label_picture;
  @field('open_picture') open_picture;
  @field('reason') reason;
  @field('result') result;
  @field('repairs') repairs;
  @field('floor') floor;
  @field('location') location;
  @field('location_type') location_type;
  @field('number') number;
  @field('smokenote') smokenote;
  @field('notes') notes;
  @field('unit') unit;
  @field('is_synced') is_synced;
}

Here is how I am creating a damper record:

await database.write(async () => {
      const damperWriteResponse = await database
        .get('dampers')
        .create(damper => {
          Object.keys(payload).forEach(key => {
            // Check if the key exists in the damperRecord to avoid errors.
            if (key in damper._raw) {
              damper[key] = payload[key];
            }
          });
          damper.is_synced = false;
        });
    });

When I see the Db file by opening it in db browser for sqlite, this is what I see(I see created_at: {} on react native experimental-debugger):

image

I am using the following versions

"@nozbe/watermelondb": "^0.27.1",
"react": "18.2.0",
"react-native": "0.73.1",

I am using this library for the first time. Let me know if I am making any mistake. I would appreciate any help in this regard. Thanks

suman379 commented 8 months ago

your payload contain the created_at and updated_at field?

if yes, then remove it from the payload because watermelondb handle it internally.

faisal-rehman19 commented 8 months ago

your payload contain the created_at and updated_at field?

if yes, then remove it from the payload because watermelondb handle it internally.

no, I am not sending created_at and updated_at in payload. I have defined these fields to be readonly in my schema. So, watermelon won't let me send them while creating the record and will throw an error even if i try to.

primus11 commented 8 months ago

just a random guess - did you add migration?

faisal-rehman19 commented 8 months ago

just a random guess - did you add migration?

No, I haven't added migrations, because the app is not in production yet. So whenever I make a change in schema, I just bump up the version number. The previously added data is lost, but it doesn't matter to me at the moment. So I think the absence of migrations is not the issue.

primus11 commented 8 months ago

Oh,

export default class Damper extends Model {
  static table = 'dampers';

  @readonly @date('created_at') created_at;          // <--------- Changes
  @readonly @date('updated_at') updated_at;       // <--------- Changes

  @field('damper_inspection_id') damper_inspection_id;

should be probably

export default class Damper extends Model {
  static table = 'dampers';

  @readonly @date('created_at') createdAt;          // <--------- Changes (camel case)
  @readonly @date('updated_at') updatedAt;       // <--------- Changes (camel case)

  @field('damper_inspection_id') damper_inspection_id;
faisal-rehman19 commented 8 months ago

Oh,

export default class Damper extends Model {
  static table = 'dampers';

  @readonly @date('created_at') created_at;          // <--------- Changes
  @readonly @date('updated_at') updated_at;       // <--------- Changes

  @field('damper_inspection_id') damper_inspection_id;

should be probably

export default class Damper extends Model {
  static table = 'dampers';

  @readonly @date('created_at') createdAt;          // <--------- Changes (camel case)
  @readonly @date('updated_at') updatedAt;       // <--------- Changes (camel case)

  @field('damper_inspection_id') damper_inspection_id;

@primus11 thanks a lot. createdAt and updatedAt should be in camel case. I thought this naming convention is upto us and we name it based on how we want to access these properties in our javascript code.