Thursday 4 May 2017

Creating/updating/removing sequelize associations in one call

My question is similar to Sequelize updating nested associations

I have a model with three has-many associations. I want to send an update with the new associations in a nested object. My update should do three things with the associated objects: create any new items, remove any items no longer there, and update any existing items. Using setAssociation gets me most of the way there, but doesn't handle the creating portion. If I try to build the nested item before hand, I get an error because the fk is missing, so I am creating with createAssociation.

This is the code I have, which works, but seems elaborate for this.

  return StructureResource.findOne(db, { slug })
    .then((oldStruct) => {
      const promises = [];
      let oldAttrsIds = _.map(oldStruct.attributes, a => a.id.toString());

      _.each(newStruct.attributes, (attribute) => {
        const oldAttr = _.find(oldStruct.attributes, (attr) => {
          if (!attr.id || !attribute.id) { return; }

          return attr.id.toString() === attribute.id.toString();
        });

        // just need to update the attribute
        if (oldAttr) {
          promises.push(VaultStructureAttribute.update(attribute, {
            where: { id: attribute.id },
          }));

          // make sure we don't remove it
          oldAttrsIds = _.without(oldAttrsIds, attribute.id.toString());
          return;
        }

        // create the attribute if not found
        promises.push(oldStruct.createAttribute(
          Object.assign({}, attribute, {
            key: StructureResource.slugify(attribute.display),
          })),
        );
      });

      // delete anything no longer existing
      _.each(oldAttrsIds, oldId =>
        promises.push(VaultStructureAttribute.destroy({
          where: { id: oldId },
        })),
      );

      // handle other nested stuff

      promises.push(VaultStructure.update(newStruct, { where: { slug } }));
      return Promise.all(promises);
    }).then(responses => resolve(responses[responses.length - 1]))
    .catch(err => reject(err));



via Troy Cosentino

No comments:

Post a Comment