Express Sequelize Heroku Postgres Configuration Success

You are in flow developing on your local database and you decide to upload everything to heroku and share it with the world.

How do you configure your production database?

It’s easier than you think. Let’s assume you have already set up your site.

If you used the sequelize init command, you will have a file db/models/index.js that looks like this

Usually, your sequelize database will initialize with the usual database, username password, etc but in the special case that your config has use_env_variable, sequelize will recognize that an environment variable (usually representing a URI) can be used in place of the usual credentials.

What is your env/config variable?

Find your heroku config variables in the heroku website or by running $ heroku config. Note, config and env variables are used to reference the same settings here.

When you create a database on your heroku account, it will default a new configuration setting called “DATABASE_URL”

You can access this with process.env.DATABASE_URL in any of your node.js code (on production). Your local machine will have different environment variables set.

Step 1: Set use_env_variable

But set it to what? Set it what heroku designates as your database url, DATABASE_URL!

Thats it!

You may need to migrate your database if you aren’t using sync

Step 2: Migrate your database

Simply run the migrate command in the heroku environment with heroku run. This avoids any configuration errors of running from your local environment

$ heroku run ./node_modules/.bin/sequelize db:migrate --debug

Final config

Step 3: Check your database

Run the heroku psql command and run the “list tables” command.

$ heroku psql

$<app_name>::DATABASE=> \dt

Possible Errors

Error: no pg_hba.conf entry for host…, SSL OFF

Add the ssl setting into dialectOptions of your config.json

Error: The server does not support SSL connections

This may be an outdated error. But previously, users who tried to migrate on their local computer would run into this error.

$ NODE_ENV=production DATABASEURL=$(heroku config:get DATABASE_URL) ./node_modules/.bin/sequelize db:migrate

This will not work correctly unless you set up your local computer to support ssl in the migration. You could get a certificate and configure your sequelize config to use that BUT theres an easier way.

ERROR: SequelizeConnectionRefusedError: connect ECONNREFUSED 127.0.0.1:5432

It’s quite possible you forgot to push your code to heroku. Make sure you git push heroku master!!!

Node Sequelize Postgres Tutorial

Why use Sequelize?

Sometimes you want your team to use an ORM. Often you need to run migrations. Sequelize provides ORM features and a much needed migrations library that allows us to create producible and version controlled database schemas.

Setup your project

Step 1: Create an npm project in your desired directory

$ npm init

Step 2: Install the packages

$ npm install --save sequelize sequelize-cli pg pg-hstore

Step 3: Create a new database

You need to have postgres installed on your machine for this. If you do not have postgres you can use brew to install it: $ brew install postgres

Now create a new database called here called “user-demo-db”

$ createdb user-demo-db

Step 4: Initialize your sequelize directories

$ node_modules/.bin/sequelize init

Now what? Using Sequelize

You have two options to create database tables: We can either create our database tables with the psql shell using raw queries or we can use sequelize to manage our database.

When to use “sync” and when to use “migrations”

Using sequelize, there are two options for creating tables: 1. Using sync or 2. Using migrations.

In most tutorials you will see code using sync() or even sync({force: true}). This is completely fine in a test database since this option will completely overwrite your database based on your model files. Note: this means you can destroy data with this option.

Why use migrations?

With migrations, we are incrementally changing the database tables and will retain a record of all these changes in our “migration” files. This record is a valuable record of our changes and will allow us to avoid destroying our data.

Step 5 : Create your first model by generating your first migration files

Here we are creating a new model by generating both the initial model file AND the migration file for a sample model User with some attributes firstName;lastName;email

* Note: we are using the singular “User” and not the plural “Users”. This will be an ORM convention that you will need to get used to.

$ node_modules/.bin/sequelize model:generate --name User --attributes firstName:string,lastName:string,email:string

Look inside your new model file: 

It should export a new “model” using sequelize.define("User", ...) with the attributes that you specified in the command line arguments.

* Note that the default id field is INTEGER and not something cool like UUID, its your code now, you can change this.

Look inside your new migration file:

It should use the  queryInterface function  createTable('User', ...) with attributes that you specified in the command line arguments plus three fields that sequelize will add to every table id, createdAt and updatedAt

* One thing that is key to note is that by default you table name is pluralized

Step 6: Run the migration

Before you run this migration, you may change the migration/model file to edit your attributes.

$ node_modules/.bin/sequelize db:migrate

