tenancy 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- OGQ1N2M3MjhhMTIwNzUwNDg5MjM3YjdmZTAzNmU0MjViYjk1ZjhjYQ==
5
- data.tar.gz: !binary |-
6
- MzUyY2NjNjA0YWRlOGY3M2QzZjY5ODI1Y2I5ZGU4ODMyYmI4YzljZA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- YjM4NWFhMjEwZTAxMGZhNTRmZTcyMWYwYzQ2Njk2ZjNkZTZlMDg3YjRjYTRi
10
- ZWY2OTg3ODliYzQ5YzQwMjNkYmRlNzc4MTZmMTdlZTI0OTAzNjI2ZGQ3MmIz
11
- NzUxNjFjYzc3NDc1MmE0NzY4Mzg0YTUxZDYyNWE3ZDU5MDkyNDY=
12
- data.tar.gz: !binary |-
13
- MGI2MWY0ZjI2NjM1ZDcyMWRhMTAwNDhkMzIxOTIwNGQ2YmYzYmM4NmNlZjk5
14
- YzE1MWJhNDUwZTAyNjY4M2M3YzViNjEyYzI0MzU4YTlmMzRiYmExZGJkMzRh
15
- MTQ4MWI3NWQ3MzhmNDQwZjBmMGY0YjE1MTc2Y2QyNTQwNDQ2YTc=
2
+ SHA1:
3
+ metadata.gz: 960f4ccd4c80911a5f803c6865f782a468e166e7
4
+ data.tar.gz: 387cf8e4f3f74bc79ed2f28402c4c33b641788b3
5
+ SHA512:
6
+ metadata.gz: 6a41030d55da3b492c2325f5b61c8feb4cf976793d3388d10eeeace10d354d4ad7fa6267c5c7f6084e62734468d0d05981042a40843cac3dfc0b8de6a4780e13
7
+ data.tar.gz: 943e3ccd96321fa385a5e0a689c4ff03b43cb5eaf445f70337e166484e5dd2ab7f6ae5a9f6fd285337f7dc0c43d86ed7b15d76de36c47fefa1d2cbad7b469404
data/.gitignore CHANGED
@@ -3,6 +3,7 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
+ gemfiles/*.lock
6
7
  Gemfile.lock
7
8
  InstalledFiles
8
9
  _yardoc
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ script: "bundle exec rake spec"
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ env:
7
+ - CODECLIMATE_REPO_TOKEN=891d362268d07d6ff0f5534f92252b6195f6be8795054d3627643eb6314a8c9e
8
+ gemfile:
9
+ - gemfiles/active_record_32.gemfile
10
+ - gemfiles/active_record_40.gemfile
11
+ notifications:
12
+ email: false
13
+ addons:
14
+ code_climate:
15
+ repo_token: 891d362268d07d6ff0f5534f92252b6195f6be8795054d3627643eb6314a8c9e
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in tenancy.gemspec
4
4
  gemspec
5
+
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Tenancy
1
+ # Tenancy [![Build Status](https://travis-ci.org/yoolk/tenancy.png?branch=master)](https://travis-ci.org/yoolk/tenancy) [![Code Climate](https://codeclimate.com/repos/527a1d45f3ea005378005fdb/badges/cfbc9ff8993d02e13b9d/gpa.png)](https://codeclimate.com/repos/527a1d45f3ea005378005fdb/feed)
2
2
 
3
- `tenancy` is a simple gem that provides multi-tenancy support on activerecord through scoping. I suggest you to watch an excellent [RailsCast on Multitenancy with Scopes](http://railscasts.com/episodes/388-multitenancy-with-scopes) and read this book [Multitenancy with Rails](https://leanpub.com/multi-tenancy-rails).
3
+ **Tenancy** is a simple gem that provides multi-tenancy support on activerecord through scoping. I suggest you to watch an excellent [RailsCast on Multitenancy with Scopes](http://railscasts.com/episodes/388-multitenancy-with-scopes) and read this book [Multitenancy with Rails](https://leanpub.com/multi-tenancy-rails).
4
4
 
5
5
  ## Installation
6
6
 
@@ -65,6 +65,7 @@ class Communication < ActiveRecord::Base
65
65
  include Tenancy::ResourceScope
66
66
 
67
67
  scope_to :portal, :listing
68
+ default_scope -> { where(is_active: true) }
68
69
  validates_uniqueness_in_scope :value
69
70
  end
70
71
 
@@ -77,13 +78,21 @@ class ExtraCommunication < ActiveRecord::Base
77
78
  validates_uniqueness_in_scope :value
78
79
  end
79
80
 
80
- Portal.current = 1
81
- Listing.find(1).to_sql
81
+ > Portal.current = 1
82
+ > Listing.find(1).to_sql
82
83
  # => SELECT "listings".* FROM "listings" WHERE "portal_id" = 1 AND "id" = 1
83
84
 
84
- Listing.current = 1
85
- Communication.find(1).to_sql
86
- # => SELECT "communications".* FROM "communications" WHERE "portal_id" = 1 AND "listing_id" = 1 AND "id" = 1
85
+ > Listing.current = 1
86
+ > Communication.find(1).to_sql
87
+ # => SELECT "communications".* FROM "communications" WHERE "portal_id" = 1 AND "listing_id" = 1 AND "is_active" = true AND "id" = 1
88
+
89
+ # unscoped :current_portal, :current_listing
90
+ > Communication.without_scope(:portal).find(1)
91
+ # => SELECT "communications".* FROM "communications" WHERE "listing_id" = 1 AND "is_active" = true AND "id" = 1
92
+ > Communication.without_scope(:listing).find(1)
93
+ # => SELECT "communications".* FROM "communications" WHERE "portal_id" = 1 AND "is_active" = true AND "id" = 1
94
+ > Communication.without_scope(:portal, :listing).find(1)
95
+ # => SELECT "communications".* FROM "communications" WHERE "is_active" = true AND "id" = 1
87
96
  ```
88
97
 
89
98
  `scope_to :portal` does 4 things:
@@ -107,13 +116,32 @@ class ApplicationController < ActionController::Base
107
116
  around_filter :route_domain
108
117
 
109
118
  protected
110
- def route_domain(&block)
111
- Portal.with(current_portal, &block)
112
- end
113
119
 
114
- def current_portal
115
- @current_portal ||= Portal.find_by_domain_name(request.host)
116
- end
120
+ def route_domain(&block)
121
+ Portal.with(current_portal, &block)
122
+ end
123
+
124
+ def current_portal
125
+ @current_portal ||= Portal.find_by_domain_name(request.host)
126
+ end
127
+ end
128
+ ```
129
+
130
+ From version 0.2.0 up, you don't need to use `around_filter` because this gem add [request_store](https://github.com/steveklabnik/request_store) as dependency. It will clear threaded variables inside middleware on every request. You can just use `before_filter` to set the current tenant.
131
+
132
+ ```ruby
133
+ class ApplicationController < ActionController::Base
134
+ before_filter :set_current_portal
135
+
136
+ protected
137
+
138
+ def current_portal
139
+ @current_portal
140
+ end
141
+
142
+ def set_current_portal
143
+ @current_portal = Portal.find_by_domain_name(request.host)
144
+ end
117
145
  end
118
146
  ```
119
147
 
@@ -134,6 +162,12 @@ require "tenancy/matchers"
134
162
 
135
163
  Example:
136
164
 
165
+ ```ruby
166
+ describe Portal do
167
+ it { should be_a_tenant }
168
+ end
169
+ ```
170
+
137
171
  ```ruby
138
172
  describe Listing do
139
173
  it { should have_scope_to(:portal) }
data/Rakefile CHANGED
@@ -1 +1,28 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = FileList['spec/**/*_spec.rb']
8
+ end
9
+
10
+ task :default => "spec:all"
11
+
12
+ namespace :spec do
13
+ %w(active_record_40 active_record_32).each do |gemfile|
14
+ desc "Run Tests against #{gemfile}"
15
+ task gemfile do
16
+ sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle --quiet"
17
+ sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle exec rake spec"
18
+ end
19
+ end
20
+
21
+ desc "Run Tests against active_record versions"
22
+ task :all do
23
+ %w(active_record_40 active_record_32).each do |gemfile|
24
+ sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle --quiet"
25
+ sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle exec rake spec"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 3.2.13', :require => 'active_record'
4
+
5
+ gem "codeclimate-test-reporter", group: :test, require: nil
6
+
7
+ gemspec :path => '../'
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 4.0.1', :require => 'active_record'
4
+
5
+ gem "codeclimate-test-reporter", group: :test, require: nil
6
+
7
+ gemspec :path => '../'
@@ -7,6 +7,10 @@ module Tenancy
7
7
  HaveScopeToMatcher.new(name)
