active_record

Rails ActiveRecord inspired for Nodejs.

ActiveRecord Nodejs

Rails ActiveRecord inspired for Nodejs.

0.1.4
npm install active_record
var ActiveRecord = require('active_record');
 
ActiveRecord.Base.configure_connection({
    driver: 'mysql',
    hostname: 'localhost',
    port: 3306,
    user: 'root',
    password: '',
    database: 'active_record'
    pool: true,
    'pool config': { min: 1, max: 20 }
});

or

ActiveRecord.Base.connection.config({ env: 'test' }); // Set Enviroment; *Default: 'dev' 
ActiveRecord.Base.configure_connection('path/to/database.json');
 
/* JSON file example: */
{
  "dev": {
    "driver": "mysql",
    "hostname": "localhost",
    "port": "3306",
    "user": "root",
    "password": "",
    "database": "chat"
  },
 
  "test": {
    "driver": "sqlite3",
    "filename": "./database"
  },
 
  "prod": {
    "driver": "postgres",
    "user": "test",
    "password": "test",
    "hostname": "localhost",
    "database": "mydb"
  }
}
ActiveRecord.Base.establish_connection([callback]);

Equal to the RAILS each model is a separate file. But you can create a single connection file and configuration of models, as follows in the examples below. Takes also that the file names are singular. Example 1: For each model create a separate file.

var ActiveRecord = require('active_record');
/* Exports the module */
module.exports = User
/* Extends the module to ActiveRecord.Base */
ActiveRecord.Base.extend(User, ActiveRecord.Base)
/* Create the Class */
function User (){
    /* Initialize the instance variables */
    this.initialize(arguments[0]);
    /** Validations */
    this.validates('name', {
        presence: true,
        length: { minimum: 6, maximum: 25 }
    })
    this.validate_length_of('password', {minimum: 5});
    this.has_secure_password(); /* Call this function after another validations */
}
 
/* Configure the model */
User.table_name = 'users';
User.fields('name', 'password'); // Create dynamics finders: User.find_by_name, etc. 
/* Configure the Associations */
User.has_many('phones');

Example 2: Configuration in a single file

var ActiveRecord = require('../index');
ActiveRecord.Base.configure_connection('./database.json');
ActiveRecord.Base.establish_connection();
/* Don't forget: Exports the models */
exports.User = User;
exports.Phone = Phone;
 
ActiveRecord.Base.extend(User, ActiveRecord.Base);
ActiveRecord.Base.extend(Phone, ActiveRecord.Base);
 
function User (){
    this.initialize(arguments[0]);
}
 
function Phone (){
    this.initialize(arguments[0]);
}
 
User.has_many('phones');
Phone.belongs_to('user');
 
ActiveRecord.Base.close_connection();
/* Create, Update, Destroy */
User.create({ name: 'Foo', password: 'Bar' }, function(data){ ... })
User.update(2, {name: 'Bar', password: 'Foo'}, function(data){ ... })
User.destroy(1, function(data){ ... })
 
/* Finders */
User.find([1,2,3], function(errordata){ ... })
User.where("name = 'foo'", function(errordata){ ... })
 
/* Calculations */
User.count('*', function (errordata){ ... })
 
/** Associations
* User.has_many('phones') */
User.find(1, function (erroruser){
    user[0]
    .phones(function (errorphonePhone){
        /* Phone.belongs_to('user') */
        phone[0].user(console.log)
    })
    .create({ // @return Phone 
        number: "(66)9999-9999"
    });
 
})
 
/* Callbacks */
User.before_find(function (queryvaluesoptions){ ... })

API

ActiveRecord Global config options

  • logger: Not implemented
  • primary_key_prefix_type:
  • table_name_prefix:
  • table_name_suffix:
  • pluralize_table_names:
  • default_timezone:
  • record_timestamps:
  • cache_query:
  • max_number_of_listeners:

Example:

var ActiveRecord = require('active_record');
ActiveRecord.configure('primary_key_prefix_type', 'table_name');

or

ActiveRecord.configure({ primary_key_prefix_type: 'table_name', ... });
  • Inflector: @methods: inflections * plural, singular, uncountable Example:
var ActiveSupport = require('active_record').ActiveSupport;
ActiveSupport.Inflector.inflections('pt-BR', function (inflector){
    inflector.plural(/(z|r)$/i, '$1es');
});
module.exports = ActiveSupport;