Sequelize will create a SequelizeMeta table in your database to keep track of which migrations have been run. That also means you can create many other models before running this command and it will run all not-yet-run migrations

Check your migration

After you run your migration you can check your table status with psql shell or pgadmin

$ psql user-demo-db

psql> \d "Users" <- note the “s”; note the double quotes 

Get used to this pattern, you will use this a lot.

(Optional) Create an instance of your model – User

Note that we use the singular User instead of the Users from the actual table

node> var models = require('./db/models')

node> models.create.User({

  firstName: "John", lastName: "Doe", email: "jd@gmail.com"})

Step 7: How to create a 1:Many (1:M) relationship

Lets create a model called Task that can only have one User. 1(User):Many(Tasks).

Create your migration files and migrate your database to add the new table

$ node_modules/.bin/sequelize model:generate --name task --attributes body:string,done:boolean

$ node_modules/.bin/sequelize db:migrate

Now we will need to associate the Task to the User in some way.

According to the docs we need to run Task.belongsTo(User)

However if we add this to the db/models/Task.js file in the associate function, our file now fails to load correctly when accessing db/models within the node shell. We can open up our node shell and do this manually.

node> const models = require('./db/models')

node> models.Task.belongsTo(models.User)

What happened?

BelongsTo associations are associations where the foreign key for the one-to-one relation exists on the source model.

– docs

We ran the code <source>.belongsTo(<target>) with having the appropriate “foreign key” on our source model (Our Task model is missing the column UserId). Instead of undoing our migration, this is a perfect time to learn how to do a database migration.

Step 8: Fix our 1:M relationship

This time we only need the migration file, and not the model generated file.

$ node_modules/.bin/sequelize migration:generate --name add_userid_to_task

Adding a foreign key field to a model – Task

We want to create a new column UserId on our Task model/table that represents a foreign key relationship. The docs explain that all we need is a references key with the correct values

Your migration file will look something like this: code

return queryInterface.addColumn(
  SOURCE_TABLE_NAME,  // "Tasks"
  TARGET_FIELD_NAME, // "UserId"
  {
    type: Sequelize.INTEGER,
    reference: {
      model: TARGET_TABLE_NAME, // "Users"
      key: "id"
    }
    onDelete: 'cascade
  }
)

Important Notes:

  • we have to match the type of the target field (“integer” in our case above, “UUID” if you wanted to create an advanced User model)
  • Your source “table” name is likely the plural version of your “model” name. You can get the model name with node> require('../models')[model_name].getTableName()
  • Your target field name should be “title-case” based on sequelize convention, so if you’re targeting id on User, your target field name is UserId

Step 9: Remember to migrate your database!

$ node_modules/.bin/sequelize db:migrate

 

More: 

Code: Sample

Docs: Sequelize Docs

Blog Post: How to configure sequelize with heroku

Blog Post: How to define Sequelize associations using migrations

How does sequelize pluralize?

If you use .sync with sequlize and have a model name like User, your database ends up with a table called Users. More clearly, when you use the sequelize-cli model generator the generated file will show this pluralized table. Here is the code: (link)

What is Utils

* Note Sequelize has a directory called Utils AND a file at lib/utils.js.

What’s in lib/util.js?

 

We find the function! This is how sequelize defines utils.pluralize link

Util.pluralize IS inflection.pluralize

This is how its tested 

What is inflection?

Inflection is a port of Ruby on Rails Active Support Inflection classes into JavaScript built by DreamersLab in Taipei. (link)

So how does sequelize/inflection pluralize?

Inflection seems to have rules based on:

Eventually, inflection takes these rules, uses RegExp and applies them to your string. Theres a bunch of rules and at the end theres this

The common rule that is the exhausted else or case default rule that targets the end of the string with $. No rules for that singular term? Add an s

Postgres timestamp with timezone – “timestamptz”

Postgres can store your “timestamp with timezone” or “timestamp without timezone”.
If you don’t specify either, it will default to “timestamp without timezone”

Which one should you use? TLDR: “timestamps with time zones”

Whats the problem living life without timezones?

Say you have two users in two different timezones – one in California and one in France. Imagine you may need to know which one acted “first”, maybe in an auction or draft scenario where the whoever acts first wins.

Without specifying timezone, your database will save the plain timestamp of each user, say “midnight” and “midnight”. How will you know which one acted first?

You could save the original timezone from the user and perform the necessary algebra when needed.