8
8
  end
9
9
 
10
+ def be_a_tenant
11
+ BeATenant.new
12
+ end
13
+
10
14
  class HaveScopeToMatcher
11
15
  def initialize(scope_name)
12
16
  @scope_name = scope_name
@@ -37,7 +41,7 @@ module Tenancy
37
41
  scoped_class = reflection.class_name.constantize
38
42
 
39
43
  if scoped_class.current_id
40
- actual_class.scoped.to_sql.include? %Q{#{actual_class.quoted_table_name}.#{scoped_class.connection.quote_column_name(reflection.foreign_key)} = #{scoped_class.connection.quote(scoped_class.current_id)}}
44
+ actual_class.where(nil).to_sql.include? %Q{#{actual_class.quoted_table_name}.#{scoped_class.connection.quote_column_name(reflection.foreign_key)} = #{scoped_class.connection.quote(scoped_class.current_id)}}
41
45
  else
42
46
  true
43
47
  end
@@ -51,6 +55,23 @@ module Tenancy
51
55
  end
52
56
  end
53
57
  end
58
+
59
+ class BeATenant
60
+ attr_accessor :klass
61
+
62
+ def matches?(instance)
63
+ self.klass = instance.class
64
+ klass.included_modules.include? Tenancy::Resource
65
+ end
66
+
67
+ def failure_message
68
+ "Expected to call `include Tenancy::Resource` inside #{klass}"
69
+ end
70
+
71
+ def description
72
+ "require to call `include Tenancy::Resource`"
73
+ end
74
+ end
54
75
  end
55
76
  end
56
77
  end
@@ -59,4 +80,4 @@ end
59
80
  require 'rspec/core'
60
81
  RSpec.configure do |config|
61
82
  config.include Tenancy::Shoulda::Matchers
62
- end
83
+ end
@@ -14,11 +14,11 @@ module Tenancy
14
14
  find(value)
15
15
  end
16
16
 
17
- Thread.current["#{name}.current"] = tenant
17
+ RequestStore.store[:"#{name}.current"] = tenant
18
18
  end
19
19
 
20
20
  def current
21
- Thread.current["#{name}.current"]
21
+ RequestStore.store[:"#{name}.current"]
22
22
  end
23
23
 
24
24
  def current_id
@@ -37,6 +37,7 @@ module Tenancy
37
37
  self.current = old
38
38
  end
39
39
  end
40
+ alias_method :use, :with
40
41
  end
41
42
  end
42
43
  end
@@ -12,13 +12,12 @@ module Tenancy
12
12
  def scope_to(*resources)
13
13
  options = resources.extract_options!.dup
14
14
  raise ArgumentError, 'options should be blank if there are multiple resources' if resources.count > 1 and options.present?
15
-
15
+
16
16
  resources.each do |resource|
17
17
  resource = resource.to_sym
18
18
  resource_class_name ||= (options[:class_name].to_s.presence || resource.to_s).classify
19
19
  resource_class = resource_class_name.constantize
20
- association_name = self.to_s.downcase.pluralize.to_sym
21
-
20
+
22
21
  # validates and belongs_to
23
22
  validates resource, presence: true
24
23
  belongs_to resource, options
@@ -38,15 +37,31 @@ module Tenancy
38
37
  end
39
38
  end
40
39
 
40
+ # inspired by: https://github.com/goncalossilva/acts_as_paranoid/blob/rails3.2/lib/acts_as_paranoid/core.rb#L76
41
+ def without_scope(*resources)
42
+ scope = where(nil).with_default_scope
43
+ resources.each do |resource|
44
+ resource = resource.to_sym
45
+ reflection = reflect_on_association(resource)
46
+ next if reflection.nil?
47
+
48
+ resource_scope_sql = where(nil).table[reflection.foreign_key].eq(reflection.klass.current_id).to_sql
49
+
50
+ scope.where_values.delete_if { |query| query.to_sql == resource_scope_sql }
51
+ end
52
+
53
+ scope
54
+ end
55
+
41
56
  def validates_uniqueness_in_scope(fields, args={})
42
57
  if args[:scope]
43
58
  args[:scope] = Array.wrap(args[:scope]) << scope_fields
44
59
  else
45
60
  args[:scope] = scope_fields
46
61
  end
47
-
62
+
48
63
  validates_uniqueness_of(fields, args)
49
64
  end
50
65
  end
51
66
  end
52
- end
67
+ end
@@ -1,3 +1,3 @@
1
1
  module Tenancy
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/tenancy.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "tenancy/version"
2
2
  require "active_support/concern"
3
+ require "request_store"
3
4
 
4
5
  module Tenancy
5
6
  autoload :Resource, 'tenancy/resource'
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Tenancy::ResourceScope" do
4
- let(:camyp) { Portal.create(domain_name: 'yp.com.kh') }
5
- let(:panpages) { Portal.create(domain_name: 'panpages.com') }
6
- let(:listing) { Listing.create(name: 'Listing 1', portal_id: camyp.id) }
4
+ let(:camyp) { Portal.create(domain_name: 'yp.com.kh') }
5
+ let(:panpages) { Portal.create(domain_name: 'panpages.com') }
6
+ let(:listing) { Listing.create(name: 'Listing 1', portal_id: camyp.id) }
7
7
 
8
8
  after(:all) do
9
9
  Portal.delete_all
@@ -11,31 +11,31 @@ describe "Tenancy::ResourceScope" do
11
11
 
12
12
  describe Listing do
13
13
  it { should belong_to(:portal) }
14
-
14
+
15
15
  it { should validate_presence_of(:portal) }
16
16
 
17
17
  it { should validate_uniqueness_of(:name).scoped_to(:portal_id).case_insensitive }
18
-
18
+
19
19
  it "have default_scope with :portal_id field" do
20
20
  Portal.current = camyp
21
21
 
22
- Listing.scoped.to_sql.should == Listing.where(portal_id: Portal.current_id).to_sql
22
+ expect(Listing.where(nil).to_sql).to eq(Listing.where(portal_id: Portal.current_id).to_sql)
23
23
  end
24
24
 
25
25
  it "doesn't have default_scope when it doesn't have current portal" do
26
26
  Portal.current = nil
27
27
 
28
- Listing.scoped.to_sql.should == "SELECT \"listings\".* FROM \"listings\" "
28
+ expect(Listing.where(nil).to_sql).not_to include(%{"listings"."portal_id" = #{Portal.current_id}})
29
29
  end
30
30
  end
31
31
 
32
32
  describe Communication do
33
33
  it { should belong_to(:portal) }
34
-
34
+
35
35
  it { should validate_presence_of(:portal) }
36
36
 
37
37
  it { should belong_to(:listing) }
38
-
38
+
39
39
  it { should validate_presence_of(:listing) }
40
40
 
41
41
  it { should validate_uniqueness_of(:value).scoped_to(:portal_id, :listing_id) }
@@ -44,14 +44,15 @@ describe "Tenancy::ResourceScope" do
44
44
  Portal.current = camyp
45
45
  Listing.current = listing
46
46
 
47
- Communication.scoped.to_sql.should == Communication.where(portal_id: Portal.current_id, listing_id: Listing.current_id).to_sql
47
+ Communication.where(nil).to_sql.should == Communication.where(portal_id: Portal.current_id, listing_id: Listing.current_id).to_sql
48
48
  end
49
49
 
50
50
  it "doesn't have default_scope when it doesn't have current portal and listing" do
51
51
  Portal.current = nil
52
52
  Listing.current = nil
53
53
 
54
- Communication.scoped.to_sql.should == "SELECT \"communications\".* FROM \"communications\" "
54
+ expect(Communication.where(nil).to_sql).not_to include(%{"communications"."portal_id" = #{Portal.current_id}})
55
+ expect(Communication.where(nil).to_sql).not_to include(%{"communications"."listing_id" = #{Listing.current_id}})
55
56
  end
56
57
  end
57
58
 
@@ -69,10 +70,10 @@ describe "Tenancy::ResourceScope" do
69
70
 
70
71
  Portal.current = camyp
71
72
  Listing.current = listing2
72
-
73
+
73
74
  extra_communication = ExtraCommunication.new
74
- extra_communication.listing_id.should == listing2.id
75
- extra_communication.portal_id.should == camyp.id
75
+ expect(extra_communication.listing_id).to eq(listing2.id)
76
+ expect(extra_communication.portal_id).to eq(camyp.id)
76
77
  end
77
78
  end
78
79
 
@@ -82,26 +83,43 @@ describe "Tenancy::ResourceScope" do
82
83
 
83
84
  it "reload belongs_to when passes true" do
84
85
  listing.portal.domain_name = 'abc.com'
85
- listing.portal(true).object_id.should_not == Portal.current.object_id
86
+ expect(listing.portal(true).object_id).not_to eq(Portal.current.object_id)
86
87
  end
87
88
 
88
89
  it "doesn't reload belongs_to" do
89
90
  listing.portal.domain_name = 'abc.com'
90
- listing.portal.object_id.should == Portal.current.object_id
91
+ expect(listing.portal.object_id).to eq(Portal.current.object_id)
91
92
  end
92
93
 
93
94
  it "returns different object" do
94
95
  listing.portal_id = panpages.id
95
- listing.portal.object_id.should_not == Portal.current.object_id
96
+ expect(listing.portal.object_id).not_to eq(Portal.current.object_id)
96
97
  end
97
98
 
98
99
  it "doesn't touch db" do
99
100
  current_listing = listing
100
101
 
101
102
  Portal.establish_connection(adapter: "sqlite3", database: "spec/invalid.sqlite3")
102
- current_listing.portal.object_id.should == Portal.current.object_id
103
+ expect(current_listing.portal.object_id).to eq(Portal.current.object_id)
103
104
 
104
105
  Portal.establish_connection(ActiveRecord::Base.connection_config)
105
106
  end
106
107
  end
108
+
109
+ describe "#without_scope" do
110
+ before(:each) { Portal.current = camyp }
111
+ after(:each) { Portal.current = nil and Listing.current = nil }
112
+
113
+ it "unscopes :current_portal" do
114
+ expect(Listing.without_scope(:portal).to_sql).not_to include(%{"listings"."portal_id" = #{Portal.current_id}})
115
+ end
116
+
117
+ it "unscopes :current_portal and :current_listing" do
118
+ Listing.current = listing
119
+
120
+ expect(Communication.without_scope(:portal).to_sql).not_to include(%{"communications"."portal_id" = #{Portal.current_id}})
121
+ expect(Communication.without_scope(:listing).to_sql).not_to include(%{"communications"."listing_id" = #{Listing.current_id}})
122
+ expect(Communication.without_scope(:portal, :listing).to_sql).to eq(%{SELECT "communications".* FROM "communications" WHERE "communications"."is_active" = 't'})
123
+ end
124
+ end
107
125
  end
@@ -11,20 +11,20 @@ describe "Tenancy::Resource" do
11
11
  Portal.delete_all
12
12
  end
13
13
 
14
- before(:each) { Thread.current['Portal.current'] = nil }
14
+ before(:each) { RequestStore.store[:'Portal.current'] = nil }
15
15
 
16
16
  it "set current with instance" do
17
17
  Portal.current = @camyp
18
18
 
19
19
  Portal.current.should == @camyp
20
- Thread.current['Portal.current'].should == @camyp
20
+ RequestStore.store[:'Portal.current'].should == @camyp
21
21
  end
22
22
 
23
23
  it "set current with id" do
24
24
  Portal.current = @panpage.id
25
25
 
26
26
  Portal.current.should == @panpage
27
- Thread.current['Portal.current'].should == @panpage
27
+ RequestStore.store[:'Portal.current'].should == @panpage
28
28
  end
29
29
 
30
30
  it "set current with nil" do
@@ -32,7 +32,7 @@ describe "Tenancy::Resource" do
32
32
  Portal.current = nil
33
33
 
34
34
  Portal.current.should == nil
35
- Thread.current['Portal.current'].should == nil
35
+ RequestStore.store[:'Portal.current'].should == nil
36
36
  end
37
37
 
38
38
  it "#current_id" do
@@ -1,6 +1,14 @@
1
1
  require 'spec_helper'
2
2
  require 'tenancy/matchers'
3
3
 
4
+ describe Portal do
5
+ it { should be_a_tenant }
6
+ end
7
+
8
+ describe Listing do
9
+ it { should be_a_tenant }
10
+ end
11
+
4
12
  describe ExtraCommunication do
5
13
  let(:camyp) { Portal.create(domain_name: 'yp.com.kh') }
6
14
  before { Portal.current = camyp }
@@ -9,4 +17,4 @@ describe ExtraCommunication do
9
17
  it { should have_scope_to(:portal).class_name('Portal') }
10
18
  it { should have_scope_to(:listing) }
11
19
  it { should have_scope_to(:listing).class_name('Listing') }
12
- end
20
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require "codeclimate-test-reporter"
2
+ CodeClimate::TestReporter.start
3
+
1
4
  require 'tenancy'
2
5
 
3
6
  # active_record
@@ -6,6 +6,7 @@ class Listing < ActiveRecord::Base
6
6
  include Tenancy::Resource
7
7
  include Tenancy::ResourceScope
8
8
 
9
+ default_scope -> { where(is_active: true) }
9
10
  scope_to :portal
10
11
  validates_uniqueness_in_scope :name, case_sensitive: false
11
12
  end
@@ -13,6 +14,7 @@ end
13
14
  class Communication < ActiveRecord::Base
14
15
  include Tenancy::ResourceScope
15
16
 
17
+ default_scope -> { where(is_active: true) }
16
18
  scope_to :portal, :listing
17
19
  validates_uniqueness_in_scope :value
18
20
  end
@@ -22,4 +24,4 @@ class ExtraCommunication < ActiveRecord::Base
22
24
 
23
25
  scope_to :portal, class_name: 'Portal'
24
26
  scope_to :listing, class_name: 'Listing'
25
- end
27
+ end
@@ -15,14 +15,16 @@ ActiveRecord::Schema.define do
15
15
  create_table :listings, :force => true do |t|
16
16
  t.string :name
17
17
  t.references :portal
18
+ t.boolean :is_active
18
19
  t.timestamps
19
20
  end
20
-
21
+
21
22
  create_table :communications, :force => true do |t|
22
23
  t.string :label
23
24
  t.string :value
24
25
  t.references :listing
25
26
  t.references :portal
27
+ t.boolean :is_active
26
28
  t.timestamps
27
29
  end
28
30
 
@@ -33,4 +35,4 @@ ActiveRecord::Schema.define do
33
35
  t.references :portal
34
36
  t.timestamps
35
37
  end
36
- end
38
+ end
data/tenancy.gemspec CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Tenancy::VERSION
9
9
  spec.authors = ["chamnap"]
10
10
  spec.email = ["chamnapchhorn@gmail.com"]
11
- spec.description = %q{A simple multi-tenancy with activerecord through scoping}
12
- spec.summary = %q{A simple multi-tenancy with activerecord through scoping}
13
- spec.homepage = ""
11
+ spec.description = %q{A simple multitenancy with activerecord through scoping}
12
+ spec.summary = %q{A simple multitenancy with activerecord through scoping}
13
+ spec.homepage = "https://github.com/yoolk/tenancy"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
@@ -24,5 +24,6 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "sqlite3", "~> 1.3.7"
25
25
  spec.add_development_dependency "rake"
26
26
 
27
- spec.add_dependency "activerecord", "~> 3.2.13"
28
- end
27
+ spec.add_dependency "activerecord", ">= 3.2.13"
28
+ spec.add_dependency "request_store", "~> 1.0.5"
29
+ end
metadata CHANGED
@@ -1,100 +1,114 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tenancy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - chamnap
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-02 00:00:00.000000000 Z
11
+ date: 2013-11-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
+ name: rspec
14
15
  requirement: !ruby/object:Gem::Requirement
15
16
  requirements:
16
17
  - - ~>
17
18
  - !ruby/object:Gem::Version
18
19
  version: 2.12.0
20
+ type: :development
21
+ prerelease: false
19
22
  version_requirements: !ruby/object:Gem::Requirement
20
23
  requirements:
21
24
  - - ~>
22
25
  - !ruby/object:Gem::Version
23
26
  version: 2.12.0
24
- type: :development
25
- prerelease: false
26
- name: rspec
27
27
  - !ruby/object:Gem::Dependency
28
+ name: shoulda
28
29
  requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
31
  - - ~>
31
32
  - !ruby/object:Gem::Version
32
33
  version: 3.5.0
34
+ type: :development
35
+ prerelease: false
33
36
  version_requirements: !ruby/object:Gem::Requirement
34
37
  requirements:
35
38
  - - ~>
36
39
  - !ruby/object:Gem::Version
37
40
  version: 3.5.0
38
- type: :development
39
- prerelease: false
40
- name: shoulda
41
41
  - !ruby/object:Gem::Dependency
42
+ name: pry
42
43
  requirement: !ruby/object:Gem::Requirement
43
44
  requirements:
44
45
  - - ~>
45
46
  - !ruby/object:Gem::Version
46
47
  version: 0.9.12
48
+ type: :development
49
+ prerelease: false
47
50
  version_requirements: !ruby/object:Gem::Requirement
48
51
  requirements:
49
52
  - - ~>
50
53
  - !ruby/object:Gem::Version
51
54
  version: 0.9.12
52
- type: :development
53
- prerelease: false
54
- name: pry
55
55
  - !ruby/object:Gem::Dependency
56
+ name: sqlite3
56
57
  requirement: !ruby/object:Gem::Requirement
57
58
  requirements:
58
59
  - - ~>
59
60
  - !ruby/object:Gem::Version
60
61
  version: 1.3.7
62
+ type: :development
63
+ prerelease: false
61
64
  version_requirements: !ruby/object:Gem::Requirement
62
65
  requirements:
63
66
  - - ~>
64
67
  - !ruby/object:Gem::Version
65
68
  version: 1.3.7
66
- type: :development
67
- prerelease: false
68
- name: sqlite3
69
69
  - !ruby/object:Gem::Dependency
70
+ name: rake
70
71
  requirement: !ruby/object:Gem::Requirement
71
72
  requirements:
72
- - - ! '>='
73
+ - - '>='
73
74
  - !ruby/object:Gem::Version
74
75
  version: '0'
76
+ type: :development
77
+ prerelease: false
75
78
  version_requirements: !ruby/object:Gem::Requirement
76
79
  requirements:
77
- - - ! '>='
80
+ - - '>='
78
81
  - !ruby/object:Gem::Version
79
82
  version: '0'
80
- type: :development
81
- prerelease: false
82
- name: rake
83
83
  - !ruby/object:Gem::Dependency
84
+ name: activerecord
84
85
  requirement: !ruby/object:Gem::Requirement
85
86
  requirements:
86
- - - ~>
87
+ - - '>='
87
88
  - !ruby/object:Gem::Version
88
89
  version: 3.2.13
90
+ type: :runtime
91
+ prerelease: false
89
92
  version_requirements: !ruby/object:Gem::Requirement
90
93
  requirements:
91
- - - ~>
94
+ - - '>='
92
95
  - !ruby/object:Gem::Version
93
96
  version: 3.2.13
97
+ - !ruby/object:Gem::Dependency
98
+ name: request_store
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 1.0.5
94
104
  type: :runtime
95
105
  prerelease: false
96
- name: activerecord
97
- description: A simple multi-tenancy with activerecord through scoping
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 1.0.5
111
+ description: A simple multitenancy with activerecord through scoping
98
112
  email:
99
113
  - chamnapchhorn@gmail.com
100
114
  executables: []
@@ -104,10 +118,13 @@ files:
104
118
  - .gitignore
105
119
  - .rspec
106
120
  - .rvmrc
121
+ - .travis.yml
107
122
  - Gemfile
108
123
  - LICENSE.txt
109
124
  - README.md
110
125
  - Rakefile
126
+ - gemfiles/active_record_32.gemfile
127
+ - gemfiles/active_record_40.gemfile
111
128
  - lib/tenancy.rb
112
129
  - lib/tenancy/matchers.rb
113
130
  - lib/tenancy/resource.rb
@@ -120,7 +137,7 @@ files:
120
137
  - spec/support/models.rb
121
138
  - spec/support/schema.rb
122
139
  - tenancy.gemspec
123
- homepage: ''
140
+ homepage: https://github.com/yoolk/tenancy
124
141
  licenses:
125
142
  - MIT
126
143
  metadata: {}
@@ -130,20 +147,20 @@ require_paths:
130
147
  - lib
131
148
  required_ruby_version: !ruby/object:Gem::Requirement
132
149
  requirements:
133
- - - ! '>='
150
+ - - '>='
134
151
  - !ruby/object:Gem::Version
135
152
  version: '0'
136
153
  required_rubygems_version: !ruby/object:Gem::Requirement
137
154
  requirements:
138
- - - ! '>='
155
+ - - '>='
139
156
  - !ruby/object:Gem::Version
140
157
  version: '0'
141
158
  requirements: []
142
159
  rubyforge_project:
143
- rubygems_version: 2.0.7
160
+ rubygems_version: 2.1.10
144
161
  signing_key:
145
162
  specification_version: 4
146
- summary: A simple multi-tenancy with activerecord through scoping
163
+ summary: A simple multitenancy with activerecord through scoping
147
164
  test_files:
148
165
  - spec/lib/resource_scope_spec.rb
149
166
  - spec/lib/resource_spec.rb