leases 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ /spec/leaser.sqlite3
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - ruby-head
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in leases.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Arjen Oosterkamp
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,100 @@
1
+ # Leases
2
+
3
+ Database multi-tenancy for Rails.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your Gemfile and run `bundle`.
8
+
9
+ ```
10
+ gem 'leases'
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```ruby
16
+ # app/models/account.rb
17
+ class Account < ActiveRecord::Base
18
+ leases
19
+ end
20
+
21
+ # app/controllers/application_controller.rb
22
+ class ApplicationController < ActionController::Base
23
+ visit_as :current_account
24
+
25
+ protected
26
+
27
+ def current_account
28
+ @account
29
+ end
30
+ end
31
+ ```
32
+
33
+ That's it. Now you have a fully multi-tenant app.
34
+
35
+ ## More
36
+
37
+ ```ruby
38
+ # app/models/account.rb
39
+ class Account < ActiveRecord::Base
40
+
41
+ # Customize the leaser name (used for the database name)
42
+ leases :name => :slug
43
+ leases :name => Proc.new { |c| "acount_#{c.id}" }
44
+
45
+ # Callbacks
46
+ on_enter :set_something # => Called on :enter (part of visit)
47
+ on_leave :clear_something # => Called on :leave (part of visit)
48
+
49
+ on_lease :create_something # => Called on new lease
50
+ on_break :delete_something # => Called on break of lease
51
+
52
+ end
53
+
54
+ account = Account.create :name => 'John Doe' # => Calls account.lease! and sets up database 'account-1'
55
+
56
+ account.enter # => Switches to database 'account-1'
57
+ account.leave # => Switches back to regular database
58
+
59
+ account.visit do
60
+ # You are now in account database context
61
+ # Context is automatically cleared after visit
62
+ end
63
+
64
+ account.destroy # => Calls account.break! and deletes leaser database
65
+ ```
66
+
67
+ ## Shared models
68
+
69
+ By default only the leaser model is a shared model. The rest is stored in a separate database. There may be situations in which you want to have more shared models, such as a `User` model. You can configure this as such:
70
+
71
+ ```ruby
72
+ # app/models/user.rb
73
+ class User < ActiveRecord::Base
74
+ shared_by_leasers
75
+ end
76
+ ```
77
+
78
+ ## Under the hood
79
+
80
+ We're using `apartment` for managing and switching databases. This is a fantastic gem that you should check out: https://github.com/influitive/apartment. Apartment supports MySQL and PostgreSQL.
81
+
82
+ ## Migrating
83
+
84
+ ```
85
+ rake apartment:migrate
86
+ ```
87
+
88
+ This will migrate all leaser databases.
89
+
90
+ ## Other solutions
91
+
92
+ If you're looking for multi-tenancy without having multiple databases then you should check out acts_as_tenant: https://github.com/ErwinM/acts_as_tenant.
93
+
94
+ ## Contributing
95
+
96
+ 1. Fork it
97
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
98
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
99
+ 4. Push to the branch (`git push origin my-new-feature`)
100
+ 5. Create new Pull Request
@@ -0,0 +1,5 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task :default => :spec
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'leases/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'leases'
8
+ gem.version = Leases::VERSION
9
+ gem.authors = ['Arjen Oosterkamp']
10
+ gem.email = ['mail@arjen.me']
11
+ gem.description = %q{Database multi-tenancy for Rails.}
12
+ gem.summary = %q{Database multi-tenancy for Rails.}
13
+ gem.homepage = 'https://github.com/Arjeno/leases'
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_development_dependency 'bundler', '>= 1.0.0'
21
+ gem.add_development_dependency 'rake'
22
+ gem.add_development_dependency 'rspec', '>= 2.3'
23
+ gem.add_development_dependency 'rspec-rails', '~> 2.0'
24
+ gem.add_development_dependency 'sqlite3'
25
+ gem.add_development_dependency 'with_model'
26
+
27
+ gem.add_dependency 'rails', '>= 3.0'
28
+ gem.add_dependency 'apartment', '>= 0.20'
29
+ end
@@ -0,0 +1,34 @@
1
+ require 'leases/railtie'
2
+ require 'leases/version'
3
+ require 'leases/model'
4
+ require 'leases/controller'
5
+
6
+ module Leases
7
+
8
+ extend self
9
+
10
+ attr_accessor :leasers
11
+ self.leasers = []
12
+
13
+ # Add leaser to array of leasers.
14
+ #
15
+ # => leasing(Account)
16
+ def leasing(object)
17
+ self.leasers << object.name
18
+ self.leasers.uniq!
19
+
20
+ Apartment.database_names = Proc.new { Leases.leaser_names }
21
+
22
+ object
23
+ end
24
+
25
+ def leaser_names(preload=true)
26
+ Rails.application.eager_load! if preload
27
+
28
+ leasers.map do |l|
29
+ model = l.constantize
30
+ model.all.collect(&:leaser_name)
31
+ end.flatten
32
+ end
33
+
34
+ end
@@ -0,0 +1,32 @@
1
+ module Leases
2
+ module Controller
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+
8
+ helper_method :current_leaser
9
+
10
+ end
11
+
12
+ module ClassMethods
13
+
14
+ # Uses a leaser as the context in a controller.
15
+ #
16
+ # => visit_as :current_account
17
+ def visit_as(leaser)
18
+ around_filter do |c, block|
19
+ c.send(leaser).visit(&block)
20
+ end
21
+ end
22
+
23
+ end
24
+
25
+ def current_leaser
26
+ Thread.current[:leaser]
27
+ end
28
+
29
+ end
30
+ end
31
+
32
+ ActionController::Base.send(:include, Leases::Controller)
@@ -0,0 +1,32 @@
1
+ require 'leases/model/base'
2
+ require 'leases/model/callbacks'
3
+
4
+ module Leases
5
+ module Model
6
+
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+
11
+ def leases(options={})
12
+ include Base
13
+ include Callbacks
14
+
15
+ shared_by_leasers
16
+
17
+ Leases.leasing(self)
18
+ self.leases_options = options
19
+ end
20
+
21
+ def shared_by_leasers
22
+ Apartment.excluded_models ||= []
23
+ Apartment.excluded_models += [self.name]
24
+ Apartment.excluded_models.uniq!
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
31
+
32
+ ActiveRecord::Base.send(:include, Leases::Model)
@@ -0,0 +1,75 @@
1
+ module Leases
2
+ module Model
3
+ module Base
4
+
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+
9
+ cattr_accessor :leases_options
10
+ self.leases_options = {}
11
+
12
+ end
13
+
14
+ # Name of the leaser, used for naming the database.
15
+ # This can be set in the leaser_options. Must be unique.
16
+ def leaser_name
17
+ name = self.class.leases_options[:name]
18
+
19
+ if name.nil?
20
+ [self.class.name.parameterize, id].join('-')
21
+ elsif name.is_a?(Symbol)
22
+ send(name)
23
+ elsif name.is_a?(Proc)
24
+ name.call(self)
25
+ end
26
+ end
27
+
28
+ # Enter the leaser-context.
29
+ #
30
+ # => account.enter
31
+ def enter
32
+ Apartment::Database.switch(leaser_name)
33
+ Thread.current[:leaser] = self
34
+ end
35
+
36
+ # Leave the leaser-context.
37
+ #
38
+ # => account.leave
39
+ def leave
40
+ Thread.current[:leaser] = nil
41
+ Apartment::Database.reset
42
+ end
43
+
44
+ # Visit a leaser by entering and leaving.
45
+ # Very useful for executing code in a leaser-context
46
+ #
47
+ # => account.visit { User.find(1) }
48
+ def visit(&block)
49
+ enter
50
+ begin
51
+ yield
52
+ ensure
53
+ leave
54
+ end
55
+ end
56
+
57
+ # Create a new lease.
58
+ # This is usually called when a model is created.
59
+ #
60
+ # => account.lease!
61
+ def lease!
62
+ Apartment::Database.create(leaser_name)
63
+ end
64
+
65
+ # Break a lease.
66
+ # This is usually called when a model is destroyed.
67
+ #
68
+ # => account.break!
69
+ def break!
70
+ Apartment::Database.drop(leaser_name)
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,59 @@
1
+ module Leases
2
+ module Model
3
+ module Callbacks
4
+
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+
9
+ ## Callbacks
10
+
11
+ after_create :lease!
12
+ after_destroy :break!
13
+
14
+ ## Custom callbacks
15
+
16
+ define_model_callbacks :enter, :leave, :lease, :break
17
+
18
+ # Define callback aliases
19
+ #
20
+ # => on_enter :method
21
+ # => on_leave :method
22
+ # => on_lease :method
23
+ # => on_break :method
24
+ class << self
25
+ alias :on_enter :after_enter
26
+ alias :on_leave :after_leave
27
+ alias :on_lease :after_lease
28
+ alias :on_break :after_break
29
+ end
30
+
31
+ end
32
+
33
+ def enter
34
+ run_callbacks :enter do
35
+ super
36
+ end
37
+ end
38
+
39
+ def leave
40
+ run_callbacks :leave do
41
+ super
42
+ end
43
+ end
44
+
45
+ def lease!
46
+ run_callbacks :lease do
47
+ super
48
+ end
49
+ end
50
+
51
+ def break!
52
+ run_callbacks :break do
53
+ super
54
+ end
55
+ end
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,12 @@
1
+ require 'rails'
2
+ require 'apartment'
3
+
4
+ module Leases
5
+ class Railtie < Rails::Railtie
6
+
7
+ config.to_prepare do
8
+ Apartment.database_names = Proc.new { Leases.leaser_names }
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Leases
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ class AnonymousController < ActionController::Base
4
+ include Rails.application.routes.url_helpers
5
+ def index
6
+ @account = Thread.current[:leaser]
7
+ @current_leaser = current_leaser
8
+ render :text => :none
9
+ end
10
+ end
11
+
12
+ describe Leases::Controller, :type => :controller do
13
+
14
+ with_model :Account do
15
+ table do |t|
16
+ t.string :name
17
+ t.timestamps
18
+ end
19
+ model do
20
+ leases
21
+ end
22
+ end
23
+
24
+ controller(AnonymousController) do
25
+ visit_as :current_account
26
+ end
27
+
28
+ let(:account) { Account.create(:name => 'John Doe') }
29
+
30
+ before(:each) do
31
+ controller.stub(:current_account).and_return(account)
32
+ get :index
33
+ end
34
+
35
+ it { assigns(:account).should == account }
36
+ it { assigns(:current_leaser).should == account }
37
+
38
+ end
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ describe Leases::Model::Base do
4
+
5
+ with_model :Account do
6
+ table do |t|
7
+ t.string :name
8
+ t.string :slug
9
+ t.timestamps
10
+ end
11
+ end
12
+
13
+ before(:each) { Account.leases options }
14
+
15
+ let(:options) { {} }
16
+ let(:account) { Account.create(:name => 'John Doe', :slug => 'john-doe') }
17
+
18
+ subject { account }
19
+
20
+ describe :leaser_name do
21
+
22
+ context 'default' do
23
+
24
+ let(:options) { {} }
25
+
26
+ its(:leaser_name) { should == "account-#{account.id}" }
27
+
28
+ end
29
+
30
+ context 'with symbol' do
31
+
32
+ let(:options) { { :name => :slug } }
33
+
34
+ its(:leaser_name) { should == account.slug }
35
+
36
+ end
37
+
38
+ context 'with proc' do
39
+
40
+ let(:options) { { :name => Proc.new { |a| [a.id, a.name].join('-') } } }
41
+
42
+ its(:leaser_name) { should == "#{account.id}-#{account.name}" }
43
+
44
+ end
45
+
46
+ end
47
+
48
+ describe :enter do
49
+
50
+ after(:each) { account.enter }
51
+
52
+ it { Apartment::Database.should_receive(:switch).with(account.leaser_name) }
53
+ it { Thread.current[:leaser].id.should == account.id }
54
+
55
+ end
56
+
57
+ describe :leave do
58
+
59
+ after(:each) { account.leave }
60
+
61
+ it { Apartment::Database.should_receive(:reset) }
62
+ it { Thread.current[:leaser].should == nil }
63
+
64
+ end
65
+
66
+ describe :visit do
67
+
68
+ it 'should enter and leave' do
69
+ account.should_receive(:enter)
70
+ account.should_receive(:leave)
71
+
72
+ account.visit {}
73
+ end
74
+
75
+ end
76
+
77
+ describe :lease! do
78
+
79
+ after(:each) { account.lease! }
80
+
81
+ it { Apartment::Database.should_receive(:create).with(account.leaser_name) }
82
+
83
+ end
84
+
85
+ describe :break! do
86
+
87
+ after(:each) { account.break! }
88
+
89
+ it { Apartment::Database.should_receive(:drop).with(account.leaser_name) }
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,169 @@
1
+ require 'spec_helper'
2
+
3
+ describe Leases::Model::Callbacks do
4
+
5
+ with_model :Account do
6
+ table do |t|
7
+ t.string :name
8
+ t.string :slug
9
+ t.timestamps
10
+ end
11
+ end
12
+
13
+ before(:each) { Account.leases }
14
+
15
+ let(:account) { Account.create }
16
+
17
+ subject { account }
18
+
19
+ describe :enter do
20
+
21
+ before(:each) do
22
+ account.stub(:_test_callback_before_enter)
23
+ account.stub(:_test_callback_after_enter)
24
+ Account.before_enter :_test_callback_before_enter
25
+ Account.after_enter :_test_callback_after_enter
26
+ end
27
+
28
+ after(:each) { account.enter }
29
+
30
+ it { account.should_receive(:_test_callback_before_enter) }
31
+ it { account.should_receive(:_test_callback_after_enter) }
32
+
33
+ describe :aliases do
34
+
35
+ describe :on_enter do
36
+
37
+ before(:each) do
38
+ account.stub(:_test_callback_on_enter)
39
+ Account.on_enter :_test_callback_on_enter
40
+ end
41
+
42
+ it { account.should_receive(:_test_callback_on_enter) }
43
+
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ describe :leave do
51
+
52
+ before(:each) do
53
+ account.stub(:_test_callback_before_leave)
54
+ account.stub(:_test_callback_after_leave)
55
+ Account.before_leave :_test_callback_before_leave
56
+ Account.after_leave :_test_callback_after_leave
57
+ end
58
+
59
+ after(:each) { account.leave }
60
+
61
+ it { account.should_receive(:_test_callback_before_leave) }
62
+ it { account.should_receive(:_test_callback_after_leave) }
63
+
64
+ describe :aliases do
65
+
66
+ describe :on_leave do
67
+
68
+ before(:each) do
69
+ account.stub(:_test_callback_on_leave)
70
+ Account.on_leave :_test_callback_on_leave
71
+ end
72
+
73
+ it { account.should_receive(:_test_callback_on_leave) }
74
+
75
+ end
76
+
77
+ end
78
+
79
+ end
80
+
81
+ describe :lease! do
82
+
83
+ describe :after_create do
84
+
85
+ let(:account) { Account.new }
86
+
87
+ after(:each) { account.save }
88
+
89
+ it { account.should_receive(:lease!) }
90
+
91
+ end
92
+
93
+ describe :custom do
94
+
95
+ before(:each) do
96
+ account.stub(:_test_callback_before_lease)
97
+ account.stub(:_test_callback_after_lease)
98
+ Account.before_lease :_test_callback_before_lease
99
+ Account.after_lease :_test_callback_after_lease
100
+ end
101
+
102
+ after(:each) { account.lease! }
103
+
104
+ it { account.should_receive(:_test_callback_before_lease) }
105
+ it { account.should_receive(:_test_callback_after_lease) }
106
+
107
+ describe :aliases do
108
+
109
+ describe :on_lease do
110
+
111
+ before(:each) do
112
+ account.stub(:_test_callback_on_lease)
113
+ Account.on_lease :_test_callback_on_lease
114
+ end
115
+
116
+ it { account.should_receive(:_test_callback_on_lease) }
117
+
118
+ end
119
+
120
+ end
121
+
122
+ end
123
+
124
+ end
125
+
126
+ describe :break! do
127
+
128
+ describe :after_destroy do
129
+
130
+ after(:each) { account.destroy }
131
+
132
+ it { account.should_receive(:break!) }
133
+
134
+ end
135
+
136
+ describe :custom do
137
+
138
+ before(:each) do
139
+ account.stub(:_test_callback_before_break)
140
+ account.stub(:_test_callback_after_break)
141
+ Account.before_break :_test_callback_before_break
142
+ Account.after_break :_test_callback_after_break
143
+ end
144
+
145
+ after(:each) { account.break! }
146
+
147
+ it { account.should_receive(:_test_callback_before_break) }
148
+ it { account.should_receive(:_test_callback_after_break) }
149
+
150
+ describe :aliases do
151
+
152
+ describe :on_break do
153
+
154
+ before(:each) do
155
+ account.stub(:_test_callback_on_break)
156
+ Account.on_break :_test_callback_on_break
157
+ end
158
+
159
+ it { account.should_receive(:_test_callback_on_break) }
160
+
161
+ end
162
+
163
+ end
164
+
165
+ end
166
+
167
+ end
168
+
169
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Leases::Model do
4
+
5
+ with_model :Account do
6
+ table do |t|
7
+ t.string :name
8
+ t.timestamps
9
+ end
10
+ end
11
+
12
+ describe :leases do
13
+
14
+ it { Account.respond_to?(:leases).should be_true }
15
+
16
+ it 'should set leases_options' do
17
+ Account.leases :name => :slug
18
+ Account.leases_options.should == { :name => :slug }
19
+ end
20
+
21
+ it 'should add the class to a list of leasers' do
22
+ Account.leases :name => :slug
23
+ Leases.leasers.should include 'Account'
24
+ end
25
+
26
+ end
27
+
28
+ describe :shared_by_leasers do
29
+
30
+ with_model :User do
31
+ table do |t|
32
+ t.string :name
33
+ t.timestamps
34
+ end
35
+ end
36
+
37
+ before(:each) { User.shared_by_leasers }
38
+
39
+ it { Apartment.excluded_models.should include 'User' }
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Leases do
4
+
5
+ with_model :Account do
6
+ table do |t|
7
+ t.string :name
8
+ t.timestamps
9
+ end
10
+ model do
11
+ leases
12
+ end
13
+ end
14
+
15
+ describe :leasing do
16
+
17
+ before(:each) { Leases.leasing(Account) }
18
+
19
+ it { Leases.leasers.should == ['Account'] }
20
+ it { Apartment.excluded_models.should include 'Account' }
21
+
22
+ end
23
+
24
+ describe :leaser_names do
25
+
26
+ let!(:account_1) { Account.create }
27
+ let!(:account_2) { Account.create }
28
+
29
+ it { Leases.leaser_names.should == [account_1.leaser_name, account_2.leaser_name] }
30
+ it { Apartment.database_names.should == Leases.leaser_names }
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,31 @@
1
+ require 'active_record'
2
+ require 'action_controller'
3
+
4
+ require 'leases'
5
+ require 'with_model'
6
+ require 'rspec/rails'
7
+
8
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3',
9
+ :database => File.dirname(__FILE__) + '/leaser.sqlite3')
10
+
11
+ Dir['spec/support/**/*.rb'].each { |f| load f }
12
+
13
+ RSpec.configure do |config|
14
+
15
+ config.mock_with :rspec
16
+ config.extend WithModel
17
+
18
+ config.before(:each) do
19
+ # Stub Apartment database interactions
20
+ Apartment::Database.stub(:switch)
21
+ Apartment::Database.stub(:reset)
22
+ Apartment::Database.stub(:create)
23
+ Apartment::Database.stub(:drop)
24
+ end
25
+
26
+ end
27
+
28
+ module Dummy
29
+ class Application < Rails::Application
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,205 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: leases
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Arjen Oosterkamp
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.0.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.0.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '2.3'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '2.3'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec-rails
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '2.0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '2.0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: sqlite3
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: with_model
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rails
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '3.0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '3.0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: apartment
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0.20'
134
+ type: :runtime
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0.20'
142
+ description: Database multi-tenancy for Rails.
143
+ email:
144
+ - mail@arjen.me
145
+ executables: []
146
+ extensions: []
147
+ extra_rdoc_files: []
148
+ files:
149
+ - .gitignore
150
+ - .travis.yml
151
+ - Gemfile
152
+ - LICENSE.txt
153
+ - README.md
154
+ - Rakefile
155
+ - leases.gemspec
156
+ - lib/leases.rb
157
+ - lib/leases/controller.rb
158
+ - lib/leases/model.rb
159
+ - lib/leases/model/base.rb
160
+ - lib/leases/model/callbacks.rb
161
+ - lib/leases/railtie.rb
162
+ - lib/leases/version.rb
163
+ - spec/leases/controller_spec.rb
164
+ - spec/leases/model/base_spec.rb
165
+ - spec/leases/model/callbacks_spec.rb
166
+ - spec/leases/model_spec.rb
167
+ - spec/leases_spec.rb
168
+ - spec/spec_helper.rb
169
+ homepage: https://github.com/Arjeno/leases
170
+ licenses: []
171
+ post_install_message:
172
+ rdoc_options: []
173
+ require_paths:
174
+ - lib
175
+ required_ruby_version: !ruby/object:Gem::Requirement
176
+ none: false
177
+ requirements:
178
+ - - ! '>='
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ segments:
182
+ - 0
183
+ hash: -3059890359605888421
184
+ required_rubygems_version: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ segments:
191
+ - 0
192
+ hash: -3059890359605888421
193
+ requirements: []
194
+ rubyforge_project:
195
+ rubygems_version: 1.8.24
196
+ signing_key:
197
+ specification_version: 3
198
+ summary: Database multi-tenancy for Rails.
199
+ test_files:
200
+ - spec/leases/controller_spec.rb
201
+ - spec/leases/model/base_spec.rb
202
+ - spec/leases/model/callbacks_spec.rb
203
+ - spec/leases/model_spec.rb
204
+ - spec/leases_spec.rb
205
+ - spec/spec_helper.rb