-
Notifications
You must be signed in to change notification settings - Fork 1
Models
The prego.Table
class is most useful as a base class for your models. It provides basic functionality to access and modify tables, callback style. Suppose, you have a persons
table, created somewhat like:
create table persons(
id serial primary key,
created_at timestamp default now(),
first_name varchar,
last_name varchar
);
Then you can easly create a model for it by declaring:
class Person extends prego.Table
This is enough, but often you add some budiness-model methods to it, for example:
class Person extends prego.Table
fullName: ->
"#{@firstName || ''} #{@lastName || ''}"
Take notice that snake_cased table column names are converted to the camelCase attribute names automatically.
Now you can do basic operations with your model:
user = new Person( { firstName: 'John', lastName: 'Doe' } )
user.save (err) ->
return err if err
console.log "User #{user.fullName()} is saved, its id is now #{user.id}"
user.firtsName = "Jane"
user.save (err) ->
# prego will issue prepared 'UPDATE persons SET last_name = 'Jane'' to save changes
Easies way is to get by id
Person.findById 1, (err, u) ->
# u is a Person instance or null:
console.log 'Found', u?.fullName()
OR using arbitrary SQL query:
Person.findBySql "SELECT * FROM persons WHERE first_name == 'Jane'", (err, u) ->
console.log 'First Jane in our persons table:', jane?.fullName()
Person.allFromSql "SELECT * FROM persons WHERE first_name == $1", ['John'], (err, all) ->
console.log 'All Johns we know:', (x.fullName() for x in all).joins(', ')
OR, the serquental access, just like 'prego.executeEach', but with model instance:
Person.eachFromSql "SELECT * FROM persons WHERE first_name == $1", ['John'], (err, person) ->
return err if err
console.log 'Found a person:', x.fullName() if person
console.log 'No more persons' unless person
Please node that you can select only few attributes from the table, say 'SELECT first_name FROM persons...', and in this case only these columns will be loaded into instance attributes.
The same way, you can select more attributes, say, aggreagetes, counts, joined table columns and so on. All these attributes will be available in the result model instance, but if you'll change something, on model.save
only the model's table attributes will be updated. Prego keeps track of table metadata and restricts load/save operations to the table columns only.
By default, prego uses model name, converting it to plural and to snake_case. For example, model class BadBoy
would expect table bad_boys
, BigBoss
- big_bosses
, OrdersMatrix
- orders_matrices
, SalesData
- sales_data
, and so on. Of course pluralization routine can sometimes mistakes plurals for English words, but it tries hard.
Sometimes though you might want to specify table name exactly:
class UsefulIndex extends prego.Table
# by default prego would expect useful_indices, but you might want:
@tableName = 'useful_indexes'
Prego uses default connection for table routines, but you can provide a connection object for a table instead, that is quite useful if you, say, want to use models from different databases, what is a very good practice, day, to exchange data between services and so on:
class ExternalTasks extends prego.Table
@connection = new prego.Connection( externalDbConnectionString )
See transactions, tables.