@alias ActiveRecord.Base

@methods:

  • Base.configure_connection alias of Base.connection.config
  • Base.estabilish_connection alias of Base.connection.connect
  • Base.close_connection alias of Base.connection.disconnect
  • Base.extend
Base.configure_connection('path/to/database.json')
Base.estabilish_connection()
Base.close_connection()
module.exports = User
Base.extend(User, Base)
function User(){
    // ... 
}

@methods: find, first, last, all, exists, where, join, find_by_sql, find_by_id, fields.

@conditions operators: is, is_not, like, not_like, gt, gte, lt, lte, between, exists, not_exists, some, all, in, not_in.

Example:

{
    name_like: 'foo',
    password_is_not: null
    roleId: 1 // If the field is with underscore (role_id), write in camelcase
    createdAt_between: [new Date(), new Date()]
}
User.find(1, function (errorrecord){ ... });
//> SELECT * FROM users WHERE `id` = 1 
 
User.find([1,2,3,4], function (errorrecord){ ... });
//> SELECT * FROM users WHERE `id` IN (1,2,3,4) 
 
User.find({
    select: ["name", "password"],
    conditions: ["name LIKE ?", "%foo%"],
    limit: 1
});
//> SELECT `name`, `password` FROM users WHERE `name` LIKE '%foo%' LIMIT 1 
 
User.find('first');
//> SELECT * FROM users LIMIT 1 ORDER BY `id` ASC 
 
User.find('last', { name_is_not: 'foo' });
//> SELECT * FROM users WHERE `name` IS NOT 'foo' LIMIT 1 ORDER BY `id` DESC 
 
User.find('all', { password: 'bar' });
//> SELECT * FROM users WHERE `password` = 'bar' 
 
User.find('all', { name_like: "%foo%" }, function (errorrecords){
    if (error) throw error;
 
    records.map(function (record){
        return record.to_json();
    })
});
//> SELECT * FROM users WHERE `name` LIKE '%foo%' 

@alias find('first', [conditions], [callback])

User.first({ id_gt: 10 });
//> SELECT * FROM users WHERE `id` > 10 

@alias find('last', [conditions], [callback])

User.last({ name_like: '%foo%' });
//> SELECT * FROM users WHERE `name` LIKE '%foo%'; 

@alias find('all', [conditions], [callback])

User.all(function (errorrecords){ ... });
//> SELECT * FROM users 
User.exists(1);
//> SELECT 1 FROM users WHERE `id` = 1 
 
User.exists({ name: 'foo' });
//> SELECT 1 FROM users WHERE `name` = 'foo' 
User.find({
    include : {
        join: 'phones',
        direction: "LEFT",
        on: "phones.user_id != users.id"
    }
});
//> SELECT * FROM users LEFT JOIN phones ON phones.user_id != users.id 
 
User.find({ include: 'phones' });
//> SELECT * FROM users INNER JOIN phones ON `phones`.`id` = `user`.`id` 
 
User.join('phones');
//> SELECT * FROM users INNER JOIN phones ON `phones`.`user_id` = `user`.`id` 
 
User.join('phones', { name: 'foo' })
//> SELECT * FROM users INNER JOIN phones ON phones.user_id = users.id WHERE `name` = 'foo' 
User.find_by_sql("SELECT DISTINCT(*) FROM users "
                +"INNER JOIN foo ON `foo`.`user_id` = `users`.`id` "
                +"WHERE `users`.`name`LIKE ?", ['%bar%'], function (errorrecords){ ... })
User.find_by_id(1)
//> SELECT * FROM users WHERE `id` = 1 

Create dynamic finders

User.fields('name', 'password', 'created_at', 'updated_at');
 
User.find_by_name('foo');
//> SELECT * FROM users WHERE `name` = 'foo' 
 
User.find_by_created_at(new Date().toString());
//> SELECT * FROM users WHERE created_at = 'Thu Dec 11 2014 22:32:45 GMT-0300 (AMST)' 

@methods: count, average alias avg, minimum alias min, maximum alias max, sum.

User.count('*');
//> SELECT COUNT(*) FROM users 
 
User.count('*', { name_like: '%foo%' }, function (errorresponse){ ... });
//> SELECT COUNT(*) FROM users  WHERE `name` LIKE '%foo%' 

