patriarch 0.2.3 → 0.2.4
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.
- 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)
|