monarchy 2.2.2 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github_changelog_generator +1 -1
- data/CHANGELOG.md +13 -2
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -1
- data/docs/acts_as_hierarchy.md +45 -0
- data/dummy/db/migrate/20160220215254_monarchy_create_users.rb +0 -1
- data/lib/monarchy/acts_as_hierarchy.rb +59 -11
- data/lib/monarchy/acts_as_resource.rb +21 -10
- data/lib/monarchy/acts_as_user.rb +5 -22
- data/lib/monarchy/exceptions.rb +0 -22
- data/lib/monarchy/validators.rb +0 -10
- data/lib/monarchy/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37446023d193a35f3d1989848c858d173810af90
|
4
|
+
data.tar.gz: 4db1f53bf50bb8f75995d10d6e4da232f042b1d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f1f23cb2bde8c85ef10b201e8ae337b70abacdf927cedf9586b8c46a839ca41118d106c925c7ebe163e7ad3ead9e4b0f8e389d6e536d3e34935d3442cacc95f
|
7
|
+
data.tar.gz: 7dcbd125eda5e4bc2c6c1afbd94d8382c70f89b54ee176fefad54e893fc84a1e0d6706f9fd802af11ac098ca2b3cd1d25d584ae09319cde4ca08093ce8207b2c
|
data/.github_changelog_generator
CHANGED
@@ -1 +1 @@
|
|
1
|
-
future-release=2.
|
1
|
+
future-release=2.3.0
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,18 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [2.
|
4
|
-
[Full Changelog](https://github.com/Exelord/Monarchy/compare/v2.2.
|
3
|
+
## [2.3.0](https://github.com/Exelord/Monarchy/tree/2.3.0) (2017-06-14)
|
4
|
+
[Full Changelog](https://github.com/Exelord/Monarchy/compare/v2.2.2...2.3.0)
|
5
|
+
|
6
|
+
**Closed issues:**
|
7
|
+
|
8
|
+
- Remove potential n-query [\#79](https://github.com/Exelord/Monarchy/issues/79)
|
9
|
+
|
10
|
+
**Merged pull requests:**
|
11
|
+
|
12
|
+
- Improve performance and specs [\#76](https://github.com/Exelord/Monarchy/pull/76) ([Exelord](https://github.com/Exelord))
|
13
|
+
|
14
|
+
## [v2.2.2](https://github.com/Exelord/Monarchy/tree/v2.2.2) (2017-06-14)
|
15
|
+
[Full Changelog](https://github.com/Exelord/Monarchy/compare/v2.2.1...v2.2.2)
|
5
16
|
|
6
17
|
**Fixed bugs:**
|
7
18
|
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
monarchy (2.
|
4
|
+
monarchy (2.3.0)
|
5
5
|
active_record_union (= 1.2.0)
|
6
6
|
activerecord (>= 4.2.7.1)
|
7
7
|
closure_tree (= 6.5.0)
|
@@ -62,6 +62,7 @@ GEM
|
|
62
62
|
concurrent-ruby (1.0.5)
|
63
63
|
configurations (2.2.2)
|
64
64
|
database_cleaner (1.5.3)
|
65
|
+
db-query-matchers (0.8.0)
|
65
66
|
diff-lcs (1.3)
|
66
67
|
docile (1.1.5)
|
67
68
|
erubis (2.7.0)
|
@@ -190,6 +191,7 @@ DEPENDENCIES
|
|
190
191
|
bundler (~> 1.12)
|
191
192
|
codeclimate-test-reporter (~> 1.0.8)
|
192
193
|
database_cleaner (= 1.5.3)
|
194
|
+
db-query-matchers (= 0.8.0)
|
193
195
|
factory_girl_rails (= 4.8.0)
|
194
196
|
ffaker (= 2.5.0)
|
195
197
|
monarchy!
|
data/docs/acts_as_hierarchy.md
CHANGED
@@ -18,6 +18,51 @@ We are using [Closure Tree][e5c808aa] behind `Hierarchy` class. There is a bunch
|
|
18
18
|
|
19
19
|
[e5c808aa]: https://github.com/mceachen/closure_tree "Closure Tree"
|
20
20
|
|
21
|
+
#### .hierarchies_for
|
22
|
+
You can use this method if you want to get all hierarchies for specific resources, eg:
|
23
|
+
|
24
|
+
```
|
25
|
+
Monarchy.hierarchy_class.hierarchies_for(Project.all) # returns hierarchies
|
26
|
+
```
|
27
|
+
|
28
|
+
** Remember: `hierarchies_for` can receive only `ActiveRecord` class argument! **
|
29
|
+
|
30
|
+
#### .children_for
|
31
|
+
You can use this method if you want to get all explicit children for specific hierarchies, eg:
|
32
|
+
|
33
|
+
```
|
34
|
+
Monarchy.hierarchy_class.children_for(my_hierarchy) # returns children hierarchies
|
35
|
+
```
|
36
|
+
|
37
|
+
** Remember: `children_for` can receive only `ActiveRecord` class argument! **
|
38
|
+
|
39
|
+
#### .parents_for
|
40
|
+
You can use this method if you want to get all explicit parents for specific hierarchies, eg:
|
41
|
+
|
42
|
+
```
|
43
|
+
Monarchy.hierarchy_class.parents_for(my_hierarchy) # returns parents hierarchies
|
44
|
+
```
|
45
|
+
|
46
|
+
** Remember: `parents_for` can receive only `ActiveRecord` class argument! **
|
47
|
+
|
48
|
+
#### .descendants_for
|
49
|
+
You can use this method if you want to get all descendants for specific hierarchies, eg:
|
50
|
+
|
51
|
+
```
|
52
|
+
Monarchy.hierarchy_class.descendants_for(my_hierarchy) # returns descendants hierarchies
|
53
|
+
```
|
54
|
+
|
55
|
+
** Remember: `descendants_for` can receive only `ActiveRecord` class argument! **
|
56
|
+
|
57
|
+
#### .ancestors_for
|
58
|
+
You can use this method if you want to get all ancestors for specific hierarchies, eg:
|
59
|
+
|
60
|
+
```
|
61
|
+
Monarchy.hierarchy_class.ancestors_for(my_hierarchies) # returns ancestors hierarchies
|
62
|
+
```
|
63
|
+
|
64
|
+
** Remember: `ancestors_for` can receive only `ActiveRecord` class argument! **
|
65
|
+
|
21
66
|
## Scopes:
|
22
67
|
|
23
68
|
### .accessible_for
|
@@ -10,15 +10,11 @@ module Monarchy
|
|
10
10
|
self.table_name = 'monarchy_hierarchies'
|
11
11
|
has_closure_tree dependent: :destroy
|
12
12
|
|
13
|
-
|
14
|
-
has_many :users, through: :members, class_name: "::#{Monarchy.user_class}"
|
15
|
-
belongs_to :resource, polymorphic: true
|
16
|
-
|
13
|
+
include_relations
|
17
14
|
include_scopes
|
15
|
+
include_validators
|
18
16
|
|
19
|
-
|
20
|
-
validates :resource_id, uniqueness: { scope: [:resource_type] }, presence: true
|
21
|
-
|
17
|
+
extend Monarchy::ActsAsHierarchy::ClassMethods
|
22
18
|
include Monarchy::ActsAsHierarchy::InstanceMethods
|
23
19
|
end
|
24
20
|
end
|
@@ -29,23 +25,75 @@ module Monarchy
|
|
29
25
|
end
|
30
26
|
end
|
31
27
|
|
28
|
+
module ClassMethods
|
29
|
+
def hierarchies_for(resources)
|
30
|
+
check_argument_type(resources)
|
31
|
+
resources ? unscoped.where(resource: resources) : none
|
32
|
+
end
|
33
|
+
|
34
|
+
def children_for(hierarchies)
|
35
|
+
check_argument_type(hierarchies)
|
36
|
+
hierarchies ? unscoped.where(parent: hierarchies) : none
|
37
|
+
end
|
38
|
+
|
39
|
+
def parents_for(hierarchies)
|
40
|
+
check_argument_type(hierarchies)
|
41
|
+
return none unless hierarchies
|
42
|
+
|
43
|
+
unscoped.joins('INNER JOIN monarchy_hierarchies AS hierarchies_children ON '\
|
44
|
+
'monarchy_hierarchies.id = hierarchies_children.parent_id')
|
45
|
+
.where(hierarchies_children: { id: hierarchies })
|
46
|
+
end
|
47
|
+
|
48
|
+
def descendants_for(hierarchies)
|
49
|
+
check_argument_type(hierarchies)
|
50
|
+
hierarchies ? unscoped.with_ancestor(hierarchies) : none
|
51
|
+
end
|
52
|
+
|
53
|
+
def ancestors_for(hierarchies)
|
54
|
+
check_argument_type(hierarchies)
|
55
|
+
return none unless hierarchies
|
56
|
+
|
57
|
+
unscoped.joins('INNER JOIN monarchy_hierarchy_hierarchies ON '\
|
58
|
+
'monarchy_hierarchies.id = monarchy_hierarchy_hierarchies.ancestor_id')
|
59
|
+
.where(monarchy_hierarchy_hierarchies: { descendant_id: hierarchies.select(:id) })
|
60
|
+
.where('monarchy_hierarchy_hierarchies.generations > 0')
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def check_argument_type(argument)
|
66
|
+
condition = argument.nil? || argument.is_a?(ActiveRecord::Base) || argument.is_a?(ActiveRecord::Relation)
|
67
|
+
raise(ArgumentError, 'Argument has to be ActiveRecord!') unless condition
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
32
71
|
module SupportMethods
|
33
72
|
private
|
34
73
|
|
74
|
+
def include_relations
|
75
|
+
belongs_to :resource, polymorphic: true
|
76
|
+
has_many :members, class_name: "::#{Monarchy.member_class}", dependent: :destroy
|
77
|
+
has_many :users, through: :members, class_name: "::#{Monarchy.user_class}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def include_validators
|
81
|
+
validates :resource_type, presence: true
|
82
|
+
validates :resource_id, uniqueness: { scope: [:resource_type] }, presence: true
|
83
|
+
end
|
84
|
+
|
35
85
|
# rubocop:disable all
|
36
86
|
def include_scopes
|
37
87
|
scope :in, (lambda do |hierarchy, descendants = true|
|
38
|
-
|
39
|
-
where(id: descendants ? hierarchy.descendants : hierarchy.children)
|
88
|
+
where(id: descendants ? descendants_for(hierarchy) : children_for(hierarchy))
|
40
89
|
end)
|
41
90
|
|
42
91
|
scope :accessible_for, (lambda do |user, options = {}|
|
43
|
-
Monarchy::Validators.user(user)
|
44
92
|
user_id = user.id
|
45
93
|
|
46
94
|
custom_options = accessible_for_options(options)
|
47
95
|
where(id: accessible_roots_ids(user_id, custom_options[:parent_access])
|
48
|
-
|
96
|
+
.union_all(accessible_leaves_ids(user_id, custom_options[:inherited_roles])))
|
49
97
|
end)
|
50
98
|
end
|
51
99
|
# rubocop:enable all
|
@@ -45,18 +45,22 @@ module Monarchy
|
|
45
45
|
@parentize_name = name
|
46
46
|
end
|
47
47
|
|
48
|
+
# rubocop:disable all
|
48
49
|
def include_scopes
|
49
50
|
scope :in, (lambda do |resource, descendants = true|
|
50
51
|
Monarchy::Validators.resource(resource)
|
51
|
-
|
52
|
+
hierarchy = Monarchy.hierarchy_class.hierarchies_for(resource)
|
53
|
+
hierarchies = Monarchy.hierarchy_class.in(hierarchy, descendants)
|
52
54
|
joins(:hierarchy).where(monarchy_hierarchies: { id: hierarchies })
|
53
55
|
end)
|
54
56
|
|
55
57
|
scope :accessible_for, (lambda do |user, options = {}|
|
58
|
+
Monarchy::Validators.user(user)
|
56
59
|
joins(:hierarchy).where(monarchy_hierarchies: { id: Monarchy.hierarchy_class
|
57
60
|
.accessible_for(user, options) })
|
58
61
|
end)
|
59
62
|
end
|
63
|
+
# rubocop:enable all
|
60
64
|
|
61
65
|
def include_relationships
|
62
66
|
has_many :members, through: :hierarchy, class_name: "::#{Monarchy.member_class}"
|
@@ -67,7 +71,7 @@ module Monarchy
|
|
67
71
|
|
68
72
|
module InstanceMethods
|
69
73
|
def parent
|
70
|
-
@parent =
|
74
|
+
@parent = parent_resource || @parent
|
71
75
|
end
|
72
76
|
|
73
77
|
def parent=(resource)
|
@@ -81,7 +85,7 @@ module Monarchy
|
|
81
85
|
end
|
82
86
|
|
83
87
|
def children=(array)
|
84
|
-
hierarchy&.update(children:
|
88
|
+
hierarchy&.update(children: children_hierarchies(array))
|
85
89
|
@children = array
|
86
90
|
end
|
87
91
|
|
@@ -91,12 +95,13 @@ module Monarchy
|
|
91
95
|
self.hierarchy ||= Monarchy.hierarchy_class.create(
|
92
96
|
resource: self,
|
93
97
|
parent: parent.try(:hierarchy),
|
94
|
-
children:
|
98
|
+
children: children_hierarchies(children)
|
95
99
|
)
|
96
100
|
end
|
97
101
|
|
98
|
-
def accessible_for(user)
|
99
|
-
|
102
|
+
def accessible_for(user, options = {})
|
103
|
+
Monarchy::Validators.user(user)
|
104
|
+
hierarchy.accessible_for(user, options)
|
100
105
|
end
|
101
106
|
|
102
107
|
private
|
@@ -117,12 +122,18 @@ module Monarchy
|
|
117
122
|
end
|
118
123
|
|
119
124
|
def children_resources
|
120
|
-
|
121
|
-
|
122
|
-
|
125
|
+
resource_hierarchy = Monarchy.hierarchy_class.hierarchies_for(self)
|
126
|
+
hierarchy_children = Monarchy.hierarchy_class.children_for(resource_hierarchy)
|
127
|
+
hierarchy_children.includes(:resource).map(&:resource)
|
123
128
|
end
|
124
129
|
|
125
|
-
def
|
130
|
+
def parent_resource
|
131
|
+
resource_hierarchy = Monarchy.hierarchy_class.hierarchies_for(self)
|
132
|
+
hierarchy_parent = Monarchy.hierarchy_class.parents_for(resource_hierarchy)
|
133
|
+
hierarchy_parent.first&.resource
|
134
|
+
end
|
135
|
+
|
136
|
+
def children_hierarchies(array)
|
126
137
|
array&.compact!
|
127
138
|
Array(array).map { |resource| Monarchy::Validators.resource(resource).hierarchy }
|
128
139
|
end
|
@@ -88,8 +88,7 @@ module Monarchy
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def resource_roles(resource)
|
91
|
-
resource_hierarchy = hierarchies_for(resource).select(:id)
|
92
|
-
|
91
|
+
resource_hierarchy = Monarchy.hierarchy_class.hierarchies_for(resource).select(:id)
|
93
92
|
user_memberships = Monarchy.member_class
|
94
93
|
.where(hierarchy_id: resource_hierarchy, user_id: id)
|
95
94
|
.select(:id, :hierarchy_id).to_sql
|
@@ -156,34 +155,18 @@ module Monarchy
|
|
156
155
|
@inherited_default_role ||= Monarchy.role_class.find_by(name: Monarchy.configuration.inherited_default_role)
|
157
156
|
end
|
158
157
|
|
159
|
-
# TODO: Make these methods public in related interfaces
|
160
|
-
|
161
158
|
def members_for(hierarchies)
|
162
159
|
Monarchy.member_class.where(hierarchy: hierarchies, user_id: id)
|
163
160
|
end
|
164
161
|
|
165
|
-
def hierarchies_for(resources)
|
166
|
-
Monarchy.hierarchy_class.where(resource: resources)
|
167
|
-
end
|
168
|
-
|
169
162
|
def descendants_for(resources)
|
170
|
-
resources_hierarchies = hierarchies_for(resources).select(:id)
|
171
|
-
|
172
|
-
Monarchy.hierarchy_class
|
173
|
-
.joins('INNER JOIN monarchy_hierarchy_hierarchies ON ' \
|
174
|
-
'monarchy_hierarchies.id = monarchy_hierarchy_hierarchies.descendant_id')
|
175
|
-
.where(monarchy_hierarchy_hierarchies: { ancestor_id: resources_hierarchies })
|
176
|
-
.where.not(monarchy_hierarchies: { id: resources_hierarchies })
|
163
|
+
resources_hierarchies = Monarchy.hierarchy_class.hierarchies_for(resources).select(:id)
|
164
|
+
Monarchy.hierarchy_class.descendants_for(resources_hierarchies)
|
177
165
|
end
|
178
166
|
|
179
167
|
def ancestors_for(resources)
|
180
|
-
resources_hierarchies = hierarchies_for(resources).select(:id)
|
181
|
-
|
182
|
-
Monarchy.hierarchy_class
|
183
|
-
.joins('INNER JOIN monarchy_hierarchy_hierarchies ON ' \
|
184
|
-
'monarchy_hierarchies.id = monarchy_hierarchy_hierarchies.ancestor_id')
|
185
|
-
.where(monarchy_hierarchy_hierarchies: { descendant_id: resources_hierarchies })
|
186
|
-
.where.not(monarchy_hierarchies: { id: resources_hierarchies })
|
168
|
+
resources_hierarchies = Monarchy.hierarchy_class.hierarchies_for(resources).select(:id)
|
169
|
+
Monarchy.hierarchy_class.ancestors_for(resources_hierarchies)
|
187
170
|
end
|
188
171
|
end
|
189
172
|
end
|
data/lib/monarchy/exceptions.rb
CHANGED
@@ -44,16 +44,6 @@ module Monarchy
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
class ModelNotHierarchy < Error
|
48
|
-
def initialize(resource)
|
49
|
-
@resource = resource
|
50
|
-
end
|
51
|
-
|
52
|
-
def message
|
53
|
-
"Model '#{@resource.class}' is not a hierarchy!"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
47
|
class ModelNotMember < Error
|
58
48
|
def initialize(member)
|
59
49
|
@member = member
|
@@ -97,12 +87,6 @@ module Monarchy
|
|
97
87
|
end
|
98
88
|
end
|
99
89
|
|
100
|
-
class HierarchyIsNil < Error
|
101
|
-
def message
|
102
|
-
'Hierarchy can NOT be nil!'
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
90
|
class UserIsNil < Error
|
107
91
|
def message
|
108
92
|
'User can NOT be nil!'
|
@@ -126,11 +110,5 @@ module Monarchy
|
|
126
110
|
'Resource has to persisted!'
|
127
111
|
end
|
128
112
|
end
|
129
|
-
|
130
|
-
class HierarchyNotPersist < Error
|
131
|
-
def message
|
132
|
-
'Resource has to persisted!'
|
133
|
-
end
|
134
|
-
end
|
135
113
|
end
|
136
114
|
end
|
data/lib/monarchy/validators.rb
CHANGED
@@ -39,16 +39,6 @@ module Monarchy
|
|
39
39
|
persistance && resource && !resource.persisted? ? raise(Monarchy::Exceptions::ResourceNotPersist) : model
|
40
40
|
end
|
41
41
|
|
42
|
-
def hierarchy(hierarchy, allow_nil = false, persistance = true)
|
43
|
-
raise Monarchy::Exceptions::HierarchyIsNil if !hierarchy && !allow_nil
|
44
|
-
|
45
|
-
model = check_model_class(hierarchy, 'ModelNotHierarchy') do
|
46
|
-
hierarchy.is_a?(Monarchy.hierarchy_class)
|
47
|
-
end
|
48
|
-
|
49
|
-
persistance && hierarchy && !hierarchy.persisted? ? raise(Monarchy::Exceptions::HierarchyNotPersist) : model
|
50
|
-
end
|
51
|
-
|
52
42
|
def user(user, allow_nil = false)
|
53
43
|
raise Monarchy::Exceptions::UserIsNil if !user && !allow_nil
|
54
44
|
model_is_class(user, Monarchy.user_class, 'ModelNotUser')
|
data/lib/monarchy/version.rb
CHANGED