Skip to content

Instantly share code, notes, and snippets.

@boriscy
Created April 28, 2012 15:11
Show Gist options
  • Save boriscy/2519729 to your computer and use it in GitHub Desktop.
Save boriscy/2519729 to your computer and use it in GitHub Desktop.
General module for multitenant
# encoding: utf-8
# app/controllers/application_controller.rb
# author: Boris Barroso
# email: boriscyber@gmail.com
class ApplicationController < ActionController::Base
layout lambda{ |c|
if (c.request.xhr? or params[:xhr])
false
elsif params[:print].present?
"print"
else
"application"
end
}
include Controllers::Authentication
helper_method Controllers::Authentication.helpers
#rescue_from Exception, :with => :render_error
include Controllers::Authorization
include Controllers::OrganisationHelpers
helper_method Controllers::OrganisationHelpers.organisation_helper_methods
protect_from_forgery
before_filter :set_user_session, :if => :user_signed_in?
before_filter :set_page
before_filter :set_organisation, :if => :organisation?
# Sets the organisation_id to help to set in the models and the search path
def set_organisation
raise "You must set the organisation" if session[:organisation].blank?
OrganisationSession.set session[:organisation]
begin
PgTools.set_search_path PgTools.get_schema_name(session[:organisation][:id])
rescue
session[:organisation] = nil
session[:user_id] = nil
redirect_to "/users/sign_out"
end
end
end
# encoding: utf-8
# app/models/organisation_session.rb
# author: Boris Barroso
# email: boriscyber@gmail.com
# Used to access the organisation_id in the models
class OrganisationSession
KEYS = [:id, :name, :currency_id, :currency_name, :currency_symbol, :due_date]
class << self
attr_reader :organisation_id, :name, :currency_id
# Stores using de application_controller the current_user for devise
# @param [Hash] details from the organisation
def set(organisation)
raise "The OrganisationSession couln't be set' the param must be a hash" unless organisation.is_a? Hash
@organisation_id = organisation[:id]
@name = organisation[:name]
@currency_id = organisation[:currency_id]
end
alias set= set
# Initialize variables
def destroy
@organisation_id = @org_name = @currency_id = nil
end
# Returns the currencies of the current organisation
def currencies
o = Organisation.find(@organisation_id)
[o.currency]+ o.currencies
end
def currency_name
current_organisation.currency_name
end
def currency_plural
current_organisation.currency_plural
end
def currency_symbol
current_organisation.currency_symbol
end
def current_organisation
@org ||= Organisation.find(organisation_id)
end
end
end
# lib/pg_tools.rb
module PgTools
extend self
def get_schema_name(id)
"schema#{id}"
end
def public_schema?
res = connection.execute("SHOW search_path")
res.getvalue(0,0) === "public"
end
def with_schema(schema_name)
old_search_path = connection.schema_search_path
set_search_path(schema_name)
connection.schema_search_path = schema_name
result = yield
connection.schema_search_path = old_search_path
reset_search_path
result
end
def set_search_path(schema_name)
connection.execute "SET search_path TO #{schema_name}"
end
def reset_search_path
connection.execute "SET search_path TO public"
ActiveRecord::Base.connection.reset!
end
def current_search_path
connection.select_value "SHOW search_path"
end
def create_schema(schema_name)
raise "#{schema_name} already exists" if schema_exists?(schema_name)
ActiveRecord::Base.logger.info "Create #{schema_name}"
connection.execute "CREATE SCHEMA #{schema_name}"
end
def drop_schema(schema_name)
raise "#{schema_name} does not exists" unless schema_exists?(schema_name)
ActiveRecord::Base.logger.info "Drop schema #{schema_name}"
connection.execute "DROP SCHEMA #{schema_name} CASCADE"
end
def migrate_schema(schema_name, version = nil)
with_schema(schema_name) do
ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, version ? version.to_i : nil)
end
end
def load_schema_into_schema(schema_name)
ActiveRecord::Base.logger.info "Enter schema #{schema_name}."
with_schema(schema_name) do
file = "#{Rails.root}/db/schema.rb"
if File.exists?(file)
ActiveRecord::Base.logger.info "Load the schema #{file}"
load(file)
else
raise "#{file} desn't exist yet. It's possible that you just ran a migration!"
end
end
end
def schema_exists?(schema_name)
all_schemas.include?(schema_name)
end
def all_schemas
connection.select_values("SELECT * FROM pg_namespace WHERE nspname != 'information_schema' AND nspname NOT LIKE 'pg%'")
end
def with_all_schemas
all_schemas.each do |schema_name|
with_schema(schema_name) do
yield
end
end
end
protected
def connection
ActiveRecord::Base.connection
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment