Heroku Deploy Procedure

Just keep record of the procedure to deploy heroku install heroku heroku gem(deprecated) or toolbelt

1
2
3
sudo aptitude install heroku-toolbelt
#or for ubuntu
wget -qO- https://toolbelt.heroku.com/install-ubuntu.sh | sh

login with credentials

1
2
3
4
5
6
7
8
heroku login
#Enter your Heroku credentials.
#Email: adam@example.com
#Password:
#Could not find an existing public key.
#Would you like to generate one? [Yn]
#Generating new SSH public key.
#Uploading ssh public key /Users/adam/.ssh/id_rsa.pub

create app

1
2
3
heroku create
heroku rename
heroku help

add to git and make a commit

push and deploy

1
2
3
4
#change Gemfile put sqlite3 to development 
#add pg to production
#if you change Gemfile you need to git commit again otherwise heroku will not know
git push heroku master

if you got error

Permission denied (publickey). fatal: The remote end hung up unexpectedly

try and reference add keys to heroku

1
2
3
4
5
heroku keys:add ~/.ssh/id_rsa.pub
ssh-keygen -t rsa -f id_rsa
git clone git@heroku.com:stark-dawn-1234.git -o heroku
heroku keys:clear
heroku keys:add

migration and open

1
2
3
4
heroku run rake db:migrate
heroku run console
heroku logs
heroku open
Comments

Sudo vs RVMSudo

RVM is a great command-line tool which allows you to easily install, manage, and work with multiple ruby environments from interpreters to sets of gems. This is exactly what makes it special, its easy to install RVM with just a few commands..

Installing RVM:

1
2
curl -L https://get.rvm.io | bash -s stable
source ~/.bashrc

Source is to load bashrc in the same window. Now just use

1
2
rvm install 1.9.3
rvm use 1.9.3

and it now you can start using ruby version 1.9.3 and switch or add more versions and install gems in its own version.

In spite of having such features to help the user, everything from there runs only for the logged in user, there may be times where you must run Ruby scripts with RVM as root (or another user) via sudo.

But if you do this after installing rvm:

1
sudo ruby script.rb

It would problably not work at all or would be using the system installed version of ruby(which might be old). Do not forget to check the version of the ruby when you do a sudo, if it runs!

1
sudo ruby -v

sudo always starts a new subshell and runs as root from the current user. That new subshell’s environment will be completely different, and which means that it does not contain RVM or the other paths. There is a workaround, where you can manually add the path by finding them. Not a great idea, but works.

RVM has a solution for running sudo with the environments, the ‘rvmsudo’ command. It will pass on any environment variables that RVM set up to get you to the correct Ruby. This includes the following variables

  • $PATH
  • $GEM_HOME
  • $GEM_PATH
  • $BUNDLE_PATH

So to run the same ruby script script.rb, simply use the Ruby you want and run it with rvmsudo.

1
2
rvm use 1.9.3
rvmsudo ruby script.rb

As always, running commands as the root user with elevated privileges, needs to be carefully done since they can alter settings and install unwanted features to all users of the system. [Follow our friendly trusted neighborhood spidey.. With Great power comes Great Responsibility]

Comments

Generate Random String in Ruby

Sometimes we need to generate a ‘n’ character random string.

Here are a few:

  • Only upper case alphabets [A-Z]
1
2
3
4
5
value = "";
8.times{value  << (65 + rand(25)).chr} >>}
#or
(0...8).map{65.+(rand(26)).chr}.join
(0...8).map{ ('A'..'Z').to_a[rand(26)]  }.join
  • Lower case and upper case [a-zA-Z]
1
2
3
4
5
value = "";
8.times{value << ((rand(2)==1?65:97) + rand(25)).chr} >>}
#or
o =  [('a'..'z'),('A'..'Z')].map{|i| i.to_a}.flatten
string  =  (0...50).map{ o[rand(o.length)]  }.join
  • Using SecureRandom provided by ActiveSupport
1
2
3
4
require 'active_support/secure_random'
random_string = ActiveSupport::SecureRandom.hex(16)

# outputs: 5b5cd0da3121fc53b4bc84d0c8af2e81
  • SecureRandom also has methods for:

base64

  1. hex
  2. random_bytes
  3. random_number

see:

  • It is also important to avoid Ambiguity
1
2
3
4
5
# Generates a random string from a set of easily readable characters
def generate_activation_code(size = 6)
  charset = %w{ 2 3 4 6 7 9 A C D E F G H J K M N P Q R T V W X Y Z}
  (0...size).map{ charset.to_a[rand(charset.size)] }.join
