Skip to content
sergeych edited this page Aug 25, 2012 · 4 revisions

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.

Creating and updating

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

Loading model instances

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.

Advanced topics

Table name

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'

Connection

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 )

Transactions

See transactions, tables.

Clone this wiki locally