不要怂,就是干,撸起袖子干!

scope.test.js 10.6 KB
"use strict";

/* jshint camelcase: false, expr: true */
var chai      = require('chai')
  , expect    = chai.expect
  , Support   = require(__dirname + '/../support')
  , DataTypes = require(__dirname + "/../../lib/data-types")
  , Sequelize = require('../../index')
  , Promise   = Sequelize.Promise
  , assert    = require('assert');

chai.config.includeStack = true;

describe(Support.getTestDialectTeaser("associations"), function() {
  describe('scope', function () {
    beforeEach(function () {
      this.Post = this.sequelize.define('post', {});
      this.Image = this.sequelize.define('image', {});
      this.Question = this.sequelize.define('question', {});
      this.Comment = this.sequelize.define('comment', {
        title: Sequelize.STRING,
        commentable: Sequelize.STRING,
        commentable_id: Sequelize.INTEGER
      }, {
        instanceMethods: {
          getItem: function() {
            return this['get'+this.get('commentable').substr(0, 1).toUpperCase()+this.get('commentable').substr(1)]();
          }
        }
      });
      this.Tag = this.sequelize.define('tag', {
        name: Sequelize.STRING,
        taggable: Sequelize.STRING,
        taggable_id: Sequelize.INTEGER
      });

      this.Post.hasMany(this.Comment, {
        foreignKey: 'commentable_id',
        scope: {
          commentable: 'post'
        }
      });
      this.Comment.belongsTo(this.Post, {
        foreignKey: 'commentable_id',
        as: 'post',
        scope: {
          commentable: 'post'
        }
      });

      this.Image.hasMany(this.Comment, {
        foreignKey: 'commentable_id',
        scope: {
          commentable: 'image'
        }
      });
      this.Comment.belongsTo(this.Image, {
        foreignKey: 'commentable_id',
        as: 'image',
        scope: {
          commentable: 'image'
        }
      });

      this.Question.hasMany(this.Comment, {
        foreignKey: 'commentable_id',
        scope: {
          commentable: 'question'
        }
      });
      this.Comment.belongsTo(this.Question, {
        foreignKey: 'commentable_id',
        as: 'question',
        scope: {
          commentable: 'question'
        }
      });
    });
    
    describe('1:M', function () {
      it('should create, find and include associations with scope values', function () {
        var self = this;
        return this.sequelize.sync({force: true}).then(function () {
          return Promise.join(
            self.Post.create(),
            self.Image.create(),
            self.Question.create(),
            self.Comment.create({
              title: 'I am a image comment'
            }),
            self.Comment.create({
              title: 'I am a question comment'
            })
          );
        }).bind(this).spread(function (post, image, question, commentA, commentB) {
          this.post = post;
          this.image = image;
          this.question = question;
          return Promise.join(
            post.createComment({
              title: 'I am a post comment'
            }),
            image.addComment(commentA),
            question.setComments([commentB])
          );
        }).then(function () {
          return self.Comment.findAll();
        }).then(function (comments) {
          comments.forEach(function (comment) {
            expect(comment.get('commentable')).to.be.ok;
          });
          expect(comments.map(function (comment) {
            return comment.get('commentable');
          }).sort()).to.deep.equal(['image', 'post', 'question']);
        }).then(function () {
          return Promise.join(
            this.post.getComments(),
            this.image.getComments(),
            this.question.getComments()
          );
        }).spread(function (postComments, imageComments, questionComments) {
          expect(postComments.length).to.equal(1);
          expect(postComments[0].get('title')).to.equal('I am a post comment');
          expect(imageComments.length).to.equal(1);
          expect(imageComments[0].get('title')).to.equal('I am a image comment');
          expect(questionComments.length).to.equal(1);
          expect(questionComments[0].get('title')).to.equal('I am a question comment');

          return [postComments[0], imageComments[0], questionComments[0]];
        }).spread(function (postComment, imageComment, questionComment) {
          return Promise.join(
            postComment.getItem(),
            imageComment.getItem(),
            questionComment.getItem()
          );
        }).spread(function (post, image, question) {
          expect(post.Model).to.equal(self.Post);
          expect(image.Model).to.equal(self.Image);
          expect(question.Model).to.equal(self.Question);
        }).then(function () {
          return Promise.join(
            self.Post.find({
              include: [self.Comment]
            }),
            self.Image.find({
              include: [self.Comment]
            }),
            self.Question.find({
              include: [self.Comment]
            })
          );
        }).spread(function (post, image, question) {
          expect(post.comments.length).to.equal(1);
          expect(post.comments[0].get('title')).to.equal('I am a post comment');
          expect(image.comments.length).to.equal(1);
          expect(image.comments[0].get('title')).to.equal('I am a image comment');
          expect(question.comments.length).to.equal(1);
          expect(question.comments[0].get('title')).to.equal('I am a question comment');
        });
      });
    });
  
    if (Support.getTestDialect() !== 'sqlite') {
      describe('N:M', function () {
        describe('on the target', function () {
          beforeEach(function () {
            this.Post = this.sequelize.define('post', {});
            this.Tag = this.sequelize.define('tag', {
              type: DataTypes.STRING
            });
            this.PostTag = this.sequelize.define('post_tag');

            this.Tag.hasMany(this.Post, {through: this.PostTag});
            this.Post.hasMany(this.Tag, {as: 'categories', through: this.PostTag, scope: { type: 'category' }});
            this.Post.hasMany(this.Tag, {as: 'tags', through: this.PostTag, scope: { type: 'tag' }});
          });
          it('should create, find and include associations with scope values', function () {
            var self = this;
            return Promise.join(
              self.Post.sync({force: true}),
              self.Tag.sync({force: true})
            ).bind(this).then(function () {
              return self.PostTag.sync({force: true});
            }).then(function () {
              return Promise.join(
                self.Post.create(),
                self.Post.create(),
                self.Post.create(),
                self.Tag.create({type: 'category'}),
                self.Tag.create({type: 'category'}),
                self.Tag.create({type: 'tag'}),
                self.Tag.create({type: 'tag'})
              );
            }).spread(function (postA, postB, postC, categoryA, categoryB, tagA, tagB) {
              this.postA = postA;
              this.postB = postB;
              this.postC = postC;

              return Promise.join(
                postA.addCategory(categoryA),
                postB.setCategories([categoryB]),
                postC.createCategory(),
                postA.createTag(),
                postB.addTag(tagA),
                postC.setTags([tagB])
              );
            }).then(function () {
              return Promise.join(
                this.postA.getCategories(),
                this.postA.getTags(),
                this.postB.getCategories(),
                this.postB.getTags(),
                this.postC.getCategories(),
                this.postC.getTags()
              );
            }).spread(function (postACategories, postATags, postBCategories, postBTags, postCCategories, postCTags) {
              expect(postACategories.length).to.equal(1);
              expect(postATags.length).to.equal(1);
              expect(postBCategories.length).to.equal(1);
              expect(postBTags.length).to.equal(1);
              expect(postCCategories.length).to.equal(1);
              expect(postCTags.length).to.equal(1);

              expect(postACategories[0].get('type')).to.equal('category');
              expect(postATags[0].get('type')).to.equal('tag');
              expect(postBCategories[0].get('type')).to.equal('category');
              expect(postBTags[0].get('type')).to.equal('tag');
              expect(postCCategories[0].get('type')).to.equal('category');
              expect(postCTags[0].get('type')).to.equal('tag');
            }).then(function () {
              return Promise.join(
                self.Post.find({
                  where: {
                    id: self.postA.get('id')
                  },
                  include: [
                    {model: self.Tag, as: 'tags'},
                    {model: self.Tag, as: 'categories'}
                  ]
                }),
                self.Post.find({
                  where: {
                    id: self.postB.get('id')
                  },
                  include: [
                    {model: self.Tag, as: 'tags'},
                    {model: self.Tag, as: 'categories'}
                  ]
                }),
                self.Post.find({
                  where: {
                    id: self.postC.get('id')
                  },
                  include: [
                    {model: self.Tag, as: 'tags'},
                    {model: self.Tag, as: 'categories'}
                  ]
                })
              );
            }).spread(function (postA, postB, postC) {
              //console.log(postA.get('categories'));
              expect(postA.get('categories').length).to.equal(1);
              expect(postA.get('tags').length).to.equal(1);
              expect(postB.get('categories').length).to.equal(1);
              expect(postB.get('tags').length).to.equal(1);
              expect(postC.get('categories').length).to.equal(1);
              expect(postC.get('tags').length).to.equal(1);

              expect(postA.get('categories')[0].get('type')).to.equal('category');
              expect(postA.get('tags')[0].get('type')).to.equal('tag');
              expect(postB.get('categories')[0].get('type')).to.equal('category');
              expect(postB.get('tags')[0].get('type')).to.equal('tag');
              expect(postC.get('categories')[0].get('type')).to.equal('category');
              expect(postC.get('tags')[0].get('type')).to.equal('tag');
            });
          });
        });

        describe.skip('on the through model', function () {
          it('should create, find and include associations with scope values', function () {

          });
        });
      });
    }
  });
});