end
  • Random URL Friendly Strings
1
rand(36**length).to_s(36)
  • One more example with SecureRandom
1
2
require 'securerandom'
s = SecureRandom.urlsafe_base64(20)
  • Creating a Random string with arguments
1
2
3
4
5
6
def random_string(length=10)
  chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'
  password = ''
  length.times { password << chars[rand(chars.size)] }
  password
end
  • This example works Only in ruby 1.9
1
2
3
4
5
6
7
8
[*('A'..'Z')].sample(8).join
#Generate a random 8 letter string (e.g. NVAYXHGR)

([*('A'..'Z'),*('0'..'9')]-%w(0 1 I O)).sample(8).join
#Generate a random 8 character string (e.g. 3PH4SWF2), excludes 0/1/I/O. Ruby 1.9
ALPHABET = ('a'..'z').to_a
10.times.map{ ALPHABET.sample }.join
10.times.inject(''){|s| s << ALPHABET.sample }
  • Here’s one using digest sha1
1
2
3
4
require 'sha1'
srand
seed = "--#{rand(10000)}--#{Time.now}--"
Digest::SHA1.hexdigest(seed)[0,8]
  • Here are more examples to help

  • Example 1

1
2
3
4
5
6
7
rand(2**256).to_s(36)[0..7]
#Add ljust if you are really paranoid about the correct string length:
rand(2**256).to_s(36).ljust(8,'a')[0..7]
characters = ('a'..'z').to_a + ('A'..'Z').to_a
# Prior to 1.9, use .choice, not .sample
(0..8).map{characters.sample}.join
(0...8).collect { |n| value  << (65 + rand(25)).chr }.join()
  • Example 2
1
2
3
4
5
6
7
8
def generate_random_string(length=6)
  string = ""
  chars = ("A".."Z").to_a
  length.times do
    string << chars[rand(chars.length-1)]
  end
  string
end
  • Example 3
1
2
3
chars = [*('a'..'z'),*('0'..'9')].flatten
#Single expression, can be passed as an argument, allows duplicate characters:
Array.new(len) {|i| chars.sample}.join
  • Example 4
1
2
3
4
def token(length=16)
  chars = [*('A'..'Z'), *('a'..'z'), *(0..9)]
  (0..length).map {chars.sample}.join
end
  • Example 5
1
''.tap {|v| 4.times { v << ('a'..'z').to_a.sample} }
  • Example 6
1
2
3
4
5
6
7
class String

  def self.random(length=10)
    ('a'..'z').sort_by {rand}[0,length].join
  end

end
  • Example 7
