Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot create the object two times - class models #3642

Closed
maxencehenneron opened this issue Mar 12, 2021 · 5 comments
Closed

Cannot create the object two times - class models #3642

maxencehenneron opened this issue Mar 12, 2021 · 5 comments

Comments

@maxencehenneron
Copy link

maxencehenneron commented Mar 12, 2021

Goals

Being able to create a class model two times

Expected Results

Two models are written to the realm.

Actual Results

The first one is successfully written, the second one throws the following exception:

Screenshot 2021-03-12 at 16 39 04

Steps to Reproduce

Given the following class model (typescript) :

export default class Transaction extends Realm.Object {
    name: string;
    date: Date;
    value: number;
    _id?: string;

    constructor(name: string, date: Date, value: number) {
        super();
        
        this._id = new ObjectId().toHexString();
        this.name = name;
        this.date = date;
        this.value = value;
    }

    static schema: Realm.ObjectSchema = {
        name: 'Transaction',
        primaryKey: '_id',
        properties: {
            _id: 'string',
            name: 'string',
            date: 'date',
            value: 'int'
        }
    };
}

Here's how I setup realm:

const realm = new Realm({schema: [Transaction]});

When I add my first transaction like this:

realm?.write(() => {
    realm.create(
        Transaction,
        new Transaction(
            "Coffee",
            new Date(),
            35
        )
    );
});

The first time, everything works as expected, but when I call this code a second time, the app crashes with the exception above.

Ideally I would want to automatically generate an id in my model, so I don't have to duplicate code ( I also need a created_at, updated_at, and I don't want to specify those everytime I create a new object ).

I think the bug is around this line:

if (!JSValueIsStrictEqual(ctx, schemaObjectConstructor, constructor)) {

Side note: I wanted to fix the issue myself but wasn't able to compile realm myself. The tests seem to use a private docker repository that I cannot clone 🙁

Version of Realm and Tooling

  • Realm JS SDK Version: 10.2.0
  • Node or React Native: React Native
  • Client OS & Version: 0.63
  • Which debugger for React Native: None
@takameyer
Copy link
Contributor

@maxencehenneron Thanks for reporting this issue. This bug is part of a larger issue relating to extended the Realm.Object class and using this object to add entries to the database. At the moment, after the first model is added, Realm creates a direct reference to memory in order to improve performance and memory usage. This is done by modifying the incoming models Realm.Object prototype chain.

We are currently debating on how we should handle this better. Here is a link to the related issue:
#3553

You can work around this by not extending Realm.Object.

I apologise that our build process is not so clear, we have actually done a lot of work in the development branch to make this easier in the future. For now, if you do want to build without those tests, just modify line 59 in the package.json :
"rebuild-changes": "node-pre-gyp rebuild --debug -j 8 ${npm_config_arch:+--target_arch=${npm_config_arch}} && cd tests && npm install",
by removing && cd tests && npm install

@maxencehenneron
Copy link
Author

@takameyer Thank you for your response. Unfortunately, removing the Realm.Object inheritance did not fix the issue. This seems to happen as soon as we use classes. Removing the class from the schema initialization works, but I lose all the benefits of classes, which are important in my use case as I need to write many functions to manipulate the data.

I'll try to build the develop branch and comment caching to unblock me.

@takameyer
Copy link
Contributor

@maxencehenneron another workaround is to keep extending the Realm.Object, but do not use the constructor. This way you could also write modifier functions in the class. You could also provide a static function to produce a normal object for creating new models with this class. Also Typescript has the declare keyword which can be used to present a class that has properties that are initialised elsewhere (in this case Realm).

export default class Transaction extends Realm.Object {
    declare name: string;
    declare date: Date;
    declare value: number;
    declare _id?: string;

    // Example function to manipulate realm data
    incrementValue(){
       this.value = this.value + 1;
    }

    // Helper function to produce an object for creating new models
    static generateObjectForCreation(name: string, date: Date, value: number) {
        return {
            _id :new ObjectId().toHexString(),
            name,
            date,
            value
        }
    }

    static schema: Realm.ObjectSchema = {
        name: 'Transaction',
        primaryKey: '_id',
        properties: {
            _id: 'string',
            name: 'string',
            date: 'date',
            value: 'int'
        }
    };
}

Then creation would happen like so:

    realm.write(() => {
        realm.create(Transaction, Transaction.generateObjectForCreation("new name", new Date(), 12 ))
    })

This is merely a workaround until we come up with an official solution. Let me know if this helps.

@maxencehenneron
Copy link
Author

Thank you, it seems to work and it's a nice workaround

@kneth
Copy link
Contributor

kneth commented Dec 9, 2022

We have changed the behaviour in version 11.0.0, and class-based models are now supported.

@kneth kneth closed this as completed Dec 9, 2022
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants