LoginSignup
1
2

More than 5 years have passed since last update.

Bookshelfでpolymorphic association

Last updated at Posted at 2013-11-30

BackboneベースのORM Bokshelfpolymorphic associationです。

$ mkdir bookshelf-polymorphic-association
$ cd  bookshelf-polymorphic-association
$ vi package.json

package.json:

{
  "name": "bookshelf-polymorphic-association",
  "version": "0.0.0",
  "main": "index.js",
  "dependencies": {
    "bookshelf": "~0.6.1",
    "knex": "git+https://github.com/tgriesser/knex.git",
    "sqlite3": "~2.1.19"
  }
}

モジュールのインストール:

$ npm install

テーブルの作成

Bookshelfが利用しているknexがマイグレーションをサポートしているのでこれを使います。

設定ファイルの作成

$ mkdir db
$ vi db/config.js

db/config.js:

module.exports = {
  directory: './db/migrations',
  database: {
    client: 'sqlite3',
    connection: {
      filename: './db/bookshelf-polymorphic-association.db'
    }
  }
};

マイグレーション作成

$ ./node_modules/.bin/knex migrate:make create -c ./db/config.js 
$ vi 20131130140239_create.js

20131130140239_create.js:

exports.up = function(knex, Promise) {
  return Promise.all([
    knex.schema.createTable('employees', function(t) {
      t.increments('id').primary();
      t.string('name');
    }),

    knex.schema.createTable('products', function(t) {
      t.increments('id').primary();
      t.string('name');
    }),

    knex.schema.createTable('pictures', function(t) {
      t.increments('id').primary();
      t.string('name');
      t.integer('imageable_id').notNull();
      t.string('imageable_type').notNull();
    })
  ]);
};

exports.down = function(knex, Promise) {
  return Promise.all([
    knex.schema.dropTable('employees'),

    knex.schema.dropTable('products'),

    knex.schema.dropTable('pictures')
  ]);
};

マイグレーション実行

$ ./node_modules/.bin/knex migrate:latest -c ./db/config.js

本題

index.js:

var config = require('./db/config').database,
    Bookshelf = require('bookshelf').initialize(config);

var Employee = Bookshelf.Model.extend({
  tableName: 'employees',
  pictures: function() {
    return this.morphMany(Picture, 'imageable');
  }
});

var Product = Bookshelf.Model.extend({
  tableName: 'products',
  pictures: function() {
    return this.morphMany(Picture, 'imageable');
  }
});

var Picture = Bookshelf.Model.extend({
  tableName: 'pictures',
  imageable: function() {
    return this.morphTo('imageable', Employee, Product);
  }
});

// Employeeを作成
new Employee({ name: 'hoge' }).save()

  // employeeのPictureを作成
  .then(function(employee) {
    var picture = new Picture({
      name: 'employee\'s picture',
      imageable_id: employee.id,
      imageable_type: 'employees'
    });

    return [picture.save(), employee];
  })

  // employeeをPicture毎フェッチしてみる
  .spread(function(picture, employee) {
    return employee.fetch({ withRelated: ['pictures'] });
  })
  .tap(function(employee) {
    console.log(employee.toJSON());
  })

  // 今度はProductを作成
  .then(function() {
    return new Product({ name: 'piyo' }).save();
  })

  // productのPictureを作成
  .then(function(product) {
    var picture = new Picture({
      name: 'product\'s picture',
      imageable_id: product.id,
      imageable_type: 'products'
    });

    return [picture.save(), product];
  })

  // productをPicture毎フェッチしてみる
  .spread(function(picture, product) {
    return product.fetch({ withRelated: ['pictures'] });
  })
  .tap(function(employee) {
    console.log(employee.toJSON());
  })

  .then(function() {
    process.exit();
  });

実行

$ node index.js
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2