1
2
3
(('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a).sample(8).join

([(48..57),(65..90),(97..122)]).sample(8).collect{|x|x.chr}""
  • Example 8
1
2
3
4
5
6
7
8
9
10
11
def secure_random_string(length = 32, non_ambiguous = false)
  characters = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a

  %w{I O l 0 1}.each{ |ambiguous_character|
    characters.delete ambiguous_character
  } if non_ambiguous

  (0...length).map{
    characters[ActiveSupport::SecureRandom.random_number(characters.size)]
  }.join
end
  • Example 9
1
2
3
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
# ruby 1.8 and unix
random_string = `openssl rand -base64 24`

.

Comments

Generate Random Number in Ruby

Sometimes we would also need to generate x random numbers from n to m

1
x.times.map{n + Random.rand( m - n )}
1
2
3
Random.new.rand(n...m)
#in ruby 1.9.3
Random.rand(n...m)

if you only want to select a random item form array.

1
2
%(a b c d e).sample
(n...m).to_a.sample

Some other ways by using SecureRandom

1
2
3
4
5
6
7
8
9
require 'securerandom'

p SecureRandom.random_number(100) #=> 15
p SecureRandom.random_number(100) #=> 88

p SecureRandom.random_number #=> 0.596506046187744
p SecureRandom.random_number #=> 0.350621695741409

p SecureRandom.hex #=> "eb693ec8252cd630102fd0d0fb7c3485"
Comments

Installing Rvm on a Mac - Issues With Gcc

While installing RVM on a mac, one of the major problems we face are due to missing Xcode. We usually get the error below:

1
2
3
4
5
6
7
8
9
10
11
12
13
rvm install 1.9.3
Installing Ruby from source to: /Users/jamie/.rvm/rubies/ruby-1.9.3-p0, this may take a while depending on your cpu(s)...

ruby-1.9.3-p0 - #fetching 
ruby-1.9.3-p0 - #extracted to /Users/jamie/.rvm/src/ruby-1.9.3-p0 (already extracted)
Fetching yaml-0.1.4.tar.gz to /Users/jamie/.rvm/archives
Extracting yaml-0.1.4.tar.gz to /Users/jamie/.rvm/src
Configuring yaml in /Users/jamie/.rvm/src/yaml-0.1.4.
Compiling yaml in /Users/jamie/.rvm/src/yaml-0.1.4.
Installing yaml to /Users/jamie/.rvm/usr
ruby-1.9.3-p0 - #configuring 
ERROR: Error running ' ./configure --prefix=/Users/jamie/.rvm/rubies/ruby-1.9.3-p0 --enable-shared --disable-install-doc --with-libyaml-dir=/Users/jamie/.rvm/usr ', please read /Users/jamie/.rvm/log/ruby-1.9.3-p0/configure.log
ERROR: There has been an error while running configure. Halting the installation.

The Error message also looks like this:

1
2
rvm install 1.9.3
ERROR: The autodetected CC(/usr/bin/gcc-4.2) is LLVM based, it is not yet fully supported by ruby and gems, please read `rvm requirements`, and set CC=/path/to/gcc .

Find the GCC installed in Mac:

1
2
3
4
5
6
gcc -v
Using built-in specs.
Target: i686-apple-darwin11
Configured with: /private/var/tmp/llvmgcc42/llvmgcc42-2336.1~1/src/configure --disable-checking --enable-werror --prefix=/Developer/usr/llvm-gcc-4.2 --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-prefix=llvm- --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin11 --enable-llvm=/private/var/tmp/llvmgcc42/llvmgcc42-2336.1~1/dst-llvmCore/Developer/usr/local --program-prefix=i686-apple-darwin11- --host=x86_64-apple-darwin11 --target=i686-apple-darwin11 --with-gxx-include-dir=/usr/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00)

also look for the files in user/bin

1
2
3
4
5
ls /usr/bin | grep gcc
gcc
i686-apple-darwin11-llvm-gcc-4.2
llvm-gcc
llvm-gcc-4.2

Here are a few ways to resolve this - read them all to get a better understanding of ways to fix issues like these:

  • Install with clang
1
rvm install 1.9.3 --with-gcc=clang
  • Install a lighter version of gcc osx-gcc

LLVM GCC

Be carefull about this, sometimes there are conflicts with Brew

  • The best of them all could still be to use the command line tools for xcode

  • If you face issues with readline, its best to pkg install readline

1
2
rvm pkg install readline
rvm install 1.9.3 --with-gcc=clang --with-readline-dir=$rvm_path/usr

.

Any questions on this, please feel free to ask. We’re here to help…

Comments

Passing Command Line Arguments to Rake Tasks

Sometimes, we need to rake tasks that inserts a paticular user entered value into multiple databases.

We’d like to be able to pass this value into the rake task from the command line, or from another rake task, how can We do this?

1
2
3
4
5
require 'rake'

task :my_task, :arg1, :arg2 do |t, args|
  puts "Args were: #{args}"
end

You can invoke it by using the following:

1
2
3
task :invoke_my_task do
  Rake.application.invoke_task("my_task[1, 2]")
end

or if you prefer this syntax…

1
2
3
task :invoke_my_task_2 do
  Rake::Task[:my_task].invoke(3, 4)
end

A task with prerequisites passes its arguments to it prerequisites(tasks)

1
task :with_prerequisite, :arg1, :arg2, :needs => :my_task

or just a…

1
task :with_prerequisite, [:arg1, :arg2] => :my_task

To specify default values, we take advantage of args being a Rake::TaskArguments object

1
2
3
4
task :with_defaults, :arg1, :arg2 do |t, args|
  args.with_defaults(:arg1 => 1, :arg2 => 2)
  puts "Args with defaults were: #{args}"
end

Here are a few usages:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> rake my_task[1,2]
Args were: {:arg1=>"1", :arg2=>"2"}

> rake "my_task[1, 2]"
Args were: {:arg1=>"1", :arg2=>"2"}

> rake invoke_my_task
Args were: {:arg1=>"1", :arg2=>"2"}

> rake invoke_my_task_2
Args were: {:arg1=>3, :arg2=>4}

> rake with_prerequisite[5,6]
Args were: {:arg1=>"5", :arg2=>"6"}

> rake with_prerequisite_2[7,8]
Args were: {:arg1=>"7", :arg2=>"8"}

> rake with_defaults
Args with defaults were: {:arg1=>:default_1, :arg2=>:default_2}

> rake with_defaults['x','y']
Args with defaults were: {:arg1=>"x", :arg2=>"y"}

For more information…

.

Any questions on this, please feel free to ask. We’re here to help…

Comments

Using NET to Post API Calls With or Without Secure Connections

Using Net module is the best and the eaiest ways to post data or make api calls to urls. Here’s an example

1
2
3
4
5
6
7
8
def post_using_net(url, params={})
  uri = URI.parse(url)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  response = http.post(uri.request_uri, params.to_query)
  response
end

for connections that does not use ssl i.e (https) the following can be removed

1
2
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

Net also handles get, put and delete, to make it work for muliple requests, just use a send to make calls to the methods

1
2
3
4
5
6
7
8
def send_using_net(method, url, params={})
  uri = URI.parse(url)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  response = http.send method, [uri.request_uri, params.to_query]
  response
end

Any questions on this, please feel free to ask. We’re here to help…

Comments

Timestamps Strftime vs Strptime

strftime

Formats date according to the directives in the given format string. The directives begins with a percent (%) character. Any text not listed as a directive will be passed through to the output string.

source link

1
2
3
4
5
6
puts Time.now.strftime("%FT%T%:z")

#  %F - The ISO 8601 date format (%Y-%m-%d)
#  %T - 24-hour time (%H:%M:%S)
#  %:z - hour and minute offset from UTC with a colon (e.g. +09:00)
#  output: 2012-11-28T06:29:36-05:00

strptime

Parses the given representation of date and time with the given template, and creates a date object.

source link

1
2
3
4
format = "%m/%d/%Y %H:%M:%S"
date_time = "11/28/2012 16:39:11.642"

date_obj = DateTime.strptime(date_time, format)

Any questions on this, please feel free to ask. We’re here to help…

Working With Digests and Signatures

MD5 digests

MD5 is a one-way hashing algorithm for creating digest “signatures” or checksums of strings. MD5 digests are 128 bit (16 byte) signatures. MD5 is the most common method of providing checksums for files downloaded over the internet. To create a checksum of an entire file or text convert the whole string.

1
digest = Digest::MD5.hexdigest(string_to_digest)

source link

hmac-sha1

In cryptography, a hash-based message authentication code (HMAC) is a specific construction for calculating a message authentication code (MAC) involving a cryptographic hash function in combination with a secret cryptographic key. As with any MAC, it may be used to simultaneously verify both the data integrity and the authenticity of a message.

source link

In ruby its simple to generate one:

1
2
3
4
5
6
7
gem install ruby-hmac

def hmac_sha1 params={}
  require 'openssl'
  secret_key = 'No telling a secret'
  OpenSSL::HMAC.hexdigest('sha1', secret_key, params)
end

Any questions on this, please feel free to ask. We’re here to help…

Comments

Applying Common Filtering for Rails Api Based Applications

Sometimes there are common sets of fields and id’s that we would like the api to filter before sending the details to the client. It would be great if we can place them in a common place so that they can be changed anytime.

File: lib/api_config.rb

1
2
# Filters out the specified list of fields from the API calls
APIFILTERS = ['id','password','secret__internal_id','updated_at','created_at']

File: config/initializers/json_config.rb

1
2
3
4
5
6
7
8
9
10
# Requiring the api configuration file
require 'api_config'

class ActiveRecord::Base
  def as_json_with_filter(options=Hash.new)
    options[:except] = APIFILTERS
    as_json_without_filter(options)
  end
  alias_method_chain :as_json, :filter
end

the alias_method_chain does two things here:

  • firstly it creates an alias method called as_json_without_filter to as_json

  • secondly it looks for as_json_with_filter and makes that as the new as_json method

The as_json method is one that gets called when the to_json method is called on a model object or a collection of model objects in rails

example: users controller file

1
2
3
4
5
6
7
8
9
class UsersController < ApplicationController

  respond_to :json

  def show
    @user = User.find(params[:id])
    respond_with @user
  end
end

the above would call the as_json method of the user model, we have just overridden the super class to filter out a few fields

1
2
3
4
5
class User < ActiveRecord::Base

def as_json(options={})
  super(:include => :parents)
end

for xml, this is slightly Different

File: config/initializers/xml_config.rb

1
2
3
4
5
6
7
8
9
10
# Requiring the api configuration file
require 'api_config'

class ActiveRecord::Base
  alias_method :to_xml, :old_to_xml
  def to_xml(options=Hash.new)
    options[:except] = APIFILTERS
    old_to_xml(options)
  end
end

Any questions, please feel free to ask. We’re here to help…

Comments