@alias avg

User.average('id');
//> SELECT AVG(id) FROM users 
 
User.avg('id', { name_like: '%foo%' }, function (errorresponse){ ... });
//> SELECT AVG(id) FROM users  WHERE `name` LIKE '%foo%' 

@alias min

User.minimum('id');
//> SELECT MIN(id) FROM users 
 
User.min('id', { name_like: '%foo%' }, function (errorresponse){ ... });
//> SELECT MIN(id) FROM users  WHERE `name` LIKE '%foo%' 

@alias max

User.maximum('id');
//> SELECT MAX(id) FROM users 
 
User.max('id', { name_like: '%foo%' }, function (errorresponse){ ... });
//> SELECT MAX(id) FROM users  WHERE `name` LIKE '%foo%' 
User.sum('id');
//> SELECT SUM(id) FROM users 
 
User.sum('id', { name_like: '%foo%' }, function (errorresponse){ ... });
//> SELECT SUM(id) FROM users  WHERE `name` LIKE '%foo%' 

@methods: create, update, update_all, destroy, destroy_all, delete, delete_all.

User.create({
    name: 'Akrata',
    password: 'akrata',
    password_confirmation: 'akrata'
});
//> INSERT INTO users SET `name` = 'Akrata', `password` = '79a1a1b8ee1b831a27db58089cbf298dc38f3eec', `updated_at` = '2014-12-13 11:07:11', `created_at` = '2014-12-13 11:07:11' 
User.update(1, {
    name: 'Fooo',
    password: '@kr@t@',
    password_confirmation: '@kr@t@'
});
//> UPDATE users SET `name` = 'Fooo', `password` = '0f962118caa0122e7b7c9b1266cecf77918c9f65', `updated_at` = '2014-12-13 11:19:24' WHERE `id` = 1 
User.update_all({ name: 'foo' }, { name: 'bar' });

Find the record before destroy

User.destroy(1);
//> SELECT * FROM users WHERE id = 1 
// if record 
//> DESTROY FROM users WHERE id = 1 

Find all record before destroy

User.destroy_all({ id_gt: 10 });
//> SELECT * FROM users WHERE id > 10 
// if record > 0 
//> DESTROY FROM users WHERE id = @record.id 

Like destroy() method, but don't find.

User.delete(1);
//> DELETE FROM users WHERE id = 1 

Like destroy_all() method, but don't find.

User.delete_all({ id_gt: 10 });
//> DESTROY FROM users WHERE id > 10 

@methods: before_create, before_update, before_destroy, before_find.

@methods: initialize, set, get, to_object, to_json, keys, values, attributes, is_valid, changed, toString, save, update_attributes, destroy, errors: { add, remove, clear, set, get, any, size, full_messages }.

Initialize instance variables

var user = new User();
user.set('name', 'Foo'); // return ERROR 
// initialize variables 
user.initialize();
user.set('name', 'Foo');
var user = new User();
user.initialize();
user.set('name', 'Foo');
user.get('name'); // return 'Foo' 
console.log(user.name);
 
user.set('password', 'bar');
user.get('password'); // return 'bar' 
 
//** DON'T USE **// 
user.name = 'Foo';

@methods: validates, validates_with, validate_presence_of, validate_uniqueness_of, validate_numericality_of, validate_length_of, validate_format_of, validate_exclusion_of, validate_inclusion_of, validate_confirmation_of, has_secure_password: { authenticate }

function User(attr){
    this.initiliaze(attr);
 
    this.validates('name', {
        presence: true
    })
 
    this.validate_length_of('name', { minimum: 5 })
}

@methods: before_create, after_create ,before_update, after_update, before_destroy, after_destroy, before_find, after_find.

There are two way to configure the callback. Config in class Example:

/* Before update */
User.before_create(function (record){
    if (record.get('name') == 'root'){
        record.errors.add('name', 'Is reserved.');
    }
})
 
/* After create */
User.after_create(function (record){
    console.log('User #'+ record.get('name') +'created with success.');
})
function User (attr){
    this.initialize(attr);
 
    this.before_create(checkName);
 
    function checkName (){
        if (this.name == 'root') this.errors.add('name', 'Is reserved.');
    }
}

GPLv3