vidigami / backbone-orm

A polystore ORM for Node.js and the browser
http://vidigami.github.io/backbone-orm
MIT License
238 stars 15 forks source link

How to use #48

Closed thokari closed 9 years ago

thokari commented 9 years ago

Hello,

it is not quite clear to me how to use backbone-orm and backbone-mongo correctly.

For example, I have a User model, which has a 'hasMany' relationship to 'Address'. In turn, the address has a 'belongsTo' relationships to 'User'.

Question 1: When I create instances, how would I go about attaching those to one another? When I do this

user = new User { ... }
address = new Address { ... }

address.set 'user', user
user.save()

then the user gets saved properly, as does the address, but the user_id of the address is 'null'. However, when I do address.save() before saving the user, then I have two identical address objects in my database, but the user still has an address_id of 'null'

Question 2: How would I set up the relation from the other side? How do I say in code 'Make it so that these address instances are attached to this user instance'?

I am generally confused, since on the documentation website there are only examples for finding stuff, so I don't even know whether my approach of using model.set(schemeProperty, value) is correct at all...

Thanks and regards, Thomas

kmalakoff commented 9 years ago

Sorry about this. I've opened an issue for improving the documentation on setting and saving relationships.

We check and save dirty relationships when you save a model so the following should all be equivalent for One-to-One:

new User({address: new Address()}).save(callback) # or new User().save({address: new Address()}, callback)

# or
new Address({user: new User()}).save(callback); new Address().save({user: new User()}, callback)

# or 
user = new User(); address = new Address()
user.set({address}).save(callback)

# or 
user = new User(); address = new Address()
address.set({user}).save(callback)

If Address and User are One-To-Many or Many-To-Many, you need to add the many relationship to the collection either first fetching and then saving the collection or using patchAdd.

new User({addresses: [new Address()]}).save(callback)

# or
user.get 'addresses', (err) -> # ensure fetched asynchronously
  user.get('addresses').add(new Address())
  user.save(callback)

or using patchAdd to not fetch before save

https://github.com/vidigami/backbone-orm/blob/master/test/spec/sync/relational/has_many.tests.coffee#L214

https://github.com/vidigami/backbone-orm/blob/master/test/spec/sync/relational/many_to_many.tests.coffee#L165


So yes, your assuming of using set (one-to) or get().add for many is correctly although patchAdd is important if you do not want to fetch first. Basically, you modify the in-memory model and then save it, and it should work.

If you are dealing with new models, BackboneORM tries to first save the models that do not store the ids so they are assigned ids. Then, it saves the belongsTo or join tables. If you have complex situations that do not neatly fit into these patterns, you might first need to save all of the models to assign ids, then either use set + save or patchAdd to configure the relationships.

If you run into any problems, let us know. We'll aim to update the documentation soon.

thokari commented 9 years ago

Hi Kevin!

Thank you for your detailed response! I tried it again today (after fiddling with https://github.com/balderdashy/waterline for a day) and it worked nicely! We are using backbone models on the server already, so backbone-orm seems like a better fit. Also, I really like the feature of being able to embed relations between models. Also a plus for backbone-orm is the fact, that I don't need to care about the database connection (with waterline you have to call an initialize function at some point, to have the models returned to you in a callback, which is somewhat annoying). However, there is a nice feature in waterline for configuring timestamps when persisting things, I'm opening an issue for that!