Rails 4.1: deploying to Heroku

download the toolbelt kit:

$ wget -O- https://toolbelt.heroku.com/install-ubuntu.sh | sh

login:

$ heroku login

create your app:

$ heroku apps:create [your app name]

or, if you already have an app in Heroku:

heroku git:remote -a ticketee-demo

Add the rails_12factor gem, to take care of the standard points a web app should cover. In your gemfile:

gem “rails_12factor”, group: :production

Also, in the same gemfile, to make sure you are using the same Ruby version as in development, add the following line (right under the “source” first line):

source 'https://rubygems.org'
ruby "2.2.1"

Also, to specify a better production server (than the redbrick default), add the following line at the bottom of your gemfile:

gem "puma", group: :production

If you are going to use the Puma server in production, in Heroku, you will also need to add a Procfile in your root folder, with the following content:

web: bundle exec puma -t 5:5 -p ${PORT:-3000}
  -e ${RACK_ENV:-development}

Then, just rebuild your gemfile.lock by running:

bundle install --without=production

And finally, to push to Heroku, checking your code, and push it:

$ git add .
$ git commit -am "setup heroku ruby version and server"
$ git push heroku master

Your code is now there, but you will also need to get the database ready and run all the needed migrations:

heroku run rake db:migrate

If you have any seed files for your db, this is also a good time to run it:

heroku run rake db:seed

If anything goes wrong, you can always see what is happening in the logs:

heroku logs

boostrapping a MEAN app (angular.js, express, node.js, mongodb)

Complete code example here

– in the folder you are creating your app, place a manifest file called package.json, example:

{
“name”: “yourappnamehere”
}

– install express and other dependencies:

$ sudo apt-get update

$ sudo apt-get install npm

sudo apt-get install nodejs

Note: copying and pasting these commands sometimes will give you the following error message:

TypeError: Cannot read property ‘latest’ of undefined

make sure to retype the “–” part manually, and you’ll be all right

$ sudo npm install –save express

$ sudo npm install –save body-parser

– if you want node to automatically restart when there are changes in the files, you can also install the following package:

$ npm install –global nodemon

– and then, when you start your server, you need to start it as:

$ npm install –global nodemon

– install mongodb, create the following file on your home directory: mongo_install.bash, with the following content:

apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
echo "deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen" | tee -a /etc/apt/sources.list.d/10gen.list
apt-get -y update
apt-get -y install mongodb-10gen

– run sudo bash ./mongo_install.bash

– the installation starts mongod by default, but that is the daemon you need to start if you don’t see it running

– install mongoose:

$ npm install –save mongoose

– to enter the console mode (and verify the installation), type mongo, if you want to connect to an specific db, you do:

mongo nameofyourdbhere

> db.posts.find()

that will give you all the records saved under the Post model

– create a server.js file, that will host your app (see code in heroku instance for content details)

– run your server:

nodejs server.js

(config.vm.network :forwarded_port, guest: 3000, host: 3000 on Vagrantfile if you are running inside vagrant)

– server.js is kind of your single point of entry for your app. It is always a good idea to keep it lean, and move as much code as possible away from it into other files. Some things that are worth having at this file are:

— the server listening loop

— global configuration and other middleware packages

— logging and error handling

— controllers spawning and mounting

– on static files: it is a good idea not to serve them via nodejs. Try to keep your node instance as an API, and let apache and other cache services to do the static servers job. But if you must, it is always a good idea to spin them into:

/controllers/static.js

and inside that file:

var express = require(‘express’)
var router = express.Router()

router.use(express.static(__dirname + ‘/../assets’))

– so now any file you put on your /assets folder will be served by node

– on services: things like $http are better constructed via a service, and then injected to wherever they are needed. Below is an example of doing just that:

app.service(‘PostsSvc’, function ($http) {

  this.fetch = function () {

    return $http.get(‘/api/posts’)

  }

  this.create = function (post) {

    return $http.post(‘/api/posts’, post)

  }

});

– and then, the controllers that consume it would looks something like this:

    // create the PostsCtrl module

    // dependency inject $scope

    app.controller(‘PostsCtrl’, function ($scope, PostsSvc) {

      // the function runs when the “Add Post” button is clicked

$scope.addPost = function () {

    if ($scope.postBody) {

      PostsSvc.create({

        username: ‘ramiro’,

        body: $scope.postBody

      }).success(function (post) {

        $scope.posts.unshift(post)

        $scope.postBody = null

      })

    }

  };

 Deploying to Heroku

– create a .gitignore file with the following lines:

node_modules
assets

– if you are in a new vagrant instance, install heroku tools first:

$ wget -qO- https://toolbelt.heroku.com/install-ubuntu.sh | sh

$ heroku login

heroku create your-app-name-here

heroku addons:create mongolab

– check what is the address of your mongolabs instance:

$ heroku config

– modify your db.js file according to what you see printed by that command, it would look something like this:

var mongoose = require(‘mongoose’);

var url = process.env.MONGOLAB_URI || ‘mongodb://localhost/social’;

mongoose.connect(url);

module.exports = mongoose;

– you also need to do a similar move for the listen command in the server.js file:

// process.env.PORT for the benefit of Heroku

app.listen(process.env.PORT || 3000, function () {

  console.log(‘Server listening on’, 3000)

});

Heroku: sending mail

It is so easy now that mandrill by MailChimp is part of the deal.

1) Add the Mandrill Add On to your site.

2) Include the ‘mail’ gem in your gemset.

