company_scope 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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: {}
|