Skip to content

Commit

Permalink
Merge branch 'release/4.0.22'
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Nov 8, 2017
2 parents 38587fa + 2356b71 commit bb64d8c
Show file tree
Hide file tree
Showing 13 changed files with 330 additions and 49 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -5,4 +5,5 @@ npm-debug.log
.idea
out
.nyc_output
test/tmp
test/**/tmp
test/functional/database
17 changes: 17 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,20 @@
<a name="4.0.22"></a>
## [4.0.22](https://github.com/adonisjs/adonis-lucid/compare/v4.0.21...v4.0.22) (2017-11-08)


### Bug Fixes

* **belongsToMany:** do not select all fields for aggregates ([5e58e38](https://github.com/adonisjs/adonis-lucid/commit/5e58e38)), closes [#216](https://github.com/adonisjs/adonis-lucid/issues/216)
* **schema:** this.raw should reference this.schema.raw ([dcfc265](https://github.com/adonisjs/adonis-lucid/commit/dcfc265)), closes [#212](https://github.com/adonisjs/adonis-lucid/issues/212)


### Features

* **belongsToMany:** add countDistinct method ([#224](https://github.com/adonisjs/adonis-lucid/issues/224)) ([26cca0e](https://github.com/adonisjs/adonis-lucid/commit/26cca0e))
* **traits:** allow user to pass options to `addTrait` ([be987ca](https://github.com/adonisjs/adonis-lucid/commit/be987ca))



<a name="4.0.21"></a>
## [4.0.21](https://github.com/adonisjs/adonis-lucid/compare/v4.0.20...v4.0.21) (2017-10-29)

Expand Down
9 changes: 5 additions & 4 deletions package.json
@@ -1,13 +1,14 @@
{
"name": "@adonisjs/lucid",
"version": "4.0.21",
"version": "4.0.22",
"description": "SQL ORM built on top of Active Record pattern",
"main": "index.js",
"scripts": {
"lint": "standard",
"pretest": "npm run lint",
"posttest": "npm run coverage",
"test:local": "FORCE_COLOR=true DB=sqlite node bin/index.js --local",
"pretest": "npm run test:cleanup && npm run lint",
"test:cleanup": "rm -rf test/functional/database && rm -rf test/unit/tmp",
"posttest": "npm run test:cleanup && npm run coverage",
"test:local": "npm run test:cleanup && FORCE_COLOR=true DB=sqlite node bin/index.js --local",
"test": "nyc npm run test:local",
"test:win": "set FORCE_COLOR=true && node bin/index.js --win",
"coverage": "nyc report --reporter=text-lcov | coveralls"
Expand Down
6 changes: 5 additions & 1 deletion src/Lucid/Model/Base.js
Expand Up @@ -187,7 +187,9 @@ class BaseModel {
'$relations',
'$sideLoaded',
'$parent',
'$frozen'
'$frozen',
'$visible',
'$hidden'
]

this.$attributes = {}
Expand All @@ -197,6 +199,8 @@ class BaseModel {
this.$sideLoaded = {}
this.$parent = null
this.$frozen = false
this.$visible = this.constructor.visible
this.$hidden = this.constructor.hidden
}

/**
Expand Down
47 changes: 5 additions & 42 deletions src/Lucid/Model/index.js
Expand Up @@ -378,7 +378,7 @@ class Model extends BaseModel {
*
* @param {Function|String} trait - A plain function or reference to IoC container string
*/
static addTrait (trait) {
static addTrait (trait, options = {}) {
if (typeof (trait) !== 'function' && typeof (trait) !== 'string') {
throw GE
.InvalidArgumentException
Expand All @@ -390,7 +390,7 @@ class Model extends BaseModel {
*/
trait = typeof (trait) === 'string' ? `${trait}.register` : trait
const { method } = resolver.forDir('modelTraits').resolveFunc(trait)
method(this)
method(this, options)
}

/**
Expand Down Expand Up @@ -470,43 +470,6 @@ class Model extends BaseModel {
return !!this.$parent
}

/**
* Instantiate the model by defining constructor properties
* and also setting `__setters__` to tell the proxy that
* these values should be set directly on the constructor
* and not on the `attributes` object.
*
* @method instantiate
*
* @return {void}
*
* @private
*/
_instantiate () {
this.__setters__ = [
'$attributes',
'$persisted',
'primaryKeyValue',
'$originalAttributes',
'$relations',
'$sideLoaded',
'$parent',
'$frozen',
'$visible',
'$hidden'
]

this.$attributes = {}
this.$persisted = false
this.$originalAttributes = {}
this.$relations = {}
this.$sideLoaded = {}
this.$parent = null
this.$frozen = false
this.$visible = null
this.$hidden = null
}

/**
* Formats the date fields from the payload, only
* when they are marked as dates and there are
Expand Down Expand Up @@ -1326,13 +1289,13 @@ class Model extends BaseModel {
}

if (!this.isNew) {
const attributes = await this.constructor.find(this.primaryKeyValue)
if (!attributes) {
const newInstance = await this.constructor.find(this.primaryKeyValue)
if (!newInstance) {
throw GE
.RuntimeException
.invoke(`Cannot reload model since row with ${this.constructor.primaryKey} ${this.primaryKeyValue} has been removed`)
}
this.newUp(attributes)
this.newUp(newInstance.$attributes)
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/Lucid/Relations/BaseRelation.js
Expand Up @@ -21,6 +21,7 @@ const methodsList = [
'count',
'truncate',
'ids',
'paginate',
'pair',
'pluckFirst',
'pluckId',
Expand Down
89 changes: 89 additions & 0 deletions src/Lucid/Relations/BelongsToMany.js
Expand Up @@ -645,11 +645,100 @@ class BelongsToMany extends BaseRelation {
return this.relatedQuery.query
}

/**
* Adds `on` clause to the innerjoin context. This
* method is mainly used by HasManyThrough
*
* @method addWhereOn
*
* @param {Object} context
*/
addWhereOn (context) {
this._makeJoinQuery()
context.on(`${this.$primaryTable}.${this.primaryKey}`, '=', `${this.$pivotTable}.${this.foreignKey}`)
}

/**
* Prepare query for an aggregate function
*
* @method _prepareAggregate
*/
_prepareAggregate () {
this._validateRead()
this._makeJoinQuery()
this.wherePivot(this.foreignKey, this.$primaryKeyValue)
}

/**
* Returns count of rows.
*
* @method count
*
* @param {String} expression
*
* @return {Array}
*/
count (expression) {
this._prepareAggregate()
return this.relatedQuery.count(expression)
}

/**
* Returns count of rows with distinct expression.
*
* @method count
*
* @param {String} expression
*
* @return {Array}
*/
countDistinct (expression) {
this._prepareAggregate()
return this.relatedQuery.countDistinct(expression)
}

/**
* Returns avg for a given column
*
* @method avg
*
* @param {String} column
*
* @return {Array}
*/
avg (column) {
this._prepareAggregate()
return this.relatedQuery.avg(column)
}

/**
* Return min value for a column
*
* @method avg
*
* @param {String} column
*
* @return {Array}
*/
min (column) {
this._prepareAggregate()
return this.relatedQuery.min(column)
}

/**
* Return max value for a column
*
* @method avg
*
* @param {String} column
*
* @return {Array}
*/
max (column) {
this._prepareAggregate()
return this.relatedQuery.max(column)
}

/**
* Attach existing rows inside pivot table as a relationship
*
Expand Down
2 changes: 1 addition & 1 deletion src/Schema/index.js
Expand Up @@ -235,7 +235,7 @@ class Schema {
* @return {Object}
*/
raw (statement) {
return this.raw(statement)
return this.schema.raw(statement)
}

/**
Expand Down
51 changes: 51 additions & 0 deletions test/unit/lucid-belongs-to-many.spec.js
Expand Up @@ -9,6 +9,7 @@
* file that was distributed with this source code.
*/

require('../../lib/iocResolver').setFold(require('@adonisjs/fold'))
const test = require('japa')
const fs = require('fs-extra')
const path = require('path')
Expand Down Expand Up @@ -1712,4 +1713,54 @@ test.group('Relations | Belongs To Many', (group) => {

assert.equal(postQuery.sql, helpers.formatQuery('select "posts".*, "post_user"."post_id" as "pivot_post_id", "post_user"."user_id" as "pivot_user_id" from "posts" inner join "post_user" on "posts"."id" = "post_user"."post_id" where "post_user"."user_id" in (?, ?)'))
})

test('do not select all rows for a counts query', async (assert) => {
class Post extends Model {
}

class User extends Model {
posts () {
return this.belongsToMany(Post)
}
}

User._bootIfNotBooted()
Post._bootIfNotBooted()

await ioc.use('Database').table('users').insert({ id: 20, username: 'virk' })
await ioc.use('Database').table('posts').insert([{ id: 18, title: 'Adonis 101' }, { id: 19, title: 'Lucid 101' }])
await ioc.use('Database').table('post_user').insert([
{ post_id: 18, user_id: 20 },
{ post_id: 19, user_id: 20 }
])

const user = await User.find(20)
const postsCount = await user.posts().count('* as total')
assert.deepEqual(postsCount, [{ 'total': 2 }])
})

test('count distinct on given field', async (assert) => {
class Post extends Model {
}

class User extends Model {
posts () {
return this.belongsToMany(Post)
}
}

User._bootIfNotBooted()
Post._bootIfNotBooted()

await ioc.use('Database').table('users').insert({ id: 20, username: 'virk' })
await ioc.use('Database').table('posts').insert([{ id: 18, title: 'Adonis 101' }, { id: 19, title: 'Lucid 101' }])
await ioc.use('Database').table('post_user').insert([
{ post_id: 18, user_id: 20 },
{ post_id: 19, user_id: 20 }
])

const user = await User.find(20)
const postsCount = await user.posts().countDistinct('post_user.user_id as total')
assert.deepEqual(postsCount, [{ 'total': 1 }])
})
})
28 changes: 28 additions & 0 deletions test/unit/lucid-relations.spec.js
Expand Up @@ -43,6 +43,7 @@ test.group('Relations | HasOne', (group) => {
await ioc.use('Adonis/Src/Database').table('pictures').truncate()
await ioc.use('Adonis/Src/Database').table('identities').truncate()
await ioc.use('Adonis/Src/Database').table('cars').truncate()
await ioc.use('Adonis/Src/Database').table('posts').truncate()
})

group.after(async () => {
Expand Down Expand Up @@ -1078,6 +1079,33 @@ test.group('Relations | HasOne', (group) => {
assert.equal(userQuery.sql, helpers.formatQuery('select *, (select count(*) from "profiles" where users.id = profiles.user_id) as "profile_count" from "users" limit ?'))
})

test('return relation with paginate method', async (assert) => {
class Post extends Model {
users () {
return this.belongsToMany(User)
}
}
class User extends Model {
posts () {
return this.belongsToMany(Post)
}
}

User._bootIfNotBooted()
Post._bootIfNotBooted()

await ioc.use('Database').table('posts').insert([{ title: 'Post #1' }, { title: 'Post #2' }])
await ioc.use('Database').table('users').insert([{ username: 'virk' }, { username: 'nikk' }])
await ioc.use('Database').table('post_user').insert([{ user_id: 1, post_id: 2 }, { user_id: 2, post_id: 2 }])

const post = await Post.find(2)
const users = await post.users().paginate(1, 1)
assert.equal(users.pages.total, 2)
assert.equal(users.pages.page, 1)
assert.equal(users.pages.perPage, 1)
assert.equal(users.pages.lastPage, 2)
})

test('define count column for withCount', async (assert) => {
class Profile extends Model {
}
Expand Down

0 comments on commit bb64d8c

Please sign in to comment.