The Silver Lining

Lessons & Learnings from a salesforce certified technical architect.

Archive for the ‘Ruby’ Category

Using the Heroku Shared Database with Sinatra and Active Record

with 6 comments

ActiveRecord is an amazing (mostly) database-agnostic ORM framework and so it’s a natural choice to use with non-Rails frameworks such as Sinatra. Note that I’ll be using sqlite3 locally but the Heroku Shared Database is a Postgres database so I’ll be setting my environments appropriately.

In this post I’ve assumed that you have a Sinatra app that is working locally and on Heroku.

Getting it working locally

First up you’ll need a few extra gems in your Gemfile, once again note that I’m using different databases in development, test and production environments.

source 'http://rubygems.org'

gem 'sinatra'
gem 'activerecord'
gem 'sinatra-activerecord' # excellent gem that ports ActiveRecord for Sinatra

group :development, :test do
  gem 'sqlite3'
end

group :production do
  gem 'pg' # this gem is required to use postgres on Heroku
end

Don’t forget that you’ll need to install the gems using bundler.

bundle install

And you will need to “require” the appropriate files in either your app configuration or the main app controller, the choice is yours 🙂

require 'sinatra/activerecord'

At this point you need to provide information that tells your app how to connect to the database.

configure :development, :test do
  set :database, 'sqlite://development.db'
end

configure :production do
  # Database connection
  db = URI.parse(ENV['DATABASE_URL'] || 'postgres://localhost/mydb')

  ActiveRecord::Base.establish_connection(
    :adapter  => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
    :host     => db.host,
    :username => db.user,
    :password => db.password,
    :database => db.path[1..-1],
    :encoding => 'utf8'
  )
end

You can include this information in your Sinatra app file but I suggest putting the information into a separate configuration file. I keep mine in a file ‘/config/environments.rb’. If you do this you’ll have to include it in your Sinatra app file(s).

require './config/environments'

In order to use migrations (to set up your object model) you’ll need to create a Rakefile with the following code.

# require your app file first
require './app'
require 'sinatra/activerecord/rake'

At this point you can use the typical ActiveRecord Migration syntax to create you migration files, for example:

rake db:create_migration NAME=create_foos

This creates a migration file in ‘./db/migrate’ and this file will be used to create your database table on migration. You will also need to create a class that is the “bridge” between your app and the database table.

class CreateFoos < ActiveRecord::Migration
  def self.up
    create_table :foos do |t|
      t.string :name
    end
  end

  def self.down
    drop_table :foos
  end
end

As with the database environment details this code can be included in your main app class but you should put it into it’s own file and include that in your app instead. Once you’ve done this you can run the following to create the database tables – this is only a local operation for now.

rake db:migrate

At this point you should have a local table and method to apply any CRUD action to said table.

And now for Heroku

Before pushing your new app to heroku you’ll need to add the Shared Database addon.

heroku addons:add shared-database

Commit and push your code to Heroku after which you’ll need to rake the remote database.

heroku rake db:migrate

And that’s it. You now have a ActiveRecord working locally and remotely and can develop in a consist way. Aw yeah.

Written by Wes

April 22, 2012 at 4:09 pm

Posted in Ruby

Tagged with , , , ,

A gem to help you document your Rails ActiveRecord model

with 2 comments

I’ve been using the “annotate” gem for a while and it’s simple whilst incredibly useful. Essentially once run it documents each resource in your database within the appropriate file. Here’s how to get it working.

Step 1

Install the gem. There are a few ways to do this but I usually include the following line in my Gemfile:

gem 'annotate'

Then run “bundle install” from the command line.

Step 2

Generate the schema annotations by running:


annotate

in the root of your rails project directory and it will inject the schema details for each “table” into the respective “model.rb” file e.g. “user.rb” might contain:

# == Schema Information
#
# Table name: users
#
#  id          :integer         not null, primary key
#  screen_name :string(255)
#  name        :string(255)
#  created_at  :datetime
#  updated_at  :datetime
#

Written by Wes

October 21, 2011 at 5:50 pm

“Dropping” a mongohq database on Heroku

leave a comment »

I’ve used inverted commas around the word ‘dropping’ because it doesn’t look like you can drop a mongohq database – what you can do however is drop all the collections in the database. I was doing this through the add-on interface in heroku but that got tired quickly, and after some googling it looked like the solution was to write a custom rake task and drop it into lib/tasks/; the file can be named anything with a ‘.rb’ extension. The code follows:

namespace :mdb do
    desc 'Drops all the collections for the database for the current Rails.env'
    task :drop => :environment do
      if ENV['MONGOHQ_URL']
        uri = URI.parse(ENV['MONGOHQ_URL'])
        conn = Mongo::Connection.from_uri(ENV['MONGOHQ_URL'])
        DB = conn.db(uri.path.gsub(/^\//, ''))
        DB.collections.each do |collection|
          begin
            collection.drop
          rescue
            puts "Can't drop: " + collection.name
          end
        end

      end
    end
end

Note that the exception handler isn’t perfect and essentially all I’m doing is skipping the system collections that can’t be dropped.
Once you’ve deployed this code to the heroku servers it’s simple to execute:

heroku rake mdb:drop

Written by Wes

October 2, 2011 at 5:05 pm

Posted in Ruby

Tagged with , , , , ,

Ruby, Rails & RVM woes

with one comment

I’ve had several issues over the past day pertaining to Ruby, Rails and RVM and all of them were caused by one silly thing.

Problem 1: You can’t swap between Ruby versions using RVM

If you can’t swap between Ruby versions that you know you’ve installed then you’ve probably installed something using “sudo”. It is highly recommended that you install & use RVM in the single user mode as this is easiest. If you do this then all the versions of Ruby etc. that you install will be installed in your home directory (usually ~/.rvm/) instead of system wide and this negates a whole bunch of complexities. Running this command will tell you which ruby executable you’re using:


which ruby

If the executable is not sitting in your home directory e.g. it’s in /usr/local/bin then you’re in a spot of bother. The easiest way I’ve found to fix this is to clear out all the RVM gemsets and start again. I’ve found that I needed to run:


rm -fr ~/.rvm

rm -fr ~/.bin

Be careful with the second command. I’d have a look around that directory before deleting it to make sure it’s not being used by anything else.

Having wiped out these directory you can now using RVM to install fresh versions of Ruby.

Problem 2: Running “rails -v” or “rails” throws an error similar to “`report_activate_error’: Could not find RubyGem rails’

This is assuming you don’t have the first problem or that you’ve corrected it. It’s also most likely to occur if you’re using RVM. The cause here is that you’re using a local version of RVM to manage your Ruby versions but have installed Rails using “sudo” so that it’s been installed system wide. The solution is simple, remove the “sudo” so that rails is installed just for your currently active gemset.


gem install rails --version x.y.z

Written by Wes

August 7, 2011 at 1:38 pm

Posted in Rails, Ruby, RVM

Tagged with , , , , ,