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
@@ -1,4 +1,33 @@
|
|
1
|
+
# Service providing methods that extract information from Redis Database like which entities behaved on me or i behaved
|
2
|
+
# on and when without knowing how the internals work. Methods are hence wrapped into sugar when called from models
|
3
|
+
# For instance with add_behaviour :like, :on => [:item] embedded in model User we build a tool method called
|
4
|
+
# items_i_like_ids that knows how to call #get_ids_from_sorted_set but does not care about internals
|
1
5
|
class Patriarch::ToolServices::RedisExtractorService < Patriarch::Service
|
6
|
+
|
7
|
+
# This gets ids stored in a given Redis::SortedSet and returns in an adapted format.
|
8
|
+
# Hence it supports various options.
|
9
|
+
#
|
10
|
+
# Base options are born from those supported by Redis::SortedSet and allow some sorting on score with options :from and :limit
|
11
|
+
# Original options were :from and :to
|
12
|
+
# More on this in redis-objects documentation
|
13
|
+
#
|
14
|
+
# Bipartite / With scores
|
15
|
+
# When storing data in bipartite transactions there is 2 protagonists hence, each protagonist only has on id to remember
|
16
|
+
# The output format is thus [id1,id2, ...] or [ [id1,score1], [id2,score2], ...] if called with option :with_scores
|
17
|
+
#
|
18
|
+
# Tripartite / With scores / protagonist type
|
19
|
+
# When storing data in tripartite there are 3 protagonists. Each of them needs to know about the 2 others most of the time.
|
20
|
+
# We store then triplets built like this : [actor,target,medium]. Triplets are marshalled.
|
21
|
+
# We choose which of the protagonist we want to retrieve information about thanks to option :protagonist_type
|
22
|
+
# Values can be :actor, :target or :medium
|
23
|
+
# The output format is thus [id_protagonist_type1, id_protagonist_type2, ...] or [[id_pt1, score1], [id_pt2,score2]] if called
|
24
|
+
# with option :with_scores
|
25
|
+
#
|
26
|
+
# Sometimes we want to know it all from target or actor point of view we hence call with option :with_medium
|
27
|
+
# Option :with_scores is not supported here
|
28
|
+
# Output format is thus [{:actor1 => actor_id1, :target1 => target_id1, :medium1 => medium_id1}, {actor2,target2,medium2 ...}, ...]
|
29
|
+
#
|
30
|
+
# For more information about redis dao return type, please go on http://github.com/nateware and visit redis-objects
|
2
31
|
def get_ids_from_sorted_set(calling_entity,redis_key,options={})
|
3
32
|
from = options[:from] || 0
|
4
33
|
limit = options[:limit] || :infinity
|
@@ -24,10 +53,11 @@ class Patriarch::ToolServices::RedisExtractorService < Patriarch::Service
|
|
24
53
|
result = ids_from_redis
|
25
54
|
end
|
26
55
|
|
27
|
-
#TODO Document me ...
|
28
56
|
if options[:with_medium]
|
29
|
-
|
30
|
-
|
57
|
+
if options[:with_scores]
|
58
|
+
raise Exception, "with_scores options is not supported along with_medium"
|
59
|
+
end
|
60
|
+
result.map!{ |triplet_id| {:actor => triplet_id[0].to_i, :target => triplet_id[1].to_i, :medium => triplet_id[2].to_i} }
|
31
61
|
return result
|
32
62
|
else
|
33
63
|
if options[:tripartite]
|
@@ -51,8 +81,7 @@ class Patriarch::ToolServices::RedisExtractorService < Patriarch::Service
|
|
51
81
|
end
|
52
82
|
end
|
53
83
|
|
54
|
-
#
|
55
|
-
|
84
|
+
# This sanitizes strings returned by Redis::Objects into integers.
|
56
85
|
result.map! do |x|
|
57
86
|
if x.is_a? Array
|
58
87
|
x[0].to_i
|
@@ -64,6 +93,7 @@ class Patriarch::ToolServices::RedisExtractorService < Patriarch::Service
|
|
64
93
|
result
|
65
94
|
end
|
66
95
|
|
96
|
+
# Tool method allowing to instantiate models from ids we find with method #get_ids_from_sorted_sets
|
67
97
|
def get_models_from_ids(calling_entity,model,get_id_method,options={})
|
68
98
|
if options[:with_medium]
|
69
99
|
id_hash_from_redis = calling_entity.send(get_id_method,options)
|
@@ -1,4 +1,13 @@
|
|
1
1
|
module Patriarch
|
2
|
+
# Class made to handle transaction even cascading ones (i.e behaviours called in the after callback of other behaviour)
|
3
|
+
# It serves as an interface that hide the different steps included in a transaction and allow us to decide when to perform
|
4
|
+
# a transaction with #execute once transaction has been built
|
5
|
+
# Passing an instance of Patriarch::Tansaction around will in some cases prevent from building another transaction and
|
6
|
+
# hence write the following events (transaction steps) in this instance
|
7
|
+
# Thus, it will build a transaction that engluf all the transaction step and can be performed entirely in one time
|
8
|
+
# It is useful to permit sql rollbacks to occur before the transaction is being executed when destroying items with
|
9
|
+
# a cascading effect. It covers the edge case where a cascading destroy that would rollback at step 3 would have performed
|
10
|
+
# the 3 destroy into the no sql database model before.
|
2
11
|
class Transaction
|
3
12
|
attr_reader :id, :steps, :current_step_number
|
4
13
|
attr_writer :steps
|
@@ -80,10 +89,8 @@ module Patriarch
|
|
80
89
|
|
81
90
|
alias :queue :transaction_queue
|
82
91
|
|
83
|
-
protected
|
84
|
-
|
85
92
|
def current_step
|
86
93
|
steps[current_step_number-1]
|
87
94
|
end
|
88
95
|
end
|
89
|
-
end
|
96
|
+
end
|
@@ -1,16 +1,20 @@
|
|
1
1
|
module Patriarch
|
2
|
+
# Represents a "step" i.e. what should occur from no sql database point of view when a model instance
|
3
|
+
# invokes a behaviour. It is encapsulated into Patriarch::Transaction item and is never exposed.
|
4
|
+
# When needed, Patriarch::Transaction will forward some method call to the current TransactionStep
|
5
|
+
# that is being built
|
2
6
|
class TransactionStep
|
3
7
|
attr_accessor :context, :queue
|
4
8
|
|
5
9
|
def initialize(relation_type,actor,target,medium = nil)
|
6
|
-
@context = {
|
10
|
+
@context = {
|
7
11
|
:relation_type => relation_type,
|
8
12
|
:actor_type => actor.class.name.underscore.to_sym,
|
9
13
|
:target_type => target.class.name.underscore.to_sym,
|
10
14
|
:actor_id => actor.id,
|
11
15
|
:target_id => target.id,
|
12
16
|
}
|
13
|
-
if medium
|
17
|
+
if medium
|
14
18
|
@context.merge! :medium_id => medium.id, :medium_type => medium.class.name.underscore.to_sym
|
15
19
|
end
|
16
20
|
@queue = []
|
@@ -23,25 +27,32 @@ module Patriarch
|
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
30
|
+
# @return the medium of this step if it exists
|
26
31
|
def medium
|
27
32
|
return nil unless medium_id && medium_type
|
28
33
|
medium_type.to_s.camelize.constantize.find medium_id
|
29
34
|
end
|
30
35
|
|
36
|
+
# @return the actor of this step
|
31
37
|
def actor
|
32
38
|
actor_type.to_s.camelize.constantize.find actor_id
|
33
39
|
end
|
34
40
|
|
41
|
+
# @return the target of this step
|
35
42
|
def target
|
36
43
|
target_type.to_s.camelize.constantize.find target_id
|
37
44
|
end
|
38
45
|
|
46
|
+
# execute the redis instruction embedded into this step
|
47
|
+
# Patriach::Transaction use this method on each of the steps it registered within a multi block
|
39
48
|
def execute
|
40
49
|
queue.each do |redis_instruction|
|
41
50
|
redis_instruction.call
|
42
51
|
end
|
43
52
|
end
|
44
53
|
|
54
|
+
# Add a redis instruction embedded in a proc into the queue of instruction to be processed of this step
|
55
|
+
# @param [Proc] proc the chunk of executable redis code embedded into a Proc to be added to queue
|
45
56
|
def add_to_queue(proc)
|
46
57
|
queue << proc
|
47
58
|
end
|
data/lib/patriarch/version.rb
CHANGED
@@ -11,7 +11,7 @@ describe Patriarch::ToolServices::RedisCleanerService.instance do
|
|
11
11
|
# Tripartite behaviour ...
|
12
12
|
FallenAngel.add_behaviour :praise, :by => [:monster], :via => [:loveLetter]
|
13
13
|
Monster.add_behaviour :praise, :on => [:fallenAngel], :via => [:loveLetter]
|
14
|
-
LoveLetter.add_behaviour :praise, :medium_between => [:fallenAngel
|
14
|
+
LoveLetter.add_behaviour :praise, :medium_between => [:monster,:fallenAngel]
|
15
15
|
end
|
16
16
|
|
17
17
|
let(:monster) { Monster.create }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: patriarch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: verbs
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: railties
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: '0'
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: activerecord
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
@@ -43,10 +53,15 @@ dependencies:
|
|
43
53
|
version: '0'
|
44
54
|
type: :runtime
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: rspec
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ! '>='
|
@@ -54,10 +69,15 @@ dependencies:
|
|
54
69
|
version: '0'
|
55
70
|
type: :development
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
58
78
|
- !ruby/object:Gem::Dependency
|
59
79
|
name: guard-rspec
|
60
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
61
81
|
none: false
|
62
82
|
requirements:
|
63
83
|
- - ! '>='
|
@@ -65,10 +85,15 @@ dependencies:
|
|
65
85
|
version: '0'
|
66
86
|
type: :development
|
67
87
|
prerelease: false
|
68
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
69
94
|
- !ruby/object:Gem::Dependency
|
70
95
|
name: activerecord
|
71
|
-
requirement:
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
72
97
|
none: false
|
73
98
|
requirements:
|
74
99
|
- - ! '>='
|
@@ -76,10 +101,15 @@ dependencies:
|
|
76
101
|
version: '0'
|
77
102
|
type: :development
|
78
103
|
prerelease: false
|
79
|
-
version_requirements:
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
80
110
|
- !ruby/object:Gem::Dependency
|
81
111
|
name: sqlite3
|
82
|
-
requirement:
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
83
113
|
none: false
|
84
114
|
requirements:
|
85
115
|
- - ! '>='
|
@@ -87,7 +117,12 @@ dependencies:
|
|
87
117
|
version: '0'
|
88
118
|
type: :development
|
89
119
|
prerelease: false
|
90
|
-
version_requirements:
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
91
126
|
description: Patriach is about adding behaviours on the fly to good old active record
|
92
127
|
models.
|
93
128
|
email:
|
@@ -168,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
203
|
version: '0'
|
169
204
|
requirements: []
|
170
205
|
rubyforge_project:
|
171
|
-
rubygems_version: 1.8.
|
206
|
+
rubygems_version: 1.8.24
|
172
207
|
signing_key:
|
173
208
|
specification_version: 3
|
174
209
|
summary: Manage relationships between instances of your models easily
|