company_scope 0.1.2 → 0.1.3
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 +4 -4
- data/README.md +45 -6
- data/company_scope.gemspec +1 -0
- data/lib/company_scope/guardian.rb +3 -0
- data/lib/company_scope/version.rb +1 -1
- data/lib/company_scope.rb +1 -0
- data/lib/rack/multi_company.rb +44 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e23f0f1665e578c9287a203ebff02717f204dfe4
|
4
|
+
data.tar.gz: 83ba3007224cc8c97f5003263efc18e97ee7e111
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0835d33a937cb22c23d5fa021f644470050ffbd4f160e0096f28a018cb902ace3bb83b44cd55b5c615194d7302949a7d5760999f8fe4a8771fea1f0514035f5
|
7
|
+
data.tar.gz: d73b5642d099a30aec593f7b4c124b766312237b20c2cb4838fbea1d84bb6216fed20305d1e0d1f46ce706a11003ef7ec06aab0ed56997382bda1e562bbf7f28
|
data/README.md
CHANGED
@@ -41,15 +41,54 @@ There are three main steps in adding multi-tenancy/company to your app with comp
|
|
41
41
|
### Decide on a process of determining the company/account ###
|
42
42
|
|
43
43
|
In the current version a helper_method called "current_company" is added to the Controller,
|
44
|
-
where you add the method "company_setup". You have therefore two choices. Either you use
|
45
|
-
own process to set the instance
|
44
|
+
where you add the method "company_setup". You have therefore two choices. Either you use the
|
45
|
+
company_scope gem process included Rack Middleware or your own process to set the instance
|
46
|
+
of "Company" into "request.env".
|
47
|
+
|
48
|
+
The included Rack Middleware can be inserted into the Rails Application stack in the config
|
49
|
+
section of 'application.rb'.
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
module YourRailsApp
|
53
|
+
class Application < Rails::Application
|
54
|
+
...
|
55
|
+
# - add some Rack middleware to detect the company_name from the subdomain
|
56
|
+
config.middleware.insert_after Rack::Sendfile, Rack::MultiCompany, :company
|
57
|
+
...
|
58
|
+
end
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
The parameter in the example above needs to be a symbol of the model of your application
|
63
|
+
that will act as the account i.e. company, tenant etc.
|
64
|
+
|
65
|
+
The domain 'lvh.me' points to 127.0.0.1 and is therefore an ideal candidate for using with local development and subdomains since they will also all point to your localhost.
|
66
|
+
|
67
|
+
[See here for info](http://stackoverflow.com/questions/12983072/rails-3-subdomain-testing-using-lvh-me)
|
68
|
+
|
69
|
+
NB: The middleware currently uses a regex to ensure the domain name can only obtain the following:
|
70
|
+
|
71
|
+
* A-Z
|
72
|
+
* a-z
|
73
|
+
* 0-9
|
74
|
+
|
75
|
+
The middleware then uses the column called "class_name"_name i.e. "company_name"
|
76
|
+
|
77
|
+
No spaces or special characters are permitted and the name is also upcased - which needs to be handled
|
78
|
+
by the model you use for scoping! This just keeps the name clean and simple.
|
79
|
+
We would strongly recommend you to have a proper index on the company
|
80
|
+
|
81
|
+
The method below is included in the Controller stack (see notes further down), and retrieves
|
82
|
+
the company object the request object. The Rack Middleware "Rack::MultiCompany" injects this
|
83
|
+
object into each request!
|
46
84
|
|
47
85
|
```ruby
|
48
86
|
def current_company
|
49
87
|
request.env["COMPANY_ID"]
|
50
88
|
end
|
51
89
|
```
|
52
|
-
|
90
|
+
|
91
|
+
An example of how the gem does this using "Rack Middleware" - is in the excerpt below:
|
53
92
|
|
54
93
|
```ruby
|
55
94
|
def call(env)
|
@@ -61,9 +100,6 @@ def call(env)
|
|
61
100
|
end
|
62
101
|
```
|
63
102
|
|
64
|
-
The next version of "company_scope", will have the Rack::Middleware call integrated and the
|
65
|
-
ability to opt out of using it.
|
66
|
-
|
67
103
|
Alternatively you can use your own process for determining the "current_company" and override this
|
68
104
|
method in your application controller, providing you declare this after the "company_setup" method,
|
69
105
|
which is detailed in the next step.
|
@@ -119,6 +155,9 @@ class Company < ActiveRecord::Base
|
|
119
155
|
end
|
120
156
|
```
|
121
157
|
|
158
|
+
The gem also injects
|
159
|
+
|
160
|
+
|
122
161
|
* Each class to be scoped needs to have the "acts_as_company :account" method. The parameter ":account"
|
123
162
|
defaults to :company if left blank. This can be any class/name of your choosing - the parameter needs
|
124
163
|
to be a underscored version of the Class name as a symbol.
|
data/company_scope.gemspec
CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_development_dependency "rake", "~> 10.0"
|
30
30
|
#
|
31
31
|
# - gem related ones
|
32
|
+
spec.add_development_dependency 'rack'
|
32
33
|
spec.add_development_dependency 'rspec'
|
33
34
|
spec.add_development_dependency 'rspec-given'
|
34
35
|
spec.add_development_dependency 'rspec-collection_matchers'
|
@@ -10,6 +10,9 @@ module CompanyScope
|
|
10
10
|
module GuardianClassMethods
|
11
11
|
#
|
12
12
|
def acts_as_guardian
|
13
|
+
#
|
14
|
+
#puts "\n\n\n Class Name: #{self.class.to_s.downcase}\n\n\n"
|
15
|
+
#validates_uniqueness_of "#{self.class.to_s.downcase}_name".to_sym #:company_name
|
13
16
|
#
|
14
17
|
def current_id=(id)
|
15
18
|
RequestStore.store[:default_scope_company_id] = id
|
data/lib/company_scope.rb
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
#
|
2
|
+
module Rack
|
3
|
+
#
|
4
|
+
class MultiCompany
|
5
|
+
#
|
6
|
+
attr_reader :company_class_name
|
7
|
+
#
|
8
|
+
def initialize(app, company_class)
|
9
|
+
@app = app
|
10
|
+
@company_class_name = company_class.to_s.split('_').collect!{ |w| w.capitalize }.join
|
11
|
+
@company = Module.const_get(@company_class_name).find_by_company_name('DEFAULT') if db_configured
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
request = Rack::Request.new(env)
|
16
|
+
first_sub_domain = request.host.split('.').first
|
17
|
+
# disallow any non alphabetic chars!
|
18
|
+
domain = first_sub_domain.upcase if first_sub_domain.match(/\A[a-zA-Z0-9]*\z/)
|
19
|
+
# insert the company into ENV - for the controller helper_method 'current_company'
|
20
|
+
env["COMPANY_ID"] = retrieve_company_from_subdomain(domain)
|
21
|
+
response = @app.call(env)
|
22
|
+
response
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def db_configured
|
28
|
+
ActiveRecord::Base.connection.table_exists? Module.const_get(@company_class_name).table_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def retrieve_company_from_subdomain(domain)
|
32
|
+
# - During test runs we load a company called 'DEFAULT' - it does not need to exist during initialisation
|
33
|
+
@company = Module.const_get(@company_class_name).find_by_company_name('DEFAULT') if Rails.env == 'test'
|
34
|
+
|
35
|
+
# - only ever load the company when the subdomain changes - also works when company is nil from an unsuccessful attempt..
|
36
|
+
@company = Module.const_get(@company_class_name).find_by_company_name(domain) unless ( domain == @company.to_s )
|
37
|
+
|
38
|
+
@company
|
39
|
+
rescue ActiveRecord::RecordNotFound => e
|
40
|
+
puts "\n\n Rack Error - Company not found: #{e.to_s}\n\n"
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: company_scope
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Forkin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rack
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rspec
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -176,6 +190,7 @@ files:
|
|
176
190
|
- lib/company_scope/guardian.rb
|
177
191
|
- lib/company_scope/railtie.rb
|
178
192
|
- lib/company_scope/version.rb
|
193
|
+
- lib/rack/multi_company.rb
|
179
194
|
homepage: http://github.com/netflakes/company_scope
|
180
195
|
licenses: []
|
181
196
|
metadata: {}
|