Skip to content

Commit

Permalink
Merge pull request bookshelf#2 from jadengore/update-to-0.8.2
Browse files Browse the repository at this point in the history
Update to Bookshelf 0.8.2
  • Loading branch information
ebramanti committed Sep 17, 2015
2 parents 0787f16 + bd55089 commit 3226898
Show file tree
Hide file tree
Showing 64 changed files with 13,752 additions and 3,625 deletions.
28 changes: 28 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"parser": "babel-eslint",
"env": {
"es6": true,
"node": true
},
"ecmaFeatures": {
"destructuring": true,
"modules": true
},
"rules": {
"quotes": 0,
"curly": 0,
"camelcase": 0,
"semi": 0,
"eol-last": 0,
"key-spacing": 0,
"new-cap": 0,
"comma-dangle": 0,
"consistent-return": 0,
"no-proto": 0,
"no-use-before-define": 0,
"no-trailing-spaces": 0,
"no-multi-spaces": 0,
"no-mixed-requires": 0,
"no-underscore-dangle": 0
}
}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ raw
.DS_Store
node_modules
npm-debug.log
tmp
tmp
docs/html
17 changes: 0 additions & 17 deletions .jshintrc

This file was deleted.

169 changes: 165 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,182 @@
## How to contribute to Bookshelf.js

