monarchy 2.2.2 → 2.3.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 +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