0

Is there a way to create a related object from embedded json in a sails.js controller?

In the contoller for the class that is being created, I need to create a related record in a different class and include the id of the parent record that was just created.

The data for the "child" record is embedded in the json that the parent record is being created from. The database in use is Mongo so it does not enforce relatioships.

How can I create these related objects?

Any examples for reference would be greatly appreciated.

UPDATE:

I've implemented the changes in the first Answer and am now getting the error "[TypeError: Cannot call method 'all' of undefined]"

Any ideas?

Edited to add code:

PurchaseInfo Model

module.exports = {

attributes: {

parent_account:{
    type:'string'
},

  purchase_date:{
      type:'datetime'
  },

  product:{
      type:'string'
  },

  subscription_length:{
      type:'integer'
  },

  renewal_date:{
      type:'date'
  },

  users_authorized:{
      type:'integer'
  },

  users_activated:{
      type:'integer'
  },

  company_name:{
      type:'string'
  },

  company_contact:{
      type:'string'
  },

  company_email:{
      type:'string',
      required:true,
      email:true
  },

  company_phone:{
      type:'string'
  },

  intended_use:{
      type:'string'
  },

  // reference to company
  company:{
      collection: 'company',
      via:'purchaser'
  }
}

};

Company Model

module.exports = {


attributes: {

company_name:{
    type:'string',
    required:'true'
},

  main_addr1:{
      type:'string',
      required:'true'
  },

  main_addr2:{
      type:'string',
      required:'true'
  },

  main_city:{
      type:'string',
      required:'true'
  },

  main_state:{
      type:'string',
      required:'true'
  },

  main_zip:{
      type:'string',
      required:'true'
  },

  main_country:{
      type:'string',
      required:'true'
  },

  mailing_same_as_main:{
      type:'boolean'
  },

  mailing_addr1:{
      type:'string'
  },

  mailing_addr2:{
      type:'string'
  },

  mailing_city:{
      type:'string'
  },

  mailing_state:{
      type:'string'
  },

  mailing_zip:{
      type:'string'
  },

  mailing_country:{
      type:'string'
  },

  primary_contact:{
      type:'string'
  },

  company_email:{
      type:'string',
      required:true,
      email:true
  },

  purchaser: {
      model: 'purchaseinfo'
  }

}

};

PurchaseInfo Controller

module.exports = {

  create: function(res, req){
  var purchaseData = req.params.all();

  // Extract the company info from the POSTed data
  var companyData = purchaseData.company_info;

 // Create the new Purchase record
  PurchaseInfo.create(purchaseData).exec(function(err,newPurchaseInfo){
      if (err){return res.req.serverError(err);}

      // Create the new Company, linking it to the purchase
      companyData.purchaser = newPurchaseInfo.id;
      Company.create(companyData).exec(function(err, newCompany) {
          if (err) {return res.serverError(err);}
          return res.json(newPurchaseInfo);
      })
  })
},
_config: {}
};

POST

http://localhost:1337/purchaseinfo/create
body:
{   "parent_account": 1,    "purchase_date": "2014-03-03",  "product": "C V1",  "subscription_length": 12,  "renewal_date": "2015-03-03",   "users_authorized": 10,     "users_activated": 1,   "company_name": "Bob's Trucking",   "company_contact": "Jane Smith",    "company_email":"[email protected]",  "company_phone": 5035129657,    "intended_use": "trucking",     "company_info": {       "company_name": "Bob's Trucking",       "main_addr1": "101 First Street",       "main_city": "Portland",        "main_state": "OR",         "main_zip": "97230",        "main_country": "USA",      "mailing_same_as_main":"true",      "primary_contact": "Jane Smith",        "company_email": "[email protected]"    } }

1 Answer 1

1

Sails v0.10 allows you to create associations between models. Here's a quick example with User and Pet models:

/* api/models/User.js */
module.exports = {
   attributes: {
     name: 'string',
     pets: {
        collection: 'pet',
        via: 'owner'
     }
   }
};

/* api/models/Pet.js */
module.exports = {
   attributes: {
     name: 'string',
     breed: 'string',
     owner: {
        model: 'user'
     }
   }
};

/* api/controllers/UserController.js */
module.exports = {

  create: function(req, res) {

    // Assuming the POST contains all the data we need to create a user...
    var userData = req.params.all();
    // Extract the pet from the POSTed data
    var petData = userData.pet;
    // Delete the pet from the POSTed data, if you
    // don't want it saved to the User collection in Mongo
    delete userData.pet;
    // Create the new user
    User.create(userData).exec(function(err, newUser) {
       if (err) {return res.serverError(err);}
       // Create the new pet, linking it to the user
       petData.owner = newUser.id;
       Pet.create(petData).exec(function(err, newPet) {
          if (err) {return res.serverError(err);}
          return res.json(newUser);
       });

    });

  }
};

This code includes an override for the default create blueprint action for User; you could also create a separate controller action for it. In reality you'd also probably want to check that the pet didn't already exist, do other validations, etc. But this should get you on your way!

Sign up to request clarification or add additional context in comments.

5 Comments

Scott, thank you for the oustanding reply! I tried this and cannot get it to work yet. I keep getting effectively "cannot read pet of undefined." So it would appear that the body is not being parsed. Also, I get errors on the "serverError" references. Do those belong to Sails or are those your functions? Thanks again for your help!
Sorry, edited answer to specify that this is all in the latest version of Sails, which you can get from Github or via npm install sails@beta. Although res.serverError should work in v0.9.x...
Also changed req.body to req.params.all(), which makes a hash of all the params sent to the route.
Fantastic! I'll check this out tonight when I get home. Thanks again!
With Scott's help I was able to get this working! Thank you Scott.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.