* Before sending a pull request for a feature or bug fix, be sure to have
[tests](https://github.com/tgriesser/bookshelf/tree/master/test).
[tests](https://github.com/tgriesser/bookshelf/tree/master/test).

* Use the same coding style as the rest of the
[codebase](https://github.com/tgriesser/bookshelf/blob/master/bookshelf.js).
[codebase](https://github.com/tgriesser/bookshelf/blob/master/src/bookshelf.js).

* Make changes in the /src directory, running "npm run dev" which will kick off
transpilation from ES6 in the background

* Files in the `/browser` folder are built automatically. You don't need to edit them.

* All pull requests should be made to the `master` branch.

### Development Environment Setup

You'll need to have `git` installed obviously. Begin by forking the [main
repository](https://github.com/tgriesser/bookshelf) and then getting the code from your forked copy:

```sh
$ git clone git@github.com:yourusername/bookshelf.git
```

Afterwards go to the bookshelf directory that was just created and install the dependencies:

```sh
$ npm install
```

At this point the only thing missing are the databases that will be used for running some of the tests of the automated
test suite.

There are two options for setting up this part. The first one is to change some configuration options of the database
servers and the other is to use a config file in case you already have your servers configured and don't want to change
any of their config files. The first two sections below deal with the first option and then there are instructions on
how to use the other option.

#### MySQL

You can install [MySQL](https://www.mysql.com/) easily on most linux distros by using their package manager. With Ubuntu
this should do it:

```sh
$ sudo apt-get install mysql-server mysql-client
```

On OSX you can download a disk image directly from the [MySQL Downloads page](http://dev.mysql.com/downloads/mysql/), or
use one of the popular package managers like [homebrew](http://brew.sh/) or [MacPorts](https://www.macports.org/).

To run the test suite you will need to make sure it is possible to connect as the user `root` without the need for a
password.

It is strongly recommended that you use the command line `mysql` client to access your MySQL instance since there can be
problems connecting as the root user with some graphical clients like `phpMyAdmin`. To check if you can connect as root
without needing a password use the following command:

```sh
$ mysql -u root
```

If you see an error like:

```sh
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
```

that means you can't login as root without a password. If you do know the root user's password just login with the known
password like this:

```sh
$ mysql -u root -p
```

and enter the password when asked. Then just set an empty password for root like so:

```SQL
USE mysql;
UPDATE user SET password = "" WHERE User = "root";
FLUSH PRIVILEGES;
QUIT;
```

Note that you'll probably need to set the password to `NULL` instead of an empty string in MySQL versions 5.5 and older.
The above example should work with versions 5.6 and newer.

If you have forgotten the root password you'll need to take some extra steps to reset it. Take a look at
[this Stack Overflow answer](http://stackoverflow.com/a/7825212/504930) for further details.

#### PostgreSQL

You can install [PostgreSQL](http://www.postgresql.org/) easily on most linux distros by using their package manager.
With Ubuntu this should do it:

```sh
$ sudo apt-get install postgresql postgresql-client
```

On OSX the easiest way is probably by using [PosgresApp](http://postgresapp.com/). It should also be available to
install via [homebrew](http://brew.sh/) or [MacPorts](https://www.macports.org/) if you prefer.

In the case of PostgreSQL the requirement is to be able to connect as the `postgres` user on localhost also without the
need for a password. This can be achieved by editing or adding the following line in the `pg_hba.conf` file:

```
host all all 127.0.0.1/32 trust
```

This file can be found in `/etc/postgresql/9.4/main/` on most linux systems. The `9.4` part could be different depending
on the version that is available in your distro. On OSX the location of this file will depend on the installation method
chosen, but for the recommended PostgresApp install it will be in `/Users/[yourusername]/Library/Application
Support/Postgres/var-9.3/`. Again, the `var-9.3` part may be different depending on the version you installed.

The `trust` in the example above tells the locally running PostgreSQL server to ignore user passwords and always grant
access on clients connecting locally. Do not use this setting in a production environment.

After editing the `pg_hba.conf` file you'll need to restart the PostgreSQL server for the changes to take effect.

#### Using a config file

If you don't want to go to the trouble of performing the changes explained in the previous two sections you can instead
use a config file that tells the test suite about your database setup.

The tests will look for a `BOOKSHELF_TEST` environment variable that points to a `config.js` file with the connection
details for each database server. This file must not be the same database config file you use for any other application,
otherwise you risk data loss in that application.

Example config file:

```javascript
module.exports = {
mysql: {
database: 'bookshelf_test',
user: 'root',
encoding: 'utf8'
},

postgres: {
user: 'myusername',
database: 'bookshelf_test',
password: 'secretpassword',
host: 'localhost',
port: 5432,
charset: 'utf8',
ssl: false
},

sqlite3: {
filename: ':memory:'
}
};
```

This file can be placed anywhere on your system and can have any name that you like, as long as the environment variable
is pointing correctly to it. For convenience you can put it in your home directory and add the following line to your
`.bashrc` or `.zshrc`:

```
export BOOKSHELF_TEST='/home/myusername/.bookshelf_config.js'
```

#### Database creation

After having ensured the test suite can access both database servers just create a new database on each that will be
used exclusively by Bookshelf.js:

```SQL
CREATE DATABASE bookshelf_test;
```

### Running the Tests

The test suite requires you to create a [MySQL](https://www.mysql.com/) and [Postgres](http://www.postgresql.org/) database named `bookshelf_test`.
The test suite requires that both MySQL and PostgreSQL servers have a database named `bookshelf_test`. See the sections
above for further instructions.

Once you have done that, you can run the tests:

```sh
$ npm test
```
```

Always make sure all the tests are passing before sending a pull request.
114 changes: 105 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,71 @@
# [bookshelf.js](http://bookshelfjs.org) [![Build Status](https://travis-ci.org/tgriesser/bookshelf.svg?branch=master)](https://travis-ci.org/tgriesser/bookshelf)

Bookshelf is a Node.js ORM with support for PostgreSQL, MySQL / MariaDB, and SQLite3.
Bookshelf is a JavaScript ORM for Node.js, built on the [Knex](http://knexjs.org) SQL query builder. Featuring both promise based and traditional callback interfaces, it follows the Model & Collection patterns seen in [Backbone.js](http://backbonejs.com), providing transaction support, eager/nested-eager relation loading, polymorphic associations, and support for one-to-one, one-to-many, and many-to-many relations.

It is built atop the <a href="http://knexjs.org">Knex query builder</a>,
and is strongly influenced by the Model and Collection foundations of Backbone.js.
It is designed to work well with PostgreSQL, MySQL, and SQLite3.

It features [transaction support](http://bookshelfjs.org/#Bookshelf-transaction), one-to-one, one-to-many, many-to-many, and polymorphic relations.
The project is [hosted on GitHub](http://github.com/tgriesser/bookshelf/), and has a comprehensive [test suite](https://travis-ci.org/tgriesser/bookshelf).

For documentation, FAQs, and other information, see: http://bookshelfjs.org.
## Introduction

To suggest a feature, report a bug, or for general discussion: http://github.com/tgriesser/bookshelf/issues/
Bookshelf aims to provide a simple library for common tasks when querying databases in JavaScript, and forming relations between these objects, taking a lot of ideas from the the [Data Mapper Pattern](http://en.wikipedia.org/wiki/Data_mapper_pattern). With a concise, literate codebase, Bookshelf is simple to read, understand, and extend. It doesn't force you to use any specific validation scheme, provides flexible and efficient relation/nested-relation loading, and first class transaction support. It's a lean Object Relational Mapper, allowing you to drop down to the raw knex interface whenever you need a custom query that doesn't quite fit with the stock conventions.

Bookshelf follows the excellent foundation provided by Backbone.js Models and Collections, using similar patterns, naming conventions, and philosophies to build a lightweight, easy to navigate ORM. If you know how to use Backbone, you probably already know how to use Bookshelf.

## Installation

You'll need to install a copy of [knex.js](http://knexjs.org/), and either mysql, pg, or sqlite3 from npm.

```js
$ npm install knex --save
$ npm install bookshelf --save

# Then add one of the following:
$ npm install pg
$ npm install mysql
$ npm install mariasql
$ npm install sqlite3
```

The Bookshelf library is initialized by passing an initialized [Knex](http://knexjs.org/) client instance. The [knex documentation](http://knexjs.org/) provides a number of examples for different databases.

```js
var knex = require('knex')({
client: 'mysql',
connection: {
host : '127.0.0.1',
user : 'your_database_user',
password : 'your_database_password',
database : 'myapp_test',
charset : 'utf8'
}
});

var bookshelf = require('bookshelf')(knex);

var User = bookshelf.Model.extend({
tableName: 'users'
});
```

This initialization should likely only ever happen once in your application. As it creates a connection pool for the current database, you should use the `bookshelf` instance returned throughout your library. You'll need to store this instance created by the initialize somewhere in the application so you can reference it. A common pattern to follow is to initialize the client in a module so you can easily reference it later:

```js
// In a file named something like bookshelf.js
var knex = require('knex')(dbConfig);
module.exports require('bookshelf')(knex);

// elsewhere, to use the bookshelf client:
var bookshelf = require('./bookshelf');

var Post = bookshelf.Model.extend({
// ...
});
```

## Examples

We have several examples [on the website](http://bookshelfjs.org). Here is the first one to get you started:
Here is an example to get you started:

```js
var knex = require('knex')({client: 'mysql', connection: process.env.MYSQL_DATABASE_CONNECTION });
Expand Down Expand Up @@ -48,6 +100,50 @@ User.where('id', 1).fetch({withRelated: ['posts.tags']}).then(function(user) {
});
```

## Contributing
## Plugins

- [Registry](https://github.com/tgriesser/bookshelf/wiki/Plugin:-Model-Registry): Register models in a central location so that you can refer to them using a string in relations instead of having to require it every time. Helps deal with the challenges of circular module dependencies in Node.
- [Virtuals](https://github.com/tgriesser/bookshelf/wiki/Plugin:-Virtuals): Define virtual properties on your model to compute new values.
- [Visibility](https://github.com/tgriesser/bookshelf/wiki/Plugin:-Visibility): Specify a whitelist/blacklist of model attributes when serialized toJSON.

## Support

Have questions about the library? Come join us in the [#bookshelf freenode IRC channel](http://webchat.freenode.net/?channels=bookshelf) for support on [knex.js](http://knexjs.org/) and bookshelf.js, or post an issue on [Stack Overflow](http://stackoverflow.com/questions/tagged/bookshelf.js) or in the GitHub [issue tracker](https://github.com/tgriesser/bookshelf/issues).

## F.A.Q.

### Can I use standard node.js style callbacks?

Yes - you can call `.asCallback(function(err, resp) {` on any "sync" method and use the standard `(err, result)` style callback interface if you prefer.

### My relations don't seem to be loading, what's up?

Make sure you check that the type is correct for the initial parameters passed to the initial model being fetched. For example `new Model({id: '1'}).load([relations...])` will not return the same as `Model({id: 1}).load([relations...])` - notice that the id is a string in one case and a number in the other. This can be a common mistake if retrieving the id from a url parameter.

This is only an issue if you're eager loading data with load without first fetching the original model. `Model({id: '1'}).fetch({withRelated: [relations...]})` should work just fine.

### My process won't exit after my script is finished, why?

The issue here is that Knex, the database abstraction layer used by Bookshelf, uses connection pooling and thus keeps the database connection open. If you want your process to exit after your script has finished, you will have to call `.destroy(cb)` on the `knex` property of your `Bookshelf` instance or on the `Knex` instance passed during initialization. More information about connection pooling can be found over at the [Knex docs](http://knexjs.org/#Installation-pooling).

### How do I debug?

If you pass `{debug: true}` as one of the options in your initialize settings, you can see all of the query calls being made. Sometimes you need to dive a bit further into the various calls and see what all is going on behind the scenes. I'd recommend [node-inspector](https://github.com/dannycoates/node-inspector), which allows you to debug code with `debugger` statements like you would in the browser.

Bookshelf uses its own copy of the "bluebird" promise library, you can read up here for more on debugging these promises... but in short, adding:

process.stderr.on('data', function(data) {
console.log(data);
});

At the start of your application code will catch any errors not otherwise caught in the normal promise chain handlers, which is very helpful in debugging.

### How do I run the test suite?

The test suite looks for an environment variable called `BOOKSHELF_TEST` for the path to the database configuration. If you run the following command: `$ export BOOKSHELF_TEST='/path/to/your/bookshelf_config.js'`, replacing with the path to your config file, and the config file is valid, the test suite should run with npm test.

Also note that you will have to create the appropriate database(s) for the test suite to run. For example, with MySQL, you'll need to run the command `create database bookshelf_test;` in addition to exporting the correct test settings prior to running the test suite.

### Can I use Bookshelf outside of Node.js?

To contribute to Bookshelf, read the [contribution documentation](CONTRIBUTING.md) for more information.
While it primarily targets Node.js, all dependencies are browser compatible, and it could be adapted to work with other javascript environments supporting a sqlite3 database, by providing a custom [Knex adapter](http://knexjs.org/#Adapters).
17 changes: 10 additions & 7 deletions bookshelf.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// Bookshelf.js 0.8.1
// ---------------

// (c) 2014 Tim Griesser
// Bookshelf may be freely distributed under the MIT license.
// For all details and documentation:
// http://bookshelfjs.org
module.exports = require('./lib')
/**
* (c) 2014 Tim Griesser
* Bookshelf may be freely distributed under the MIT license.
* For all details and documentation:
* http://bookshelfjs.org
*
* version 0.8.1
*
*/
module.exports = require('./lib/bookshelf')

0 comments on commit 3226898

Please sign in to comment.