Связанная вставка в 2 таблицы в Sailes.js

Для экспертов, знакомых с парусами.js: у меня есть модель клиентов, и для простоты скажем

/**
 * Customers.js
 */

module.exports = {

    attributes: {

        firstName: { type: 'string' },
        lastName: { type: 'string' }
    }
};

ВАЖНО: существует также модель CustomerHistory, как показано ниже. Всякий раз, когда клиент создается или обновляется, соответствующая запись CustomerHistory также должна быть вставлена/создана.

     /**
     * CustomerHistory.js
     */

    module.exports = {

        attributes: {

            customer: { model: 'customer' },
            firstName: { type: 'string' },
            lastName: { type: 'string' },
            modifiedAt: { type: 'datetime'}
        }
    };

ВАРИАНТЫ в Sails.js:

  1. Переопределить или создать новые действия Sails Blueprint (назовем их CreateWithHistory и UpdateWithHistory), которые всегда вставляются в CustomerHistory после успешного сохранения в Customer. Если это предлагаемое решение, поможет пример кода.

  2. Создайте настраиваемые действия контроллера (назовем их CreateWithHistory и UpdateWithHistory), которые всегда вставляются в CustomerHistory при успешном сохранении в Customer. Если это предлагаемое решение, пример кода поможет связать 2 Model.create и Model.update с действиями Model.create.

  3. Создайте пользовательское действие «Модель клиентов» для неявного сохранения в журнале при создании или обновлении. Как это сделать?


person user3233791    schedule 09.01.2018    source источник
comment
Лично я бы предпочел третий метод, при котором триггер будет находиться в хуках Customer afterCreate/afterUpdate. В 1-м и 2-м методах есть вероятность, что какой-то другой разработчик может использовать метод по умолчанию .create или .update, и тогда в CustomerHistory не будет соответствующего действия. 3-й случай обрабатывает эту ситуацию.   -  person khushalbokadey    schedule 10.01.2018


Ответы (1)


Sails js предоставляет обратные вызовы жизненного цикла для моделей, которые вы можете использовать. Они позволяют выполнять пользовательский код всякий раз, когда создаются, обновляются новые модели или в другое время. Я думаю, вы можете добиться того, чего хотите, добавив обратные вызовы в свою модель Customer. В Customer.js:

module.exports = {

    attributes: {
        firstName: { type: 'string' },
        lastName: { type: 'string' }
    },

    // this will create a new CustomerHistory for each Customer created
    afterCreate: function(customer, cb) {
        CustomerHistory.create({
            customer: customer.id,
            firstName: customer.firstName,
            lastName: customer.lastName,
            modifiedAt: new Date()
        }).exec(function(err, history) {
            if (err) { return cb(err); }
            cb();
        });
    },

    // update some fields in CustomerHistory after Customer is updated
    afterUpdate: function(customer, cb) {
        CustomerHistory.update({customer: customer.id}, {
            firstName: customer.firstName,
            lastName: customer.lastName,
            modifiedAt: new Date()
        }).exec(function(err, history) {
            if (err) { return cb(err); }
            cb();
        });
    }
};

Это может быть не тот точный поток, который вам нужен (например, может быть, вы иногда сначала создаете историю, иногда не изменяете историю при обновлении и т. д.), но я думаю, используя список доступных обратных вызовов должен быть в состоянии выполнить то, что вы хотите.

person arbuthnott    schedule 10.01.2018
comment
Это фактический ответ, который я нашел наиболее оптимальным и реализовал его. Спасибо @arbutnott - person user3233791; 13.01.2018
comment
Я пытаюсь что-то вроде этого, но когда он запускается, он говорит, что обратный вызов уже был вызван - person Kevin Hernandez; 28.08.2019
comment
@KevinHernandez это было опубликовано для парусов 0.12 - не уверен, что v1 ведет себя по-другому. Ваша ошибка звучит так, будто cb() встречается дважды в одном из ваших обратных вызовов жизненного цикла. В моем ответе выше я избегаю этого, используя ранний возврат, например return cb(err). Попробуйте следовать вашей логике и посмотрите, можно ли когда-нибудь вызвать обратный вызов дважды. - person arbuthnott; 29.08.2019
comment
@arbuthnott Я понял это, функция была асинхронной, и у меня возникали странные условия гонки, потому что я не использовал ожидание. - person Kevin Hernandez; 29.08.2019