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

Saving model with relations #83

Open
luisbravoa opened this issue Oct 9, 2013 · 16 comments
Open

Saving model with relations #83

luisbravoa opened this issue Oct 9, 2013 · 16 comments
Labels

Comments

@luisbravoa
Copy link

Hi, is there a way to save a models data with related models? I have a model User and it has a Profile and a Role.

I'm using backbone on the client side and i'm making a put to edit user info:

var userData = {
    "email": "info@luisbravoa.com",
    "Profile": {
        "firstname": "luis",
        "lastname": "bravo"
    },
    "Role": {
          "user_id": "1",
          "role_id": "3"
      }
} ;

How can i specified in the save method to save also related models, something like this:

User.forge({id: id})
   .save(userData, { withRealated: true})
   .then(function(model){
       // weeee
   })
   .otherwise(function(error){
     // :(
});

thanks very much!

@tgriesser
Copy link
Member

I don't have something for this yet, though I'm considering it... just need to think through the different cases a bit before trying to hack something together. In the meantime you can do something like this (assuming you've loaded/parsed the relations with the appropriate data, which you could do with a custom format method).

var _    = require('underscore');
var when = require('when');

User.forge({id: id})
   .save(userData)
   .then(function(model){
     return when.all(_.map(model.relations, function(relation) {
       return relation.save();
     }).yield(model);
   })
   .then(function(model) {
     // wee
   })
   .otherwise(function(error){
     // :(
   });

You might also want to wrap it in a transaction, to ensure that if one item fails to save for whatever reason, everything is rolled back:

var when = require('when');
bookshelf.transaction(function(t) {
  User.forge({id: id})
     .save(userData, {transacting: t})
     .then(function(model){
       return when.all(_.map(model.relations, function(relation) {
         return relation.save(null, {transacting: t}));
       }).then(t.commit, t.rollback).yield(model);
     });
}).then(function(model) {
  // wee
})
.otherwise(function(error){
  // :(
});

@bendrucker
Copy link
Member

Assuming exampleRelation is a collection, you want invokeThen. invoke returns an array of promises and so calling then would throw. invokeThen is wrapping the returned array in a Promise.all which then actually resolves the promise array using then.

If exampleRelation is a single model — e.g. Model.relation: function() { return this.hasOne(ExampleRelation); } — then it would just be a standard save.

@FabricioFFC
Copy link

@tgriesser

In my case I have a object called Customer, that has many hasMany associations. These associations are stored in my model as arrays. Follows an example below:

name: 'Customer X',
email: 'customerx@gmail.com',
bankAccounts: [{
  agency: '0110',
  accountNumber: '01111'
  ...
}]

What is the best way to save my main object (Customer) and it's relations? I dig into the docs and the Ghost code, but I didn't found any simple way to save the object with all data associated.

@tgriesser
Copy link
Member

@FabricioFFC there isn't yet, mainly because there isn't a unified way of loading relation data (when it's not coming from a database) without a custom parse method. I have this relatively high on the todo list though, I'll keep you posted

@FabricioFFC
Copy link

@tgriesser ok. Thank you!

@willrstern
Copy link

Eric Clemmons came up with https://github.com/ericclemmons/bookshelf-manager as a way of saving a deeply-nested model with relations.

@dvp0
Copy link

dvp0 commented Feb 25, 2015

@tgriesser This functionality seems very vital for large data objects. Would be really helpful if we can get this built in bookshelf !

@tgriesser
Copy link
Member

Yep we're going to make sure this happens and is done right. Keep an eye on #552

@shinzui
Copy link

shinzui commented May 18, 2016

Is this feature in development? It's hard to tell by looking at #552

@adnanoner
Copy link

Is this possible?

@vellotis
Copy link
Contributor

It may be possible with bookshelf-manager.

@crunchtime-ali
Copy link
Member

The project leadership of Bookshelf recently changed. In an effort to advance the project we close all issues older than one year.

If you think this issue needs to be re-evaluated please post a comment on why this is still important and we will re-open it.

We also started an open discussion about the future of Bookshelf.js here #1600. Feel free to drop by and give us your opinion.
Let's make Bookshelf great again

@mrsimb
Copy link

mrsimb commented Nov 26, 2019

Bulk saving nested data is crucial when you create tests that fill your database. I would like to do something like this:

await new Users([
  {
    login: 'user1',
    articles: [
      { title: 'Article 1' },
      { title: 'Article 2' }
    ]
  },
  // ...
]).save()

@ricardograca
Copy link
Member

I agree. I would also like to have this functionality.

@fl0w
Copy link
Collaborator

fl0w commented Nov 26, 2019

If you want to accomplish this without restructuring the core it is possible, as previously discussed (for reference) in #1979 (comment)

@ricardograca
Copy link
Member

Great solution. Seems very elegant! We can probably add that to Bookshelf if anyone is willing to submit a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests