Reputation: 1349
I have below models
company.js
var Company = DB.Model.extend({
tableName: 'company',
hasTimestamps: true,
hasTimestamps: ['created_at', 'updated_at']
});
user.js
var User = DB.Model.extend({
tableName: 'user',
hasTimestamps: true,
hasTimestamps: ['created_at', 'updated_at'],
companies: function() {
return this.belongsToMany(Company);
}
});
With a many-to-many
relation between Company
and User
which handle via the following table in the database.
user_company.js
var UserCompany = DB.Model.extend({
tableName: 'user_company',
hasTimestamps: true,
hasTimestamps: ['created_at', 'updated_at'],
users: function() {
return this.belongsToMany(User);
},
companies: function() {
return this.belongsToMany(Company);
}
});
The problem is when I run following query.
var user = new User({ id: req.params.id });
user.fetch({withRelated: ['companies']}).then(function( user ) {
console.log(user);
}).catch(function( error ) {
console.log(error);
});
It logs following error because it is looking for company_user
table instead of user_company
.
{ [Error: select `company`.*, `company_user`.`user_id` as `_pivot_user_id`, `company_user`.`company_id` as `_pivot_company_id` from `company` inner join `company_user` on `company_user`.`company_id` = `company`.`id` where `company_user`.`user_id` in (2) - ER_NO_SUCH_TABLE: Table 'navardeboon.company_user' doesn't exist]
code: 'ER_NO_SUCH_TABLE',
errno: 1146,
sqlState: '42S02',
index: 0 }
Is there any way to tell it to look for a certain table while fetching relations?
Upvotes: 2
Views: 1060
Reputation: 1349
Actually I found a very simple solution for it. You just need to mention table name like this:
var User = DB.Model.extend({
tableName: 'user',
hasTimestamps: true,
hasTimestamps: ['created_at', 'updated_at'],
companies: function() {
return this.belongsToMany(Company, **'user_company'**);
}
})
and as @uglycode said, no need to have UserCompany
model anymore.
Upvotes: 0
Reputation: 3082
With Bookshelf.js it is VERY important, how the tables and ids are named in your database. Bookshelf.js does some interesting things with foreign keys (i.e. converts it to singular and appends _id
).
When using Bookshelfjs's many-to-many feature, you don't need UserCompany
model. However, you need to following the naming conventions of the tables and ids for this to work.
Here's an example of many-to-many models. Firstly, the database:
exports.up = function(knex, Promise) {
return knex.schema.createTable('books', function(table) {
table.increments('id').primary();
table.string('name');
}).createTable('authors', function(table) {
table.increments('id').primary();
table.string('name');
}).createTable('authors_books', function(table) {
table.integer('author_id').references('authors.id');
table.integer('book_id').references('books.id');
});
};
Please note how the junction table is named: alphabetically ordered (authors_books
). If you'd write books_authors
, the many-to-many features wouldn't work out of the box (you'd have to specify the table name explicitly in the model). Also note the foreign keys (singular of authors
with _id
appended, i.e. author_id).
Now let's look at the models.
var Book = bookshelf.Model.extend({
tableName: 'books',
authors: function() {
return this.belongsToMany(Author);
}
});
var Author = bookshelf.Model.extend({
tableName: 'authors',
books: function() {
return this.belongsToMany(Book);
}
});
Now that our database has the correct naming of the tables and ids, we can just use belongsToMany and this works! There is no need for a AuthorBook
model, Bookshelf.js does this for you!
Here's the advanced description: http://bookshelfjs.org/#Model-instance-belongsToMany
Upvotes: 2