3) Example of how to send stuff:

 

require ‘mail’

Mail.defaults do
delivery_method :smtp, {
:port => 587,
:address => “smtp.mandrillapp.com”,
:user_name => “your mandrill username here”,
:password => “your mandrill API key”
}
end

mail = Mail.deliver do
to ‘somebody@gmail.com’
from ‘JohnYo DoeMero <johnmero@somewhere.com>’
subject ‘Test email via Mandrill!’

text_part do
body ‘This is the email body message’
end

html_part do
content_type ‘text/html; charset=UTF-8’
body ‘<em>And, the HTML counterpart <strong>is working!</strong></em>’
end
end

Ruby On Rails: barebones site template from the ground up.

We are talking about quick demos, site bootstraping kind of deal here. So don’t expect robust, detailed explanations.

Also, assuming you have Ruby / Rails / Git / postgresql / RVM (optional) installed. Barebones, cutting through most of the commands explanations. Aim to push site and ideas fast out there.

$rails new first_app -d postgresql

-d postgresql to create this with postgres

NOTE: postgresql (and role creation) have some issues. It is not a straight process, you can always default to the mysql default in your local server, and harden it on production (if saving time in a demo is an issue).

To secure your app, create a role for the postgres database specific to your app.

In your postgres admin, click on the Login Roles, add Login Role. Make sure the new role can create database objects. Make sure you set a password for it as well.

Then, in config/database.yml you need to plugin the username / password you just created  ( in all the diff databases: development, test and production)

Modify your gem file as follows

$bundle install –without production –binstubs

binstubs makes it easier to run tests later (the command is shorter). It stores binaries so they don’t have to be pre-compiled everytime you run tests.

Speaking of tests, at this point you can generate the skeleton to run tests:

$rails generate cucumber:install
$rails generate rspec:install

$rake db:create

$rails server // just to make sure you have a local server setup

$git init

$git add .

$git commit -m “Initial commit”

[optional] Create a bitbucket (or github) repo:

git remote add origin https://usernamehere@bitbucket.org/usernamehere/projectnamehere
git push -u origin --all # to push up the repo for the first time

Download and install heroku toolbelt (if not there yet)

https://toolbelt.heroku.com/

$heroku login

$heroku create [name of your app here]// inside your app’s directory

// Create the basic model for your users:

$rails generate scaffold User first_name:string last_name:string

// By convention, rails likes models to be singular, and camel cased (starts with a capital letter). As in “User”

// At this point, you should have the basic CRUD operations for users at:

localhost:3000/users

// To create the user’s authentication stuff:

$ rails generate devise:install

// And follow the instructions printed afterwards (no need to replicate them here)

$ rails generate devise User

$ rails generate devise Admin

// Important! protect your user’s section by adding the following to app/controllers/users_controller.rb:

before_filter :authenticate_admin!

// And also, make sure users can’t register as admins (inside the admin’s model, app/models/admin.rb)

devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable

// Notice that :registerable has been removed. If you need to create admins, you will have to do it via direct db access, or by using the console and bypassing momentarily that restriction, or, you can bring it back and ask for an extra token at admin registration time, but then you will have to manage / distribute those tokens

$bundle exec rake db:migrate // Update the DB with it

$ rails generate controller StaticPages home help about contact_us–no-test-framework // Create home and help pages, which can contain dynamic variables. It generates all your views and controllers

– Modify your public/index.html with something other than the default Rails page (or remove it if you are sending users to another page via the router)

root to: ‘static_pages#home’ // redirects “/” to static pages controller, home method

match ‘/help’, to: ‘static_pages#help’ // redirects to help page

– Put any other pure static pages in this directory as well (public/hello.html, etc)

Example of how to integrate the login and signup links in a view after devise is in place:

<% unless admin_signed_in? -%>
  <p><%= link_to ‘Sign up as Admin’, new_admin_registration_path %></p>
  <p><%= link_to ‘Sign in as Admin’, new_admin_session_path %></p>
<% end -%>
<% unless user_signed_in? -%>
  <p><%= link_to ‘Sign up as User’, new_user_registration_path %></p>
  <p><%= link_to ‘Sign in as User’, new_user_session_path %></p>
<% end -%>
<% if user_signed_in? -%>
  <p><%= link_to ‘Token Authentication Example’, token_path(:auth_token => current_user.authentication_token) %></p>
<% end -%>

Example of how to protect your pages from access (via the controller):

before_filter :authenticate_user!

or

before_filter :authenticate_admin!

$rails generate scaffold Micropost content:string user_id:integer // Create an object that will be associated with a user

// Setup your basic models associations at this point:

class User < ActiveRecord::Base // Inside apps/model/user.rb
attr_accessible :email, :name
has_many :microposts
end

class Micropost < ActiveRecord::Base // Inside apps/model/micropost.rb
attr_accessible :content, :user_id

belongs_to :user

validates :content, :length => { :maximum => 140 }
end

// Next, save the changes, and push them locally and in Heroku:

$ git add .

$ git commit -m “Add models”

$ git push heroku master

$ heroku run rake db:migrate

$ heroku open // Make sure things are handy dandy

//  A bit of automatic styling

app/assets/stylesheets/custom.css.scss // Add this file, with the following line:

@import “bootstrap”; // Now you can use twitter’s bootstrap to style your app!