patriarch 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +180 -9
- data/lib/generators/patriarch/templates/manager_service-tripartite.rb +10 -1
- data/lib/patriarch/authorization_service.rb +24 -13
- data/lib/patriarch/behaviours.rb +190 -128
- data/lib/patriarch/dao_services/bipartite_relationship_builder_service.rb +15 -1
- data/lib/patriarch/dao_services/redis_mapper_service.rb +56 -27
- data/lib/patriarch/dao_services/retriever_service.rb +27 -15
- data/lib/patriarch/dao_services/tripartite_relationship_builder_service.rb +24 -9
- data/lib/patriarch/manager_service.rb +1 -0
- data/lib/patriarch/service.rb +5 -2
- data/lib/patriarch/tool_services/redis_cleaner_service.rb +50 -37
- data/lib/patriarch/tool_services/redis_extractor_service.rb +35 -5
- data/lib/patriarch/transaction.rb +10 -3
- data/lib/patriarch/transaction_step.rb +13 -2
- data/lib/patriarch/version.rb +1 -1
- data/spec/lib/patriarch/tool_services/redis_cleaner_service_spec.rb +1 -1
- metadata +52 -17
data/README.md
CHANGED
@@ -17,7 +17,9 @@ and keep track of all this in one transaction.
|
|
17
17
|
Patriarch allows you to handle all of this in a matter of seconds and
|
18
18
|
- gathers all of the redis calls in one transaction object that stores a redis queue ready to be processed
|
19
19
|
- rollbacks SQL destroy transaction if redis database dropped while processing the instruction queue to clean data relative
|
20
|
-
to SQL rows destroyed. Reduces possibilities of painful database
|
20
|
+
to SQL rows destroyed. Reduces possibilities of painful database incoherence.
|
21
|
+
|
22
|
+
Note : We use Patriarch in production
|
21
23
|
|
22
24
|
# What Patriarch is not
|
23
25
|
|
@@ -26,8 +28,14 @@ Patriarch is not a replacement for SQL
|
|
26
28
|
## Installation
|
27
29
|
|
28
30
|
Add this line to your application's Gemfile:
|
31
|
+
```ruby
|
32
|
+
gem 'patriarch'
|
33
|
+
```
|
29
34
|
|
30
|
-
|
35
|
+
Or this one if you want to be up-to-date in real time
|
36
|
+
```ruby
|
37
|
+
gem 'patriarch', :git => 'https://github.com/nateware/redis-objects.git'
|
38
|
+
```
|
31
39
|
|
32
40
|
And then execute:
|
33
41
|
|
@@ -40,11 +48,11 @@ Or install it yourself as:
|
|
40
48
|
## Usage
|
41
49
|
|
42
50
|
First include it into your model:
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
51
|
+
```ruby
|
52
|
+
class User < ActiveRecord::Base
|
53
|
+
include Patriarch::Behaviours
|
54
|
+
end
|
55
|
+
```
|
48
56
|
### Initializing files for a behaviour
|
49
57
|
|
50
58
|
Just type in:
|
@@ -55,10 +63,168 @@ Just type in:
|
|
55
63
|
|
56
64
|
Add a behaviour in a simple way and write this just below the include:
|
57
65
|
|
58
|
-
|
59
|
-
|
66
|
+
```ruby
|
67
|
+
add_behaviour :behaviour, :on => [:model1,:model2] # add active_behaviour performed on instances of model1, model2
|
68
|
+
add_behaviour :behaviour, :by => :model3 # add passive_behaviour performed on us by instances of model3
|
69
|
+
```
|
60
70
|
|
61
71
|
It works like belongs_to and has_many helpers of active record, you need to include declarations in both models
|
72
|
+
Let's say we have a Users that we want it to be able to like instances from model Post and Message. You may want to use
|
73
|
+
aliases like did below with as and undo_as options
|
74
|
+
```ruby
|
75
|
+
class User < ActiveRecord::Base
|
76
|
+
include Patriarch::Behaviours
|
77
|
+
add_behaviour :like, :on => [:notification,:post], :as => :love, :undo_as => :hate
|
78
|
+
end
|
79
|
+
|
80
|
+
class Post < ActiveRecord::Base
|
81
|
+
include Patriarch::Behaviours
|
82
|
+
add_behaviour :like, :by => :user
|
83
|
+
end
|
84
|
+
|
85
|
+
class Message < ActiveRecord::Base
|
86
|
+
include Patriarch::Behaviours
|
87
|
+
add_behaviour :like, :by => :user
|
88
|
+
end
|
89
|
+
```
|
90
|
+
This will provide 'behaviour' methods and tool methods whose name are built like this :
|
91
|
+
```ruby
|
92
|
+
"#{actor_model_name.pluralize}_#{behaviour_in_progressive_present_form}_me" # tool method to retrieve models that acted on me
|
93
|
+
"#{target_model_name.pluralize}_i_#{behaviour}" # tool method to retrieve models i acted on
|
94
|
+
```
|
95
|
+
Adding suffix ids will prevent costly model instantiations and requesting the database and only return ids as an array
|
96
|
+
of Fixnum
|
97
|
+
|
98
|
+
And now with the example ...
|
99
|
+
```ruby
|
100
|
+
# Let's grab an user a message and a post, we assume some are already created
|
101
|
+
user = User.first
|
102
|
+
post = Post.first
|
103
|
+
mess = Message.find(10)
|
104
|
+
|
105
|
+
user.like post
|
106
|
+
user.love mess
|
107
|
+
|
108
|
+
user.posts_i_like # => [post]
|
109
|
+
user.messages_i_like # => [mess]
|
110
|
+
user.posts_i_love # => [post]
|
111
|
+
|
112
|
+
user.posts_i_like_ids # => [1]
|
113
|
+
useu.messages_i_like_ids # => [10]
|
114
|
+
useu.messages_i_love_ids # => [10]
|
115
|
+
|
116
|
+
post.users_loving_me # => [user]
|
117
|
+
mess.users_liking_me_ids # => [1]
|
118
|
+
|
119
|
+
user.undo_like mess
|
120
|
+
user.messages_i_like # => []
|
121
|
+
user.messages_i_like_ids # => []
|
122
|
+
|
123
|
+
user.hate post
|
124
|
+
user.posts_i_like # => []
|
125
|
+
user.posts_i_love_ids # => []
|
126
|
+
```
|
127
|
+
### Tripartite relations
|
128
|
+
|
129
|
+
You can also define tripartite behaviours. An example we use is that you can comment a post via a message.
|
130
|
+
Tripartite behaviours implies that a medium is used to perform an action.
|
131
|
+
For our little example that would become :
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
class User < ActiveRecord::Base
|
135
|
+
include Patriarch::Behaviours
|
136
|
+
add_behaviour :comment, :on => :post, :via => :message
|
137
|
+
end
|
138
|
+
|
139
|
+
class Post < ActiveRecord::Base
|
140
|
+
include Patriarch::Behaviours
|
141
|
+
add_behaviour :comment, :by => :user, :via => :message
|
142
|
+
end
|
143
|
+
|
144
|
+
class Message < ActiveRecord::Base
|
145
|
+
include Patriarch::Behaviours
|
146
|
+
add_behaviour :comment, :medium_between => [:user,:post]
|
147
|
+
end
|
148
|
+
```
|
149
|
+
|
150
|
+
This will provide 'behaviour' methods and tool methods whose name are built like this :
|
151
|
+
```ruby
|
152
|
+
"#{actor_model_name.pluralize}_#{behaviour_in_progressive_present_form}_me_via_#{medium_model_name.pluralize}"
|
153
|
+
# tool method to retrieve models that acted on me through medium
|
154
|
+
|
155
|
+
"#{target_model_name.pluralize}_i_#{behaviour}_via_#{medium_model_name.pluralize}"
|
156
|
+
# tool method to retrieve models i acted on me through medium
|
157
|
+
|
158
|
+
"#{actor_model_name.pluralize}_#{behaviour_in_progressive_present_form}_#{target_model_name.pluralize}_via_me"
|
159
|
+
# tool method to retrieve models that acted through me on target
|
160
|
+
```
|
161
|
+
|
162
|
+
Adding suffix ids will prevent costly model instantiations and requesting the database and only return ids as an array
|
163
|
+
of Fixnum. See Options section to learn more about some detailed job.
|
164
|
+
|
165
|
+
And now with the example ...
|
166
|
+
```ruby
|
167
|
+
# Let's grab an user a message and a post, we assume some are already created
|
168
|
+
user = User.first
|
169
|
+
post = Post.first
|
170
|
+
mess = Message.first
|
171
|
+
|
172
|
+
user.comment mess,post
|
173
|
+
|
174
|
+
user.posts_i_comment_via_messages # => [post]
|
175
|
+
user.posts_i_comment_via_messages_ids # => [1]
|
176
|
+
|
177
|
+
post.users_commenting_me_via_messages # => [user]
|
178
|
+
post.users_commenting_me_via_messages_ids # => [1]
|
179
|
+
|
180
|
+
mess.users_commenting_posts_via_me
|
181
|
+
# => [{:actor_type => User, :actor_id => 1, :medium_type => Message, :medium_id => 1, :target_type => Post, :target_id => 1}]
|
182
|
+
|
183
|
+
user.undo_like mess
|
184
|
+
user.messages_i_like # => []
|
185
|
+
user.messages_i_like_ids # => []
|
186
|
+
|
187
|
+
user.hate post
|
188
|
+
user.posts_i_like # => []
|
189
|
+
user.posts_i_love_ids # => []
|
190
|
+
```
|
191
|
+
|
192
|
+
Also, aliases work for tripartite the same way they do for bipartite
|
193
|
+
|
194
|
+
### Options
|
195
|
+
#### with_scores
|
196
|
+
Patriarch automatically stores interactions with a score that equals to Time.now.to_f. This is for the moment not possible
|
197
|
+
to change this and is a behaviour of Patriarch that one should be able to change in a near future.
|
198
|
+
You can hence passe the options :with_scores => true when calling tool methods
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
# Let's grab an user a message and a post, we assume some are already created
|
202
|
+
user = User.first
|
203
|
+
post = Post.first
|
204
|
+
|
205
|
+
user.like post
|
206
|
+
|
207
|
+
user.posts_i_like # => [post]
|
208
|
+
user.posts_i_like :with_scores => true # => [[post,123456.789123]]
|
209
|
+
```
|
210
|
+
#### with_medium
|
211
|
+
Patriarch allows you to bring back the entire "who's who" information of a tripartite transaction
|
212
|
+
It will bring something like that if you take back the example we gave a while ago
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
user = User.first
|
216
|
+
post = Post.first
|
217
|
+
mess = Message.first
|
218
|
+
|
219
|
+
user.comment mess,post
|
220
|
+
|
221
|
+
user.posts_i_comment_via_messages # => [post]
|
222
|
+
user.posts_i_comment_via_messages_ids # => [1]
|
223
|
+
user.posts_i_comment_via_messages_ids :with_medium => true
|
224
|
+
# => [{:actor_type => User, :actor_id => 1, :medium_type => Message, :medium_id => 1, :target_type => Post, :target_id => 1}]
|
225
|
+
```
|
226
|
+
|
227
|
+
"with_medium" option is not compatible with "with_scores" option
|
62
228
|
|
63
229
|
## Contributing
|
64
230
|
|
@@ -67,3 +233,8 @@ It works like belongs_to and has_many helpers of active record, you need to incl
|
|
67
233
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
68
234
|
4. Push to the branch (`git push origin my-new-feature`)
|
69
235
|
5. Create new Pull Request
|
236
|
+
|
237
|
+
## Thanks
|
238
|
+
|
239
|
+
Thanks for using this gem ! If you are really really grateful or want to talk about this and happen to be in Paris, you
|
240
|
+
can issue a beer pull request that i will happily merge.
|
@@ -33,4 +33,13 @@ class Patriarch::Services::<%= class_name %>::ManagerService < Patriarch::Manage
|
|
33
33
|
# If everything went smoothly
|
34
34
|
transac.execute if (transac_first_step && callbacks_were_completed)
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
|
+
def resolve_with_reduced_sql_database_calls(actor_class,actor_id,target_class,target_id,medium_class,medium_id)
|
38
|
+
actor = OpenStruct.new ; actor.id = actor_id
|
39
|
+
actor.define_singleton_method(:class) do
|
40
|
+
actor_class
|
41
|
+
end
|
42
|
+
target = OpenStruct.new ; target.id = target_id ; target.class = target_class
|
43
|
+
medium = OpenStruct.new ; medium.id = medium_id ; medium.class = medium_class
|
44
|
+
end
|
45
|
+
end
|
@@ -1,21 +1,30 @@
|
|
1
1
|
require 'singleton'
|
2
2
|
|
3
|
+
# Mother class of all the Patriarch::__behaviour__::AuthorizationService
|
4
|
+
# We use singleton pattern here
|
3
5
|
module Patriarch
|
6
|
+
class ForbiddenBehaviourException < Exception; end
|
7
|
+
|
4
8
|
class AuthorizationService
|
5
9
|
include Singleton
|
6
10
|
|
7
|
-
#
|
11
|
+
# All authorization services are called by method #grant
|
12
|
+
# Since type verification is an eternal we implement grant in the mother class and let daughter classes
|
13
|
+
# call it with super and benefit from verify_types or bypass it completely and override the function
|
8
14
|
def grant?(transac)
|
9
|
-
|
10
|
-
if verify_types(transac)
|
15
|
+
if check_types(transac)
|
11
16
|
true
|
12
17
|
else
|
13
|
-
raise "that behaviour is not authorized"
|
18
|
+
raise Patriarch::ForbiddenBehaviourException, "that behaviour is not authorized"
|
14
19
|
end
|
15
|
-
#true
|
16
20
|
end
|
17
21
|
|
18
|
-
|
22
|
+
# When declaring behaviours in model thanks to add_behaviour helper we enforce that ONLY the behaviour declared
|
23
|
+
# are authorized. We hence verify that when a behaviour is called.
|
24
|
+
# For example User could be able to like Items and thus be blessed with #like as an instance method.
|
25
|
+
# But then we can tell any user instance to like any object, this method denies these behaviours.
|
26
|
+
# @transac [Patriarch::Transaction] the transaction to be authorized (or not)
|
27
|
+
def check_types(transac)
|
19
28
|
actor_model = transac.actor.class
|
20
29
|
actor_model_sym = actor_model.name.underscore.to_sym
|
21
30
|
|
@@ -29,19 +38,21 @@ module Patriarch
|
|
29
38
|
auths = []
|
30
39
|
|
31
40
|
if transac.tripartite?
|
32
|
-
#
|
41
|
+
# Verification for actor
|
33
42
|
auths << actor_model.patriarch_behaviours[behaviour][:on].map{ |b_sym| b_sym.to_s.underscore.to_sym }.include?(target_model_sym)
|
34
43
|
auths << actor_model.patriarch_behaviours[behaviour][:via].map{ |b_sym| b_sym.to_s.underscore.to_sym }.include?(medium_model_sym)
|
35
44
|
|
36
|
-
#
|
45
|
+
# Verification for target
|
37
46
|
auths << target_model.patriarch_behaviours[behaviour][:by].map{ |b_sym| b_sym.to_s.underscore.to_sym }.include?(actor_model_sym)
|
38
47
|
auths << target_model.patriarch_behaviours[behaviour][:via].map{ |b_sym| b_sym.to_s.underscore.to_sym }.include?(medium_model_sym)
|
39
48
|
|
40
|
-
#
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
49
|
+
# Verification for medium
|
50
|
+
# Pay attention here since add_behaviour syntax is different when being a medium
|
51
|
+
auths << medium_model.patriarch_behaviours[behaviour][:medium_between].map do |dual_sym_tab|
|
52
|
+
dual_sym_tab.map{ |b_sym| b_sym.to_s.underscore.to_sym }
|
53
|
+
end.include?(
|
54
|
+
[actor_model_sym, target_model_sym]
|
55
|
+
)
|
45
56
|
else
|
46
57
|
auths << actor_model.patriarch_behaviours[behaviour][:on].map{ |b_sym| b_sym.to_s.underscore.to_sym }.include?(target_model_sym)
|
47
58
|
auths << target_model.patriarch_behaviours[behaviour][:by].map{ |b_sym| b_sym.to_s.underscore.to_sym }.include?(actor_model_sym)
|
data/lib/patriarch/behaviours.rb
CHANGED
@@ -20,13 +20,17 @@ module Patriarch
|
|
20
20
|
class << self
|
21
21
|
|
22
22
|
# Helper function to complete the anonymous module we include later in the process in the enhanced model class
|
23
|
-
|
24
|
-
|
23
|
+
# @param [Module] anon_module refers to the anonymous module to be completed
|
24
|
+
# @param [String] behaviour the behaviour for which we complete the module with tools method
|
25
|
+
# @param [Array] acted_on_model_list the list of model classes that i can target with the behaviour
|
26
|
+
# @param [Hash] options options can serve to build custom alias for tool methods
|
27
|
+
def complete_custom_active_module_bipartite(anon_module,behaviour,acted_on_model_list,options={})
|
28
|
+
anon_module.class_eval do
|
25
29
|
|
26
30
|
acted_on_model_list.each do |acted_on_model|
|
27
31
|
|
28
32
|
# Compute names based on conventions
|
29
|
-
classic_tool_method_name = "#{acted_on_model.to_s.tableize}_i_#{
|
33
|
+
classic_tool_method_name = "#{acted_on_model.to_s.tableize}_i_#{behaviour}"
|
30
34
|
raw_tool_method_name = classic_tool_method_name + "_ids"
|
31
35
|
redis_key = "patriarch_" + classic_tool_method_name
|
32
36
|
|
@@ -37,29 +41,35 @@ module Patriarch
|
|
37
41
|
get_models_from_ids(self,acted_on_model.to_s.classify.constantize,raw_tool_method_name,options)
|
38
42
|
end
|
39
43
|
if options[:as]
|
40
|
-
alias_for_classic = classic_tool_method_name.sub(
|
41
|
-
alias_method alias_for_classic, classic_tool_method_name
|
42
|
-
end
|
44
|
+
alias_for_classic = classic_tool_method_name.sub(behaviour, options[:as].to_s)
|
45
|
+
alias_method alias_for_classic, classic_tool_method_name
|
46
|
+
end
|
43
47
|
|
44
48
|
define_method(raw_tool_method_name) do |options={}|
|
45
|
-
Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options)
|
49
|
+
Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options)
|
46
50
|
end
|
47
51
|
if options[:as]
|
48
|
-
alias_for_raw = raw_tool_method_name.sub(
|
52
|
+
alias_for_raw = raw_tool_method_name.sub(behaviour, options[:as].to_s)
|
49
53
|
alias_method alias_for_raw, raw_tool_method_name
|
50
|
-
end
|
54
|
+
end
|
51
55
|
end
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
55
|
-
def complete_custom_passive_module_bipartite(module_to_complete,relation_type,targetted_by_model_list,options={})
|
56
|
-
module_to_complete.class_eval do
|
57
59
|
|
58
|
-
|
60
|
+
# Helper function to complete the anonymous module we include later in the process in the enhanced model class
|
61
|
+
# @param [Module] anon_module refers to the anonymous module to be completed
|
62
|
+
# @param [String] behaviour the behaviour for which we complete the module with tools method
|
63
|
+
# @param [Array] targeted_by_model_list the list of model classes that can target me with the behaviour
|
64
|
+
# @param [Hash] options options can serve to build custom alias for tool methods
|
65
|
+
def complete_custom_passive_module_bipartite(anon_module,behaviour,targeted_by_model_list,options={})
|
66
|
+
anon_module.class_eval do
|
67
|
+
|
68
|
+
targeted_by_model_list.each do |targeted_by_model|
|
59
69
|
|
60
|
-
# Compute names based on conventions
|
61
|
-
progressive_present_relation_type = (Verbs::Conjugator.conjugate
|
62
|
-
classic_tool_method_name = "#{
|
70
|
+
# Compute names based on conventions
|
71
|
+
progressive_present_relation_type = (Verbs::Conjugator.conjugate behaviour.to_sym, :aspect => :progressive).split(/ /).last
|
72
|
+
classic_tool_method_name = "#{targeted_by_model.to_s.tableize}_#{progressive_present_relation_type}_me"
|
63
73
|
raw_tool_method_name = classic_tool_method_name + "_ids"
|
64
74
|
redis_key = "patriarch_" + classic_tool_method_name
|
65
75
|
|
@@ -67,43 +77,49 @@ module Patriarch
|
|
67
77
|
# Redis key has the same radical as the method in class by convention (but has a patriarch_ prefix to avoid collisions with other gems)
|
68
78
|
define_method(classic_tool_method_name) do |options={}|
|
69
79
|
Patriarch::ToolServices::RedisExtractorService.instance.
|
70
|
-
get_models_from_ids(self,
|
80
|
+
get_models_from_ids(self,targeted_by_model.to_s.classify.constantize,raw_tool_method_name,options)
|
71
81
|
end
|
72
82
|
if options[:as]
|
73
|
-
progressive_present_relation_type_alias = (Verbs::Conjugator.conjugate options[:as], :aspect => :progressive).split(/ /).last
|
83
|
+
progressive_present_relation_type_alias = (Verbs::Conjugator.conjugate options[:as], :aspect => :progressive).split(/ /).last
|
74
84
|
alias_for_classic = classic_tool_method_name.sub(progressive_present_relation_type,progressive_present_relation_type_alias)
|
75
85
|
alias_method alias_for_classic, classic_tool_method_name
|
76
86
|
end
|
77
87
|
|
78
88
|
define_method(raw_tool_method_name) do |options={}|
|
79
|
-
Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options)
|
89
|
+
Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options)
|
80
90
|
end
|
81
91
|
if options[:as]
|
82
|
-
progressive_present_relation_type_alias = (Verbs::Conjugator.conjugate options[:as], :aspect => :progressive).split(/ /).last
|
92
|
+
progressive_present_relation_type_alias = (Verbs::Conjugator.conjugate options[:as], :aspect => :progressive).split(/ /).last
|
83
93
|
alias_for_raw = raw_tool_method_name.sub(progressive_present_relation_type,progressive_present_relation_type_alias)
|
84
94
|
alias_method alias_for_raw, raw_tool_method_name
|
85
|
-
end
|
95
|
+
end
|
86
96
|
|
87
97
|
end
|
88
98
|
|
89
99
|
end
|
90
|
-
end
|
100
|
+
end
|
91
101
|
|
92
|
-
|
93
|
-
|
102
|
+
# Helper function to complete the anonymous module we include later in the process in the enhanced model class
|
103
|
+
# @param [Module] anon_module refers to the anonymous module to be completed
|
104
|
+
# @param [String] behaviour the behaviour for which we complete the module with tools method
|
105
|
+
# @param [Array] acted_on_model_list the list of model classes that i can target with the behaviour
|
106
|
+
# @param [Array] via_model_list the list of model classes that the behaviour use to act through
|
107
|
+
# @param [Hash] options options can serve to build custom alias for tool methods
|
108
|
+
def complete_custom_active_module_tripartite(anon_module,behaviour,acted_on_model_list,via_model_list,options={})
|
109
|
+
anon_module.class_eval do
|
94
110
|
|
95
111
|
acted_on_model_list.each do |acted_on_model|
|
96
112
|
via_model_list.each do |via_model|
|
97
113
|
|
98
114
|
# Compute names based on conventions
|
99
115
|
# fallen_angels_i_praise_via_love_letters
|
100
|
-
target_classic_tool_method_name = "#{acted_on_model.to_s.tableize}_i_#{
|
116
|
+
target_classic_tool_method_name = "#{acted_on_model.to_s.tableize}_i_#{behaviour}_via_#{via_model.to_s.tableize}"
|
101
117
|
target_raw_tool_method_name = target_classic_tool_method_name + "_ids"
|
102
118
|
|
103
119
|
# love_letters_i_use_to_praise_fallen_angels
|
104
|
-
medium_classic_tool_method_name = "#{via_model.to_s.tableize}_i_use_to_#{
|
105
|
-
medium_raw_tool_method_name = medium_classic_tool_method_name + "_ids"
|
106
|
-
|
120
|
+
medium_classic_tool_method_name = "#{via_model.to_s.tableize}_i_use_to_#{behaviour}_#{acted_on_model.to_s.tableize}"
|
121
|
+
medium_raw_tool_method_name = medium_classic_tool_method_name + "_ids"
|
122
|
+
|
107
123
|
redis_key = "patriarch_" + target_classic_tool_method_name
|
108
124
|
|
109
125
|
# Define methods with the pattern : items_i_like that returns models and items_i_like_ids that return
|
@@ -113,17 +129,17 @@ module Patriarch
|
|
113
129
|
get_models_from_ids(self,acted_on_model.to_s.classify.constantize,target_raw_tool_method_name,options.merge({:tripartite => true}))
|
114
130
|
end
|
115
131
|
if options[:as]
|
116
|
-
alias_for_classic = target_classic_tool_method_name.sub(
|
117
|
-
alias_method alias_for_classic, target_classic_tool_method_name
|
118
|
-
end
|
132
|
+
alias_for_classic = target_classic_tool_method_name.sub(behaviour, options[:as].to_s)
|
133
|
+
alias_method alias_for_classic, target_classic_tool_method_name
|
134
|
+
end
|
119
135
|
|
120
136
|
define_method(target_raw_tool_method_name) do |options={}|
|
121
137
|
Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options.merge({:tripartite => true, :protagonist_type => :target}))
|
122
138
|
end
|
123
139
|
if options[:as]
|
124
|
-
alias_for_target_raw = target_raw_tool_method_name.sub(
|
140
|
+
alias_for_target_raw = target_raw_tool_method_name.sub(behaviour, options[:as].to_s)
|
125
141
|
alias_method alias_for_target_raw, target_raw_tool_method_name
|
126
|
-
end
|
142
|
+
end
|
127
143
|
|
128
144
|
#
|
129
145
|
define_method(medium_classic_tool_method_name) do |options={}|
|
@@ -131,48 +147,54 @@ module Patriarch
|
|
131
147
|
get_models_from_ids(self,via_model.to_s.classify.constantize,medium_raw_tool_method_name,options.merge({:tripartite => true}))
|
132
148
|
end
|
133
149
|
if options[:as]
|
134
|
-
alias_for_medium_classic = medium_classic_tool_method_name.sub(
|
135
|
-
alias_method alias_for_medium_classic, medium_classic_tool_method_name
|
136
|
-
end
|
150
|
+
alias_for_medium_classic = medium_classic_tool_method_name.sub(behaviour, options[:as].to_s)
|
151
|
+
alias_method alias_for_medium_classic, medium_classic_tool_method_name
|
152
|
+
end
|
137
153
|
#
|
138
154
|
|
139
155
|
define_method(medium_raw_tool_method_name) do |options={}|
|
140
156
|
Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options.merge({:tripartite => true, :protagonist_type => :medium}))
|
141
157
|
end
|
142
158
|
if options[:as]
|
143
|
-
alias_for_medium_raw = medium_raw_tool_method_name.sub(
|
159
|
+
alias_for_medium_raw = medium_raw_tool_method_name.sub(behaviour, options[:as].to_s)
|
144
160
|
alias_method alias_for_medium_raw, medium_raw_tool_method_name
|
145
|
-
end
|
161
|
+
end
|
146
162
|
|
147
163
|
end
|
148
164
|
end
|
149
165
|
|
150
|
-
end
|
166
|
+
end
|
151
167
|
end
|
152
168
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
169
|
+
# Helper function to complete the anonymous module we include later in the process in the enhanced model class
|
170
|
+
# @param [Module] anon_module refers to the anonymous module to be completed
|
171
|
+
# @param [String] behaviour the behaviour for which we complete the module with tools method
|
172
|
+
# @param [Array] targeted_by_model_list the list of model classes that can target me with the behaviour
|
173
|
+
# @param [Array] via_model_list the list of model classes that the behaviour use to act through
|
174
|
+
# @param [Hash] options options can serve to build custom alias for tool methods
|
175
|
+
def complete_custom_passive_module_tripartite(anon_module,behaviour,targeted_by_model_list,via_model_list,options={})
|
176
|
+
anon_module.class_eval do
|
177
|
+
|
178
|
+
targeted_by_model_list.each do |targeted_by_model|
|
157
179
|
via_model_list.each do |via_model|
|
158
|
-
# Compute names based on conventions
|
159
|
-
progressive_present_relation_type = (Verbs::Conjugator.conjugate
|
160
|
-
|
161
|
-
actor_classic_tool_method_name = "#{
|
180
|
+
# Compute names based on conventions
|
181
|
+
progressive_present_relation_type = (Verbs::Conjugator.conjugate behaviour.to_sym, :aspect => :progressive).split(/ /).last
|
182
|
+
|
183
|
+
actor_classic_tool_method_name = "#{targeted_by_model.to_s.tableize}_#{progressive_present_relation_type}_me_via_#{via_model.to_s.tableize}"
|
162
184
|
actor_raw_tool_method_name = actor_classic_tool_method_name + "_ids"
|
163
|
-
|
185
|
+
|
164
186
|
#"love_letters_used_by_monsters_to_praise_me"
|
165
|
-
medium_classic_tool_method_name = "#{via_model.to_s.tableize}_used_by_#{
|
187
|
+
medium_classic_tool_method_name = "#{via_model.to_s.tableize}_used_by_#{targeted_by_model.to_s.tableize}_to_#{behaviour}_me"
|
166
188
|
medium_raw_tool_method_name = medium_classic_tool_method_name + "_ids"
|
167
|
-
|
189
|
+
|
168
190
|
redis_key = "patriarch_" + actor_classic_tool_method_name
|
169
191
|
|
170
192
|
define_method(actor_classic_tool_method_name) do |options={}|
|
171
193
|
Patriarch::ToolServices::RedisExtractorService.instance.
|
172
|
-
get_models_from_ids(self,
|
194
|
+
get_models_from_ids(self,targeted_by_model.to_s.classify.constantize,actor_raw_tool_method_name,options.merge({:tripartite => true}))
|
173
195
|
end
|
174
196
|
if options[:as]
|
175
|
-
progressive_present_relation_type_alias = (Verbs::Conjugator.conjugate options[:as], :aspect => :progressive).split(/ /).last
|
197
|
+
progressive_present_relation_type_alias = (Verbs::Conjugator.conjugate options[:as], :aspect => :progressive).split(/ /).last
|
176
198
|
alias_for_actor_classic = actor_classic_tool_method_name.sub(progressive_present_relation_type,progressive_present_relation_type_alias)
|
177
199
|
alias_method alias_for_actor_classic, actor_classic_tool_method_name
|
178
200
|
end
|
@@ -181,36 +203,41 @@ module Patriarch
|
|
181
203
|
Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options.merge({:tripartite => true , :protagonist_type => :actor}))
|
182
204
|
end
|
183
205
|
if options[:as]
|
184
|
-
progressive_present_relation_type_alias = (Verbs::Conjugator.conjugate options[:as], :aspect => :progressive).split(/ /).last
|
206
|
+
progressive_present_relation_type_alias = (Verbs::Conjugator.conjugate options[:as], :aspect => :progressive).split(/ /).last
|
185
207
|
alias_for_actor_raw = actor_raw_tool_method_name.sub(progressive_present_relation_type,progressive_present_relation_type_alias)
|
186
208
|
alias_method alias_for_actor_raw, actor_raw_tool_method_name
|
187
|
-
end
|
209
|
+
end
|
188
210
|
|
189
211
|
define_method(medium_classic_tool_method_name) do |options={}|
|
190
212
|
Patriarch::ToolServices::RedisExtractorService.instance.
|
191
213
|
get_models_from_ids(self,via_model.to_s.classify.constantize,medium_raw_tool_method_name,options.merge({:tripartite => true}))
|
192
|
-
end
|
214
|
+
end
|
193
215
|
#TODO add alias there
|
194
216
|
# FIXME id in it is wrong ...
|
195
217
|
define_method(medium_raw_tool_method_name) do |options={}|
|
196
218
|
Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options.merge({:tripartite => true , :protagonist_type => :medium}))
|
197
|
-
end
|
219
|
+
end
|
198
220
|
|
199
221
|
end
|
200
222
|
end
|
201
223
|
|
202
224
|
end
|
203
|
-
end
|
225
|
+
end
|
204
226
|
|
227
|
+
#:nodoc:
|
205
228
|
def included(klass)
|
229
|
+
# Classic extend of ClassMethods module embedded within this module
|
206
230
|
klass.extend ClassMethods
|
207
|
-
#klass.extend ActiveModel::Callbacks
|
208
231
|
unless klass.respond_to?(:before_destroy) && klass.respond_to?(:after_destroy)
|
209
232
|
raise AddBehaviourDependencyError, "class #{klass.name} including Patriarch::Behaviours does not support callbacks"
|
210
233
|
end
|
211
234
|
|
235
|
+
# insert callback logic here : behaviours have to be cleaned when a destroy occur in SQL
|
236
|
+
# First we build the transaction with #compute_redis_dependencies
|
237
|
+
# We execute the clean only when the SQL transaction commit to avoid data inconsistency if a SQL Rollback occurs
|
238
|
+
# in a middle of a cascading transaction
|
212
239
|
klass.class_eval do
|
213
|
-
|
240
|
+
|
214
241
|
before_destroy :compute_redis_dependencies
|
215
242
|
def compute_redis_dependencies
|
216
243
|
@redis_destroy_transac_object = Patriarch::ToolServices::RedisCleanerService.instance.clean_all(self)
|
@@ -240,40 +267,47 @@ module Patriarch
|
|
240
267
|
end
|
241
268
|
end
|
242
269
|
|
270
|
+
# Gathers class methods that should be available for model that include Patriarch::Behaviours
|
243
271
|
module ClassMethods
|
244
272
|
|
245
|
-
|
273
|
+
|
274
|
+
# Helper that checks if options syntax is correct
|
275
|
+
# Raises errors if not with indications on what should be corrected
|
276
|
+
# @param [Object] options
|
277
|
+
def check_add_behaviour_syntax(options)
|
246
278
|
if options[:medium_between] || options[:via]
|
247
|
-
check_tripartite_add_behaviour_syntax(
|
279
|
+
check_tripartite_add_behaviour_syntax(options)
|
248
280
|
elsif options[:on] || options[:by]
|
249
|
-
check_bipartite_add_behaviour_syntax(
|
281
|
+
check_bipartite_add_behaviour_syntax(options)
|
250
282
|
end
|
251
283
|
end
|
252
284
|
|
253
|
-
|
285
|
+
#:nodoc:
|
286
|
+
def check_bipartite_add_behaviour_syntax(options)
|
254
287
|
# Either you add a behaviour on another model or allow a behaviour on you by another model
|
255
288
|
unless options[:by].nil? ^ options[:on].nil?
|
256
289
|
raise AddBehaviourSyntaxError, "you must not define a behaviour as active (using on) and passive at the same time (using by)"
|
257
290
|
end
|
258
|
-
|
259
|
-
# as option should be a string or symbol
|
291
|
+
|
292
|
+
# as option should be a string or symbol
|
260
293
|
if options[:as]
|
261
|
-
unless [Symbol,String].include?(options[:as].class)
|
294
|
+
unless [Symbol,String].include?(options[:as].class)
|
262
295
|
raise AddBehaviourSyntaxError, "as option should be a string or symbol"
|
263
|
-
end
|
296
|
+
end
|
264
297
|
end
|
265
|
-
end
|
298
|
+
end
|
266
299
|
|
267
|
-
|
300
|
+
#:nodoc:
|
301
|
+
def check_tripartite_add_behaviour_syntax(options)
|
268
302
|
# Xor on options :medium_between and :via, disparate cases ...
|
269
303
|
unless options[:medium_between].nil? ^ options[:via].nil?
|
270
304
|
raise AddBehaviourSyntaxError, "you must not define a behaviour as active (using on) and passive at the same time (using by)"
|
271
|
-
end
|
305
|
+
end
|
272
306
|
|
273
307
|
if options[:via]
|
274
308
|
unless options[:by].nil? ^ options[:on].nil?
|
275
309
|
raise AddBehaviourSyntaxError, "you must not define a behaviour as active (using on) and passive at the same time (using by)"
|
276
|
-
end
|
310
|
+
end
|
277
311
|
else
|
278
312
|
medium_between_option = options[:medium_between]
|
279
313
|
unless medium_between_option.is_a?(Array) && medium_between_option.size == 2
|
@@ -282,8 +316,8 @@ module Patriarch
|
|
282
316
|
end
|
283
317
|
|
284
318
|
if options[:as]
|
285
|
-
# as option should be a string or symbol
|
286
|
-
unless [Symbol,String].include?(options[:as].class)
|
319
|
+
# as option should be a string or symbol
|
320
|
+
unless [Symbol,String].include?(options[:as].class)
|
287
321
|
raise AddBehaviourSyntaxError, "as option should be a string or symbol"
|
288
322
|
end
|
289
323
|
end
|
@@ -299,7 +333,11 @@ module Patriarch
|
|
299
333
|
end
|
300
334
|
end
|
301
335
|
|
302
|
-
|
336
|
+
# @param [Module] module_to_complete
|
337
|
+
# @param [String] behaviour
|
338
|
+
# @param [Object] options
|
339
|
+
# Adds alias for behaviour calls available to models if options allow to do so
|
340
|
+
def add_aliases_for_functionality(module_to_complete,behaviour,options)
|
303
341
|
if options[:as]
|
304
342
|
behaviour_alias = options[:as].to_s
|
305
343
|
end
|
@@ -308,25 +346,30 @@ module Patriarch
|
|
308
346
|
behaviour_undo_alias = options[:undo_as].to_s
|
309
347
|
end
|
310
348
|
|
311
|
-
if options[:on]
|
349
|
+
if options[:on]
|
312
350
|
module_to_complete.instance_eval do
|
313
351
|
# add behaviour_alias
|
314
|
-
if options[:as]
|
352
|
+
if options[:as]
|
315
353
|
alias_method behaviour_alias, behaviour
|
316
354
|
end
|
317
355
|
|
318
356
|
# add undo_behaviour_alias
|
319
|
-
if options[:undo_as]
|
357
|
+
if options[:undo_as]
|
320
358
|
alias_method behaviour_undo_alias, Patriarch.undo(behaviour)
|
321
|
-
end
|
359
|
+
end
|
322
360
|
end
|
323
|
-
end
|
361
|
+
end
|
324
362
|
end
|
325
363
|
|
326
|
-
|
327
|
-
|
364
|
+
# @param [Module] anon_module
|
365
|
+
# @param [String] behaviour
|
366
|
+
# Add basic behaviours calls to models in bipartite situations
|
367
|
+
def add_functionality_for_bipartite(anon_module,behaviour)
|
368
|
+
anon_module.instance_eval do
|
328
369
|
|
329
370
|
instance_eval do
|
371
|
+
# in instance_eval situations, there is no scope change so if we want to define included as a "self" method
|
372
|
+
# we are obliged to use this
|
330
373
|
(class << self; self; end).send(:define_method,:included) do |klass|
|
331
374
|
klass.extend ActiveModel::Callbacks
|
332
375
|
klass.send(:define_model_callbacks, behaviour, Patriarch.undo(behaviour))
|
@@ -336,24 +379,29 @@ module Patriarch
|
|
336
379
|
# behave
|
337
380
|
define_method(behaviour) do |entity,options={}|
|
338
381
|
run_callbacks behaviour do
|
339
|
-
"Patriarch::Services::#{behaviour.classify}::ManagerService".constantize.instance.resolve(self,entity,options)
|
382
|
+
"Patriarch::Services::#{behaviour.classify}::ManagerService".constantize.instance.resolve(self,entity,options)
|
340
383
|
end
|
341
384
|
end
|
342
385
|
|
343
386
|
# undo_behave
|
344
387
|
define_method(Patriarch.undo(behaviour).to_sym) do |entity,options={}|
|
345
388
|
run_callbacks Patriarch.undo(behaviour).to_sym do
|
346
|
-
"Patriarch::Services::#{(Patriarch.undo(behaviour)).classify}::ManagerService".constantize.instance.resolve(self,entity,options)
|
389
|
+
"Patriarch::Services::#{(Patriarch.undo(behaviour)).classify}::ManagerService".constantize.instance.resolve(self,entity,options)
|
347
390
|
end
|
348
391
|
end
|
349
392
|
|
350
393
|
end # instance_eval
|
351
394
|
end
|
352
395
|
|
353
|
-
|
354
|
-
|
396
|
+
# @param [Module] anon_module
|
397
|
+
# @param [String] behaviour
|
398
|
+
# Add basic behaviours calls to models in tripartite situations
|
399
|
+
def add_functionality_for_tripartite(anon_module,behaviour)
|
400
|
+
anon_module.instance_eval do
|
355
401
|
|
356
402
|
instance_eval do
|
403
|
+
# in instance_eval situations, there is no scope change so if we want to define included as a "self" method
|
404
|
+
# we are obliged to use this
|
357
405
|
(class << self; self; end).send(:define_method,:included) do |klass|
|
358
406
|
klass.extend ActiveModel::Callbacks
|
359
407
|
klass.send(:define_model_callbacks, behaviour, Patriarch.undo(behaviour))
|
@@ -363,7 +411,7 @@ module Patriarch
|
|
363
411
|
# behave
|
364
412
|
define_method(behaviour) do |via_entity,entity,options={}|
|
365
413
|
run_callbacks behaviour.to_sym do
|
366
|
-
"Patriarch::Services::#{behaviour.classify}::ManagerService".constantize.instance.resolve(self,entity,via_entity,options)
|
414
|
+
"Patriarch::Services::#{behaviour.classify}::ManagerService".constantize.instance.resolve(self,entity,via_entity,options)
|
367
415
|
end
|
368
416
|
end
|
369
417
|
|
@@ -371,48 +419,56 @@ module Patriarch
|
|
371
419
|
# undo_behave
|
372
420
|
define_method(Patriarch.undo(behaviour)) do |via_entity,entity,options={}|
|
373
421
|
run_callbacks Patriarch.undo(behaviour).to_sym do
|
374
|
-
"Patriarch::Services::#{Patriarch.undo(behaviour).classify}::ManagerService".constantize.instance.resolve(self,entity,via_entity,options)
|
422
|
+
"Patriarch::Services::#{Patriarch.undo(behaviour).classify}::ManagerService".constantize.instance.resolve(self,entity,via_entity,options)
|
375
423
|
end
|
376
424
|
end
|
377
425
|
|
378
426
|
end # instance_eval
|
379
427
|
end
|
380
428
|
|
429
|
+
# @param [String] behaviour
|
430
|
+
# @param [Hash] options
|
431
|
+
# Registers at a class level a declaration of bipartite behaviour so that it can be used
|
432
|
+
# to check protagonist types when calling behaviours
|
381
433
|
def register_bipartite_behaviour(behaviour,options)
|
434
|
+
behaviour = behaviour.underscore.to_sym
|
435
|
+
|
382
436
|
self.patriarch_behaviours ||= { }
|
383
437
|
#self.patriarch_behaviours[behaviour.underscore.to_sym] ||= { :on => [], :by =>[] }
|
384
|
-
self.patriarch_behaviours[behaviour
|
385
|
-
self.patriarch_behaviours[behaviour
|
386
|
-
self.patriarch_behaviours[behaviour
|
387
|
-
|
388
|
-
if options[:on]
|
389
|
-
self.patriarch_behaviours[behaviour
|
390
|
-
self.patriarch_behaviours[behaviour
|
391
|
-
self.patriarch_behaviours[behaviour
|
438
|
+
self.patriarch_behaviours[behaviour] ||= { }
|
439
|
+
self.patriarch_behaviours[behaviour][:on] ||= []
|
440
|
+
self.patriarch_behaviours[behaviour][:by] ||= []
|
441
|
+
|
442
|
+
if options[:on]
|
443
|
+
self.patriarch_behaviours[behaviour][:on] << options[:on]
|
444
|
+
self.patriarch_behaviours[behaviour][:on].uniq!
|
445
|
+
self.patriarch_behaviours[behaviour][:on].flatten!
|
392
446
|
elsif options[:by]
|
393
|
-
self.patriarch_behaviours[behaviour
|
394
|
-
self.patriarch_behaviours[behaviour
|
395
|
-
self.patriarch_behaviours[behaviour
|
396
|
-
end
|
447
|
+
self.patriarch_behaviours[behaviour][:by] << options[:by]
|
448
|
+
self.patriarch_behaviours[behaviour][:by].uniq!
|
449
|
+
self.patriarch_behaviours[behaviour][:by].flatten!
|
450
|
+
end
|
397
451
|
end
|
398
452
|
|
453
|
+
# @param [String] behaviour
|
454
|
+
# @param [Hash] options
|
455
|
+
# Registers at a class level a declaration of tripartite behaviour so that it can be used
|
456
|
+
# to check protagonist types when calling behaviours
|
399
457
|
def register_tripartite_behaviour(behaviour,options)
|
400
|
-
# TODO disjonction register tripartite
|
401
|
-
# register the behaviour we just added
|
402
458
|
behaviour = behaviour.underscore.to_sym
|
403
459
|
|
404
460
|
self.patriarch_behaviours ||= { }
|
405
|
-
self.patriarch_behaviours[behaviour] ||= {}
|
406
|
-
|
461
|
+
self.patriarch_behaviours[behaviour] ||= {}
|
462
|
+
|
407
463
|
if options[:via]
|
408
464
|
#self.patriarch_behaviours[behaviour.underscore.to_sym] ||= { :on => [], :by => [], :via => [] }
|
409
465
|
self.patriarch_behaviours[behaviour][:on] ||= []
|
410
|
-
self.patriarch_behaviours[behaviour][:by] ||= []
|
411
|
-
self.patriarch_behaviours[behaviour][:via] ||= []
|
466
|
+
self.patriarch_behaviours[behaviour][:by] ||= []
|
467
|
+
self.patriarch_behaviours[behaviour][:via] ||= []
|
412
468
|
elsif options[:medium_between]
|
413
469
|
#self.patriarch_behaviours[behaviour.underscore.to_sym] ||= { :medium_between => [] }
|
414
|
-
self.patriarch_behaviours[behaviour][:medium_between] ||= []
|
415
|
-
end
|
470
|
+
self.patriarch_behaviours[behaviour][:medium_between] ||= []
|
471
|
+
end
|
416
472
|
|
417
473
|
if options[:via]
|
418
474
|
if options[:on]
|
@@ -426,35 +482,38 @@ module Patriarch
|
|
426
482
|
end
|
427
483
|
self.patriarch_behaviours[behaviour][:via] << options[:via]
|
428
484
|
self.patriarch_behaviours[behaviour][:via].uniq!
|
429
|
-
self.patriarch_behaviours[behaviour][:via].flatten!
|
485
|
+
self.patriarch_behaviours[behaviour][:via].flatten!
|
430
486
|
elsif options[:medium_between]
|
431
487
|
self.patriarch_behaviours[behaviour][:medium_between] << options[:medium_between]
|
432
488
|
self.patriarch_behaviours[behaviour][:medium_between].uniq!
|
433
489
|
self.patriarch_behaviours[behaviour][:medium_between]
|
434
|
-
end
|
490
|
+
end
|
435
491
|
end
|
436
492
|
|
493
|
+
# @param [Symbol] behaviour the tripartite behaviour we want to add to our model
|
494
|
+
# @param [Object] options information useful to determine if supplementary functionality such as aliases or custom
|
495
|
+
# tool method shall be implemented
|
437
496
|
def add_tripartite_behaviour(behaviour,options)
|
438
497
|
behaviour = behaviour.to_s.underscore
|
439
498
|
|
440
|
-
check_add_behaviour_syntax(
|
499
|
+
check_add_behaviour_syntax(options)
|
441
500
|
|
442
501
|
methods_mod = Module.new do; end
|
443
502
|
|
444
503
|
# Target on Actor cases
|
445
504
|
if options[:via]
|
446
505
|
# Actor case
|
447
|
-
if options[:on]
|
448
|
-
|
449
|
-
|
506
|
+
if options[:on]
|
507
|
+
add_functionality_for_tripartite(methods_mod,behaviour)
|
508
|
+
add_aliases_for_functionality(methods_mod,behaviour,options)
|
450
509
|
acted_on_model_list = Array(options[:on])
|
451
510
|
via_model_list = Array(options[:via])
|
452
|
-
Patriarch::Behaviours.complete_custom_active_module_tripartite(methods_mod,behaviour,acted_on_model_list,via_model_list,options)
|
511
|
+
Patriarch::Behaviours.complete_custom_active_module_tripartite(methods_mod,behaviour,acted_on_model_list,via_model_list,options)
|
453
512
|
#Target case
|
454
513
|
elsif options[:by]
|
455
|
-
|
456
|
-
via_model_list = Array(options[:via])
|
457
|
-
Patriarch::Behaviours.complete_custom_passive_module_tripartite(methods_mod,behaviour,
|
514
|
+
targeted_by_model_list = Array(options[:by])
|
515
|
+
via_model_list = Array(options[:via])
|
516
|
+
Patriarch::Behaviours.complete_custom_passive_module_tripartite(methods_mod,behaviour,targeted_by_model_list,via_model_list,options)
|
458
517
|
end
|
459
518
|
# Medium case
|
460
519
|
elsif options[:medium_between]
|
@@ -463,35 +522,38 @@ module Patriarch
|
|
463
522
|
|
464
523
|
# Finally ...
|
465
524
|
include methods_mod
|
466
|
-
# include in which we can
|
525
|
+
# include in which we can override the methods of the previous custom module included there ...
|
467
526
|
include "Patriarch::Behaviours::#{behaviour.classify}::ToolsMethods".constantize
|
468
527
|
# register behaviour we just added
|
469
|
-
register_tripartite_behaviour(behaviour,options)
|
528
|
+
register_tripartite_behaviour(behaviour,options)
|
470
529
|
end
|
471
530
|
|
531
|
+
# @param [Symbol] behaviour the bipartite behaviour we want to add to our model
|
532
|
+
# @param [Object] options information useful to determine if supplementary functionality such as aliases or custom
|
533
|
+
# tool method shall be implemented
|
472
534
|
def add_bipartite_behaviour(behaviour,options)
|
473
|
-
# add_behaviour :like, :by => bla, :on => [:item,:user] || :community, :as => :
|
474
|
-
|
535
|
+
# add_behaviour :like, :by => bla, :on => [:item,:user] || :community, :as => :love, :reverse_as => :hate ...
|
536
|
+
|
475
537
|
behaviour = behaviour.to_s.underscore
|
476
538
|
|
477
|
-
check_add_behaviour_syntax(
|
539
|
+
check_add_behaviour_syntax(options)
|
478
540
|
|
479
541
|
methods_mod = Module.new do; end
|
480
542
|
|
481
|
-
if options[:on]
|
543
|
+
if options[:on]
|
482
544
|
# Adds active methods and defines the hook to set callbacks on them
|
483
|
-
|
484
|
-
|
545
|
+
add_functionality_for_bipartite(methods_mod,behaviour)
|
546
|
+
add_aliases_for_functionality(methods_mod,behaviour,options)
|
485
547
|
acted_on_model_list = Array(options[:on])
|
486
|
-
Patriarch::Behaviours.complete_custom_active_module_bipartite(methods_mod,behaviour,acted_on_model_list,options)
|
548
|
+
Patriarch::Behaviours.complete_custom_active_module_bipartite(methods_mod,behaviour,acted_on_model_list,options)
|
487
549
|
else
|
488
|
-
|
489
|
-
Patriarch::Behaviours.complete_custom_passive_module_bipartite(methods_mod,behaviour,
|
550
|
+
targeted_by_model_list = Array(options[:by])
|
551
|
+
Patriarch::Behaviours.complete_custom_passive_module_bipartite(methods_mod,behaviour,targeted_by_model_list,options)
|
490
552
|
end
|
491
553
|
|
492
554
|
# Finally includes the custom module
|
493
555
|
include methods_mod
|
494
|
-
# include in which we can
|
556
|
+
# include in which we can override the methods of the previous custom module included there ...
|
495
557
|
include "Patriarch::Behaviours::#{behaviour.classify}::ToolsMethods".constantize
|
496
558
|
# register the behaviour we just added
|
497
559
|
register_bipartite_behaviour(behaviour,options)
|