Solution – Use “timestamp with time zone” otherwise known as “timestamptz” 

For timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system’s TimeZone parameter, and is converted to UTC using the offset for the timezone zone.

Postgres docs

This bears repeating: 

“For timestamp with time zone, the internally stored value is always in UTC.”

A proper name for this might be timestamp saved as UTC by default. By saving everything in the “same” timezone, we know the absolute time of the timestamps.

This brings up the main UX concern: What do users see?

Your users want to read data from the database using their preferred timezone.

(If they added a blog post at 3:00pm PST, they want to see the timestamp as 3:00pm not 6:00PM EST )

Dates are saved as UTC so you will eventually need to convert the time

Converting on the server:

Best practice is to save the users’ preferred timezone as a name (e.g. America/Los_Angeles). This way your query or ORM can convert the date according to user preference.

Remember, timezones offsets are affected by political actions. A timezones actual hour offset can change depending on whether the timezone recognizes daylight savings time (Phoenix does not) or just simply when the political “owners” of the timezone decide to CHANGE the offset. Read The Long, Painful History of Time for more info.

Converting on the browser:

Many browsers have default timezones that can be used by passing in your date to new Date. You can also, simply use moment.js to parse the dates on the client to show the correctly formatted date string for your purpose.

Do not convert at all! Use “Time from now”:

Ever notice how websites have time indicators like “just now”, “30 minutes ago” and “22 hours ago”? These avoid dealing with timezones altogether. Way easier! moment.js has this API that will simply accept your date and convert it to time from now style.

moment([2007, 0, 29]).fromNow(); // 4 years ago

What about user input?

User input should always be converted to UTC (with timestampz this will be handled and stored in UTC by default). Many functions already return UTC by default such as  new Date() in Browser JavaScript and node.

Resources:

PostgreSQL Data Types: Date, Timestamp, and Time Zones

Detecting the time zone from the browser: 

Using CAShapeLayer to draw a circle

UIViews are like Ogres, which are like onions – they have layers.

Source: Documentation

More accurately, UIView has a single layer property that can have infinite sublayers.

UIView’s have layers

Lets draw a circle.

First create a UIView and a CAShapeLayer:

let myView = UIView()

let myLayer = CAShapeLayer()

Layers have a path

UIBezierPath makes drawing shapes extremely smooth, lets say in the shape of a circle:

let circlePath = UIBezierPath(
  arcCenter: CGPoint(x: 100.0, y: 100.0),
  radius: 100,
  startAngle: 0 * CGFloat.pi / 180,
  endAngle: 360 * CGFloat.pi / 180,
  clockwise: true)

Great! Now we can add CAShapeLayer as a CGPath and spruce up our fill and stroke colors

myLayer.path = circlePath.cgPath
myLayer.strokeColor = UIColor.blue.cgColor
myLayer.fillColor = UIColor.yellow.cgColor

Last step! Add this layer to your UIView

myView.layer.addSublayer(myLayer)

Layers have attributes

strokeColor,fillColor, opacity, lineWidth and more!

Bonus: Layers can animate attributes

