あいつの日誌β

働きながら旅しています。

sequelize tutorial(2) many to many

sequelize tutorial many to many

sequelize で many to many をするやり方を思い出しやすいようにメモに残します。

準備

http://okamuuu.hatenablog.com/entry/2016/03/25/163856

モデルを作成する

Role を準備します

$(npm bin)/sequelize model:create --name Role --attributes "name:string"
sed -i '' -e 's/\/\/ associations can be defined here/Todo.belongsToMany(models.User, {through: 'UserRole'});/' models/role.js
git add models migrations && git commit -m 'add new models'

それから User を編集します。

User.belongsToMany(models.Role, {through: 'UserRole'});

マイグレーションを実行

$(npm bin)/sequelize db:migrate 

テーブルが作成されている事を確認します。UserRole は後の作業で作成されます。

% sqlite3 db/development.db '.schema'
CREATE TABLE `SequelizeMeta` (`name` VARCHAR(255) NOT NULL UNIQUE PRIMARY KEY, UNIQUE (name));
CREATE TABLE `Roles` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL);
CREATE TABLE `Users` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `email` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL);
CREATE TABLE `Todos` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` VARCHAR(255), `complete` TINYINT(1), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `UserId` INTEGER REFERENCES `Users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE);

Fixture を作る

create test/fixture/role.js

cat << EOS > test/fixture/role.js
'use strict';

module.exports = (models) => {
  return models.Role.bulkCreate([
    {   
      id: 1,
      name: "admin"
    },  
    {   
      id: 2,
      name: "operator"
    }   
  ])  
}
EOS
cat << EOS > test/fixture/index.js
'use strict';

module.exports = (models) => {
  const Promise = models.Sequelize.Promise;

  return Promise.all([
    require('./role')(models), // role を追加
    require('./user')(models),
    require('./todo')(models)
  ])  
}
EOS

bin/sync を実行する

bin/sync

create example/user_role.js

cat << EOS > example/user_role.js
'use strict';

const co = require('co');
const models = require('../models');

co(function*() {
  console.log('=== before ===');
  let users = yield models.User.findAll({include: [models.Role]});
  users[0].Roles.forEach((role) => {
    console.log('user[0] ', role.name);
  });

  users[1].Roles.forEach((role) => {
    console.log('user[1] ', role.name);
  });

  const roles = yield models.Role.findAll();
  yield users[0].addRole(roles);
  yield users[1].addRole(roles[0]);

  console.log('=== after ===');

  users = yield models.User.findAll({include: [models.Role]});
  users[0].Roles.forEach((role) => {
    console.log('user[0] ', role.name);
  });

  users[1].Roles.forEach((role) => {
    console.log('user[1] ', role.name);
  });


}).catch(console.log);
EOS

実行する前に結果が見やすくなるように config/config.json で logging を false に設定します。

 {
   "development": {
     "dialect": "sqlite",
-    "storage": "./db/development.db"
-  },  
+    "storage": "./db/development.db",
+    "logging": false
+  },
   "test": {
     "dialect": "sqlite",
     "storage": "./db/test.db"
-  },  
+  },
   "production": {
     "dialect": "sqlite",
     "storage": "./db/production.db"

実行

:!node example/user_role.js
=== before ===
=== after ===
user[0]  admin
user[0]  operator
user[1]  admin

おしまい