sequelize / cli

The Sequelize CLI
MIT License
2.53k stars 526 forks source link

question: createdAt & updatedAt default value #414

Closed kissmygritts closed 7 years ago

kissmygritts commented 7 years ago

Why doesn't sequelize model:create foobar --attributes 'foo:string, bar:string add the default value now() to createdAt and updatedAt?

'use strict';
module.exports = {
  up: function(queryInterface, Sequelize) {
    return queryInterface.createTable('foobar', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      foo: {
        type: Sequelize.STRING
      },
      bar: {
        type: Sequelize.STRING
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: function(queryInterface, Sequelize) {
    return queryInterface.dropTable('foobar');
  }
};
tyler-canton commented 7 years ago

Check enabling 'timestamps:true' in your options. And why isn't your tables modular?

Create your tables like so:


 module.exports = (sequelize, Sequelize) => {
   const projects = sequelize.define('projects',
     {
      id: {
        type: Sequelize.UUID,
        allowNull: false,
        primaryKey: true,
        unique: true
      },
      uid: {
        type: Sequelize.UUID,
        allowNull: false,
        defaultValue: Sequelize.UUIDV4,

      },
      client: {
        type: Sequelize.STRING(255),
        allowNull: false
      },
      name: {
        type: Sequelize.STRING(255),
        allowNull: false
      },

    },
    {
      tableName: 'projects',
      freezeTableName: true,
      underscored: false,
      // don't forget to enable timestamps!
      timestamps: true,
      // I don't want createdAt
      createdAt: 'dateCreated',
      // I want updatedAt to actually be called updateTimestamp
      updatedAt: 'dateModified',
      // And deletedAt to be called destroyTime (remember to enable paranoid for this to work)
      deletedAt: 'dateDestroyed',
      // Paranoid will not delete tables from cascade only add delete to active

    });

  return projects;
};

Then do this:
'use strict';

let models = require('../Models/index');

module.exports = {
  up: function (queryInterface, Sequelize) {
    return Promise.resolve()
      .then(() => {
        return queryInterface.createTable(models.projects.tableName,
          models.projects.attributes, models.projects.options);
      }); 
  down: function (queryInterface, Sequelize) {
    return Promise.resolve()
      .then(() => {
        return queryInterface.dropAllTable();
      });
  }
};
EdByrnee commented 7 years ago

The CLI generates createdAt and updatedAt for the migrations, should we then also manually change each migration to include timestamps: true? I'm confused.

edit: the createdAt and updatedAt generated by the cli do not have any default values

kissmygritts commented 7 years ago

When the CLI generates createAt and updatedAt each of these should have a default prop for the current timestamp.

createdAt: {
        allowNull: false,
        type: Sequelize.DATE,
       default: now()
      }

I don't use sequelize anymore. So this can be closed as I appear to be the only one that wants this feature.

sushantdhiman commented 7 years ago

Adding default should not be required as Sequelize handles them and it doesnt use database default values for maintaining these fields

MikeDabrowski commented 6 years ago

Adding default should not be required as Sequelize handles them and it doesnt use database default values for maintaining these fields

It shouldn't yet I still have ERROR: Field 'createdAt' doesn't have a default value

'use strict';

module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      email: {
        type: Sequelize.STRING
      },
      password: {
        type: Sequelize.STRING
      },
      name: {
        type: Sequelize.STRING
      },
      lastName: {
        type: Sequelize.STRING
      },
      address: {
        type: Sequelize.STRING
      },
      phoneNumber: {
        type: Sequelize.STRING
      },
      position: {
        type: Sequelize.STRING
      },
      department: {
        type: Sequelize.STRING
      },
      createdAt: {
        type: Sequelize.DATE
      },
      updatedAt: {
        type: Sequelize.DATE
      }
    }, {
      indexes: [{
        unique: true,
        fields: ['email']
      }]
    });
  },

  down: (queryInterface, Sequelize) => {
    queryInterface.dropTable('users');
  }
};

This fails subsequent migrations, adds table users but doesn't add new row to SequelizeMeta making it impossible to revert migration

francof commented 6 years ago

This still fails. In a new project:

  1. node_modules/.bin/sequelize model:generate --name User --attributes username
  2. node_modules/.bin/sequelize db:migrate
  3. node_modules/.bin/sequelize seed:generate --name new-users
  4. edit seed to insert a user using bulkInsert following the generated example
  5. node_modules/.bin/sequelize db:seed:all gives ERROR: Field 'createdAt' doesn't have a default value
  6. edit model to include timestamps:true
  7. same error
francof commented 6 years ago

you can add
createdAt: new Date(), updatedAt: new Date() to all the seeds, but maybe it should be documented somewhere?

JontyC commented 6 years ago

I agree, the documentation contradicts what actually happens. Creating First Seed fails, as @francof said.

btronquo commented 5 years ago

Thanks @francof Is was a pain to me to understand what happened with these errors !!

Thanks again

OrderAndCh4oS commented 5 years ago

The suggestion from @francof is shown in the bulkInsert docs.

http://docs.sequelizejs.com/class/lib/query-interface.js~QueryInterface.html#instance-method-bulkInsert

queryInterface.bulkInsert('roles', [{
   label: 'user',
   createdAt: new Date(),
   updatedAt: new Date()
 }, {
   label: 'admin',
   createdAt: new Date(),
   updatedAt: new Date()
 }]);
gnorbsl commented 5 years ago

Stumbled over the same issue, please update the docs:

http://docs.sequelizejs.com/manual/migrations.html#creating-first-seed

This example wont work the way it is displayed now due to missing timestamps.

leejh3224 commented 5 years ago

This issue still happens. Document#Creating First Seed must be updated as follows.

'use strict';

module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.bulkInsert('Users', [{
        firstName: 'John',
        lastName: 'Doe',
        email: 'demo@demo.com',
        createdAt: new Date(),
        updatedAt: new Date()
      }], {});
  },

  down: (queryInterface, Sequelize) => {
    return queryInterface.bulkDelete('Users', null, {});
  }
};
zuoyi615 commented 5 years ago

Add defaultValue manually after generating the migration file, this issue will not happen.

'use strict';
// 20190620055759-create-user.js
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('Users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      username: {
        type: Sequelize.STRING
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE,
        defaultValue: new Date()
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE,
        defaultValue: new Date()
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('Users');
  }
};
ratijas commented 5 years ago

@zuoyi615 Wouldn't it set a default value to a hard-coded date at the time of execution? That's not what's happening with DEFAULT now() in e.g. PostgreSQL.