// create the animation
let opacityAnimation = CABasicAnimation(
  keyPath: #keyPath(CALayer.opacity))
opacityAnimation.fromValue = 0
opacityAnimation.toValue = 1
opacityAnimation.duration = 5.0

// set the final value; add the animation
myLayer.opacity = 1
myLayer.add(opacityAnimation, forKey: #keyPath(CALayer.opacity))

iOS Application Lifecycle – UIKit basics

iOS applications are all about cycles

This is because the iOS applications are richly interactive when it comes to user input and much of your programming with UIKit will be delegate oriented. Knowing the many different “cycles” of the device and application will be illuminating for your development.

States of the UIKit App Cycle

* These are the execution states of a UIKit app from the Apple docs. But why so many arrows? Below is the simplified flow charts

User Action: Your app has not been launched

Your application starts off Current State: Not Running

User Action: Your app is launched

Delegate method called: application(_:didFinishLaunchingWithOptions:)

New state: Inactive – your application is briefly here as it prepares a successful launch

New state: Active – your application is now the “foreground app”.

Many apps will place a majority of the app setup logic in this function including setting up a programmatic view controller setup (bypassing the default storyboard)

Delegate method called: applicationDidBecomeActive

User Action: User goes to home screen or opens another app

 

Current state: Active

Delegate method called: applicationWillResignActive

New state: Inactive – your application is briefly here

New state: Background – your app is available in the app picker screen on home button double tap

Delegate method called: applicationDidEnterBackground*

* If your app does not support background execution “applicationWillTerminate” is called

** If your iOS device is low on memory, it may suspend and even terminate your app back to the state “Not Running”

User Action: User reopens a background app

Current state: Background

Delegate method called: applicationWillEnterForeground

New state: Active

Delegate method called: applicationDidBecomeActive

 

TLDR: Your basic UIKit flow moves from Active <-> Background

These are only the basic lifecycle events for your UIKit app, there are MANY different scenarios that can change the state of your app – the device can span a low battery warning and show the power saving alert, a phone call may occur, users can click and hold notifications, the device can run out of batteries.

iOS without storyboard

Why?

Programmatically/Code or NIB based layouts are a much better fit for projects that use version control (see merge conflicts) and make it much easier to reuse views. If you are deciding not to use storyboards, you will need to manually set your application window to your desired UIWindow

Prerequisites:

– Delete Main Interface from Deployment Info Settings

– Delete the Main.storyboard file

How to: set up a iOS project without storyboard

Step 1: Create a UIWindow with the frame using the bounds of the UIScreen

UIWindow(frame: UIScreen.main.bounds)

Step 2: Assign this to the AppDelegate window property

window = ...

Step 3: Make the window “key” and “visible” 

window?.makeKeyAndVisible

Step 4: Set the window `rootViewController` to the VC of your choice

window?.rootViewController = ...

Code: link

Forgetting to set translatesAutoresizingMaskIntoConstraints to false

UIKit on iOS is great! There are tons of tools and often this can supercharge your productivity for getting a prototype out into the world.

Additionally, working with AutoLayout programmatically can be great if you avoid these rookie mistakes.

Rookie Mistake 1:

It hurts when you spend hours dealing with the rookie mistake of forgetting to set translatesAutoresizingMaskIntoConstraints to false on the view when setting constraints.

view.translatesAutoresizingMaskIntoConstraints = false

Rookie Mistake 2: 

Remember that you also have to also set your NSLayoutConstraint to true

Example:

yourView.centerXAnchor.constraint(equalTo:
  view.centerXAnchor).isActive = true

Solution:

This function allows you to program with wild abandon! If you use this function to set your constraints you never need to remember those pesky settings.

func setLayoutConstraints(
    view: UIView,
    constraints: [NSLayoutConstraint]) {
        view.translatesAutoresizingMaskIntoConstraints = false
        constraints.forEach({constraint in
            constraint.isActive = true
        })
}

Code found here, and more

*Update: Apple created a convenience method on NSLayoutConstraint called .activate that will set the isActive property to true. The new code would look like this:

func setLayoutConstraints(
    view: UIView,
    constraints: [NSLayoutConstraint]) {
        view.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate(constraints)
}

Delete files by filename with “find”

When you upload photos multiple times, the computer can start numbering the photos. IMG_A becomes IMG_A 1 and IMG_A 2 and IMG_A 3.

Using a wildcard * and specifying the ending space and number will help you select the files. For example:

Find all the files that end in "space"1.JPG

find -name '* 1.JPG'

* Have a look at the returned files to make sure you want to delete these

Find AND DELETE all the files that end in "space"1.JPG

find -name '* 1.JPG' -delete

gist

Setting environment variables

How to see and set your environment variables

Print all your current environment variables with 

$ printenv

See a the value for a specific variable with echo

$ printenv <YOUR_VARIABLE> or $ echo $<YOUR_VARIABLE>

For example:

$ printenv MY_API_KEY or $ echo $MY_API_KEY

How do I set the variable temporarily?

This will set your variable for ONLY your current shell session

$ export <YOUR_VARIABLE>=some-secret-pattern

You can also prepend values to a currently set variable

$ export <YOUR_VARIABLE>=some-secret-pattern:$<YOUR_VARIABLE>

This is why you see export PATH statements like this

export PATH=/usr/local/mysql/bin:$PATH

This is actually prepending /usr/local/mysql/bin to the existing PATH

How do I set the variable permanently?

You can run the same start up export command with every shell session if you put this in your .bash_profile

export <YOUR_VARIABLE>=some-secret-pattern

* Make sure you source your bash_profile to see the changes

$ source ~/.bash_profile

How do I see it in my code?

Using your node shell:

node> console.log(process.env)

Using your python shell

python> import os; print os.environ