linkyndy/remodel

Handling model hierarchies offline

dirkdevriendt opened this issue · 6 comments

Not sure how deep a change like this would go, but it would be handy to be able to use remodel Model objects without having them stored in a database. Currently this is not possible since as soon as you try to add a linked object, remodel needs a db key relationship. (Error: Cannot assign "<Test: not saved>": "Test" instance isn't saved)
I see no reason why vanilla Python object links wouldn't suffice until one of the objects in the hierarchy is actually saved to the DB.

Love the project, by the way!

Hey, thanks for the interest in remodel!

Having simplicity in mind, this was the most straight-forward way to handle relations. Otherwise, I would have had to keep links between objects somewhere and trigger the saving of associated objects. Also, if say, you had a multi-level hierarchy of relations and you were to save an object from the middle of this hierarchy, the ORM would have had to lookup which related objects needed to be saved and which not.

Ultimately, I believe that things stay more consistent this way; I guess this is why other frameworks (such as Django or Rails) also use this approach when it comes to associated objects.

Your question sounds indeed interesting and I'm curious on your use case; why isn't the current approach working for you?

Our specific use case is that we have different monitoring backend databases with plant configurations (renewable energy plants) which we consolidate to a common object structure. The rethinkdb + remodel ease of use makes it tempting to use it as a central repository/cache.
Having to have a connection to a rethinkdb instance, however, makes it impossible to just load a plant config from one of those monitoring tools and work with it without storing it in rethinkdb first or working offline (e.g. on the train) with some set of objects created in code.

The reasons it may be interesting for other people are also illustrated here (and so it seems it might become a rethinkdb feature in the future)

I understand it may be a burden in terms of complexity so I'm also asking to gauge if you would be accepting PRs in that direction (no promises yet :-)) or if you would consider it too much bloat anyway.

So basically you're after the ODM interface provided by remodel but wish to have other custom backends where to persist the objects? Then, on demand, you'd like to sync these custom backends to the central RethinkDB instance?

I believe this feature goes beyond the scope of remodel, at least for the moment. It addresses a rather custom requirement which probably wouldn't be worth the hassle to be included in the main package, since there would be too few use cases for it. Since remodel abstracts some basic RethinkDB operations and the datastore itself doesn't provide (yet) offline functionality, I don't know whether it would be suitable to integrate this in remodel.

Nevertheless, if you're really after this functionality and wish to implement it, you can always fork this repo; if the feature gets integrated into RethinkDB at a later point, we can always merge your fork here.

If I missed something obvious, please let me know!

Thanks for indulging and your interest, but don't feel obligated to maintain the conversation :-)

The idea would be to be able to work offline (with or without other backends, that does not regard remodel) and save multiple linked Model descendent objects in one go (possibly following relations and saving "dirty" and new objects in the hierarchy, but this is not required).

Looking at it naively and not burdened with too much remodel knowledge, my impression is it should be possible:

  • for the Python id() to be used to track the object identity / link to RethinkDB id
  • for remodel to recursively find all related remodel objects and check if they should be created or updated
  • to save all Model descendent objects if something like a "dirty" concept does not exist in remodel

AFAICT this can be done without RethinkDB support.

Pseudo code:

class Country(Model):
    has_many = ('City',)

class City(Model):
    belongs_to = ('Country',)

timisoara = City(name='Timisoara')
bucharest = City(name='Bucharest')
# the cities are _not_ saved to RethinkDB
romania = Country(name='Romania', cities=[timisoara, bucharest])
# romania is _not_ saved to RethinkDB
# the relations are purely in Python, no RethinkDB IDs are created yet

# Use one of the following to persist the set of objects to RethinkDB:
romania.save(save_linked_objects=True)
romania.save(linked_objects_to_save=[timisoara, bucharest])
remodel.save(romania, timisoara, bucharest)

# Or persist them individually
# (e.g. first the country without the has_many links, then the cities and all links):
romania.save()
timisoara.save()
bucharest.save()

The idea is interesting, but I believe it will go too far in another direction that I initially established for remodel. By reading your posts, I think a separate library would be more useful in this case, since too little of remodel would be needed and too much would need to be added. I like the idea of simple things that provide just a few features.

These being said, would a plugin for remodel sound better than a separate library? I don't know. Tell me what you think; also, if you wish to embark on this journey, I would be happy to help however I can.

I'm closing this due to the lack of replies; however, feel free to reopen the issue if you have more ideas!