patriarch 0.2.4 → 0.2.5
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/.travis.yml +12 -0
- data/README.md +8 -5
- data/Rakefile +5 -0
- data/lib/patriarch/dao_services/bipartite_relationship_builder_service.rb +17 -13
- data/lib/patriarch/dao_services/tripartite_relationship_builder_service.rb +16 -10
- data/lib/patriarch/tool_services/redis_cleaner_service.rb +0 -2
- data/lib/patriarch/transaction.rb +2 -2
- data/lib/patriarch/transaction_step.rb +11 -7
- data/lib/patriarch/version.rb +1 -1
- data/patriarch.gemspec +2 -2
- data/spec/lib/patriarch/dao_services/bipartite_relationship_builder_spec.rb +13 -5
- data/spec/lib/patriarch/dao_services/tripartite_relationship_builder_spec.rb +13 -5
- data/spec/lib/patriarch/destroy_entity_spec.rb +55 -0
- metadata +5 -2
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[](https://travis-ci.org/giglemad/patriarch)
|
2
|
+
[](https://gemnasium.com/giglemad/patriarch)
|
1
3
|
# Patriarch
|
2
4
|
|
3
5
|
N-N tables are often a pain to deal with in SQL especially when you want to
|
@@ -32,11 +34,6 @@ Add this line to your application's Gemfile:
|
|
32
34
|
gem 'patriarch'
|
33
35
|
```
|
34
36
|
|
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
|
-
```
|
39
|
-
|
40
37
|
And then execute:
|
41
38
|
|
42
39
|
$ bundle update
|
@@ -44,6 +41,10 @@ And then execute:
|
|
44
41
|
Or install it yourself as:
|
45
42
|
|
46
43
|
$ gem install patriarch
|
44
|
+
|
45
|
+
Patriarch needs to generate some file before you use it, type this:
|
46
|
+
|
47
|
+
$ rails generate patriarch:install
|
47
48
|
|
48
49
|
## Usage
|
49
50
|
|
@@ -236,5 +237,7 @@ user.posts_i_comment_via_messages_ids :with_medium => true
|
|
236
237
|
|
237
238
|
## Thanks
|
238
239
|
|
240
|
+
I'd like to give credit to @nateware who built the awesome Redis-Objects this gem rely on to perform operations against redis.
|
241
|
+
|
239
242
|
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
243
|
can issue a beer pull request that i will happily merge.
|
data/Rakefile
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require "redis/objects/sorted_sets"
|
2
|
-
|
2
|
+
require 'ostruct'
|
3
3
|
# Patriarch::Transaction instances are composed of transaction steps that each represent
|
4
4
|
# a behaviour being triggered. RelationshipBuilderServices allow Services managing transaction
|
5
5
|
# flow to build transaction step correctly. This deals with transaction step needed to represent
|
@@ -16,8 +16,11 @@ class Patriarch::DAOServices::BipartiteRelationshipBuilderService < Patriarch::S
|
|
16
16
|
actor_dao = dao_tab[:actor]
|
17
17
|
target_dao = dao_tab[:target]
|
18
18
|
|
19
|
-
l =
|
20
|
-
ll =
|
19
|
+
l = build_ostruct_for_create(actor_dao,transaction_item.target_id,t)
|
20
|
+
ll = build_ostruct_for_create(target_dao,transaction_item.actor_id,t)
|
21
|
+
|
22
|
+
p "#{l.inspect} is creating on key #{actor_dao.key} : #{transaction_item.target_type} #{transaction_item.target_id}"
|
23
|
+
p "#{ll.inspect} is creating on key #{target_dao.key} : #{transaction_item.actor_type} #{transaction_item.actor_id}"
|
21
24
|
|
22
25
|
# care about that, should be encapsulated into a beautiful add_to_queue method
|
23
26
|
transaction_item.add_to_queue l
|
@@ -32,12 +35,11 @@ class Patriarch::DAOServices::BipartiteRelationshipBuilderService < Patriarch::S
|
|
32
35
|
|
33
36
|
actor_dao = dao_tab[:actor]
|
34
37
|
target_dao = dao_tab[:target]
|
35
|
-
|
36
|
-
l = lambda { actor_dao.delete transaction_item.target_id }
|
37
|
-
ll = lambda { target_dao.delete transaction_item.actor_id }
|
38
38
|
|
39
|
-
#
|
40
|
-
#
|
39
|
+
#l = proc { actor_dao.delete transaction_item.target_id }
|
40
|
+
#ll = proc { target_dao.delete transaction_item.actor_id }
|
41
|
+
l = OpenStruct.new(:method_sym => :delete ,:dao => actor_dao, :args => [transaction_item.target_id])
|
42
|
+
ll = OpenStruct.new(:method_sym => :delete ,:dao => target_dao, :args => [transaction_item.actor_id])
|
41
43
|
|
42
44
|
transaction_item.add_to_queue l
|
43
45
|
transaction_item.add_to_queue ll
|
@@ -47,12 +49,14 @@ class Patriarch::DAOServices::BipartiteRelationshipBuilderService < Patriarch::S
|
|
47
49
|
# @param [Redis::Objects] dao
|
48
50
|
# @param [Array] ids
|
49
51
|
# @param [Time] time
|
50
|
-
# Returns
|
51
|
-
def
|
52
|
+
# Returns ostruct objects that store parameters to execute a redis operation
|
53
|
+
def build_ostruct_for_create(dao,id,time)
|
52
54
|
if dao.is_a? Redis::SortedSet
|
53
|
-
return
|
55
|
+
return OpenStruct.new(:method_sym => :add ,:dao => dao, :args => [id,time])
|
56
|
+
# return lambda { dao.add ids, time }
|
54
57
|
else
|
55
|
-
return
|
58
|
+
return OpenStruct.new(:method_sym => :add ,:dao => dao, :args => [id])
|
59
|
+
# return lambda { dao.add ids }
|
56
60
|
end
|
57
|
-
end
|
61
|
+
end
|
58
62
|
end
|
@@ -20,9 +20,9 @@ class Patriarch::DAOServices::TripartiteRelationshipBuilderService < Patriarch::
|
|
20
20
|
|
21
21
|
protagonist_ids = [transaction_item.actor_id,transaction_item.target_id,transaction_item.medium_id]
|
22
22
|
|
23
|
-
l =
|
24
|
-
ll =
|
25
|
-
lll =
|
23
|
+
l = build_ostruct_for_create(actor_dao,protagonist_ids,t)
|
24
|
+
ll = build_ostruct_for_create(target_dao,protagonist_ids,t)
|
25
|
+
lll = build_ostruct_for_create(medium_dao,protagonist_ids,t)
|
26
26
|
|
27
27
|
# care about that, should be encapsulated into a beautiful add_to_queue method
|
28
28
|
transaction_item.add_to_queue l
|
@@ -42,10 +42,14 @@ class Patriarch::DAOServices::TripartiteRelationshipBuilderService < Patriarch::
|
|
42
42
|
|
43
43
|
protagonist_ids = [transaction_item.actor_id,transaction_item.target_id,transaction_item.medium_id]
|
44
44
|
|
45
|
-
l = lambda { actor_dao.delete protagonist_ids }
|
46
|
-
ll = lambda { target_dao.delete protagonist_ids }
|
47
|
-
lll = lambda { medium_dao.delete protagonist_ids }
|
45
|
+
#l = lambda { actor_dao.delete protagonist_ids }
|
46
|
+
#ll = lambda { target_dao.delete protagonist_ids }
|
47
|
+
#lll = lambda { medium_dao.delete protagonist_ids }
|
48
48
|
|
49
|
+
l = OpenStruct.new(:method_sym => :delete ,:dao => actor_dao, :args => [protagonist_ids])
|
50
|
+
ll = OpenStruct.new(:method_sym => :delete ,:dao => target_dao, :args => [protagonist_ids])
|
51
|
+
lll = OpenStruct.new(:method_sym => :delete ,:dao => medium_dao, :args => [protagonist_ids])
|
52
|
+
|
49
53
|
transaction_item.add_to_queue l
|
50
54
|
transaction_item.add_to_queue ll
|
51
55
|
transaction_item.add_to_queue lll
|
@@ -55,12 +59,14 @@ class Patriarch::DAOServices::TripartiteRelationshipBuilderService < Patriarch::
|
|
55
59
|
# @param [Redis::Objects] dao
|
56
60
|
# @param [Array] ids
|
57
61
|
# @param [Time] time
|
58
|
-
# Returns
|
59
|
-
def
|
62
|
+
# Returns ostruct objects that store parameters to execute a redis operation
|
63
|
+
def build_ostruct_for_create(dao,ids,time)
|
60
64
|
if dao.is_a? Redis::SortedSet
|
61
|
-
return
|
65
|
+
return OpenStruct.new(:method_sym => :add ,:dao => dao, :args => [ids,time])
|
66
|
+
# return lambda { dao.add ids, time }
|
62
67
|
else
|
63
|
-
return
|
68
|
+
return OpenStruct.new(:method_sym => :add ,:dao => dao, :args => [ids])
|
69
|
+
# return lambda { dao.add ids }
|
64
70
|
end
|
65
71
|
end
|
66
72
|
end
|
@@ -43,18 +43,22 @@ module Patriarch
|
|
43
43
|
target_type.to_s.camelize.constantize.find target_id
|
44
44
|
end
|
45
45
|
|
46
|
-
# execute the redis
|
46
|
+
# execute the redis instructions embedded into this step against
|
47
|
+
# instructions are a dao, a method to call upon and its argument embedded into a OpenStruct
|
48
|
+
# before Patriarch 0.2.5, was embedded directly in a proc, was a complete failure for unknown reasons
|
47
49
|
# Patriach::Transaction use this method on each of the steps it registered within a multi block
|
48
50
|
def execute
|
49
|
-
queue.each do |
|
50
|
-
|
51
|
+
queue.each do |redis_ostruct_instruction|
|
52
|
+
os = redis_ostruct_instruction
|
53
|
+
dao, method_sym, args = [os.dao,os.method_sym,os.args]
|
54
|
+
dao.send(method_sym,*args)
|
55
|
+
# deprecated, remove this : redis_instruction.call
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
54
|
-
#
|
55
|
-
|
56
|
-
|
57
|
-
queue << proc
|
59
|
+
# @param [OpenStruct] ostruct dao with parameters and method to call embedded here to be processed later
|
60
|
+
def add_to_queue(ostruct)
|
61
|
+
queue << ostruct
|
58
62
|
end
|
59
63
|
end
|
60
64
|
end
|
data/lib/patriarch/version.rb
CHANGED
data/patriarch.gemspec
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
require File.expand_path('../lib/patriarch/version', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |spec|
|
5
|
-
spec.authors = ["Hugo Lepetit"]
|
6
|
-
spec.email = ["hugo@blackbid.co"]
|
5
|
+
spec.authors = ["Hugo Lepetit","Loïc Delmaire"]
|
6
|
+
spec.email = ["hugo@blackbid.co","loic@blackbird.co"]
|
7
7
|
spec.description = %q{Patriach is about adding behaviours on the fly to good old active record models.}
|
8
8
|
spec.summary = %q{Manage relationships between instances of your models easily}
|
9
9
|
spec.homepage = "https://github.com/giglemad/patriarch"
|
@@ -22,20 +22,28 @@ describe Patriarch::DAOServices::BipartiteRelationshipBuilderService do
|
|
22
22
|
it "shall insert processable lambdas into queues when create is called" do
|
23
23
|
expect{
|
24
24
|
instance.create(@transac)
|
25
|
-
}.to change{ @transac.transaction_queue.select{ |queue_element| queue_element.is_a?
|
25
|
+
}.to change{ @transac.transaction_queue.select{ |queue_element| queue_element.is_a? OpenStruct}.size }.by(2)
|
26
26
|
|
27
27
|
expect{
|
28
|
-
@transac.transaction_queue.each
|
28
|
+
@transac.transaction_queue.each do |redis_ostruct_instruction|
|
29
|
+
os = redis_ostruct_instruction
|
30
|
+
dao, method_sym, args = [os.dao,os.method_sym,os.args]
|
31
|
+
dao.send(method_sym,*args)
|
32
|
+
end
|
29
33
|
}.to change{ $redis.keys.size}.by(2)
|
30
34
|
end
|
31
35
|
|
32
36
|
it "shall insert processable lambdas into queues when destroy is called" do
|
33
37
|
expect{
|
34
38
|
instance.destroy(@transac)
|
35
|
-
}.to change{ @transac.transaction_queue.select{ |queue_element| queue_element.is_a?
|
39
|
+
}.to change{ @transac.transaction_queue.select{ |queue_element| queue_element.is_a? OpenStruct}.size }.by(2)
|
36
40
|
|
37
41
|
expect{
|
38
|
-
@transac.transaction_queue.each
|
42
|
+
@transac.transaction_queue.each do |redis_ostruct_instruction|
|
43
|
+
os = redis_ostruct_instruction
|
44
|
+
dao, method_sym, args = [os.dao,os.method_sym,os.args]
|
45
|
+
dao.send(method_sym,*args)
|
46
|
+
end
|
39
47
|
}.to change{ $redis.info["total_commands_processed"].to_i}.by(3)
|
40
48
|
end
|
41
49
|
|
@@ -43,4 +51,4 @@ describe Patriarch::DAOServices::BipartiteRelationshipBuilderService do
|
|
43
51
|
$redis.del "monster:#{monster.id}:patriarch_fallen_angels_i_like"
|
44
52
|
$redis.del "fallen_angel:#{fallen_angel.id}:patriarch_monsters_liking_me"
|
45
53
|
end
|
46
|
-
end
|
54
|
+
end
|
@@ -24,20 +24,28 @@ describe Patriarch::DAOServices::TripartiteRelationshipBuilderService do
|
|
24
24
|
it "shall insert processable lambdas into queues when create is called" do
|
25
25
|
expect{
|
26
26
|
instance.create(@transac)
|
27
|
-
}.to change{ @transac.transaction_queue.select{ |queue_element| queue_element.is_a?
|
27
|
+
}.to change{ @transac.transaction_queue.select{ |queue_element| queue_element.is_a? OpenStruct}.size }.by(3)
|
28
28
|
|
29
29
|
expect{
|
30
|
-
@transac.transaction_queue.each
|
30
|
+
@transac.transaction_queue.each do |redis_ostruct_instruction|
|
31
|
+
os = redis_ostruct_instruction
|
32
|
+
dao, method_sym, args = [os.dao,os.method_sym,os.args]
|
33
|
+
dao.send(method_sym,*args)
|
34
|
+
end
|
31
35
|
}.to change{ $redis.keys.size}.by(3)
|
32
36
|
end
|
33
37
|
|
34
38
|
it "shall insert processable lambdas into queues when destroy is called" do
|
35
39
|
expect{
|
36
40
|
instance.destroy(@transac)
|
37
|
-
}.to change{ @transac.transaction_queue.select{ |queue_element| queue_element.is_a?
|
41
|
+
}.to change{ @transac.transaction_queue.select{ |queue_element| queue_element.is_a? OpenStruct}.size }.by(3)
|
38
42
|
|
39
43
|
expect{
|
40
|
-
@transac.transaction_queue.each
|
44
|
+
@transac.transaction_queue.each do |redis_ostruct_instruction|
|
45
|
+
os = redis_ostruct_instruction
|
46
|
+
dao, method_sym, args = [os.dao,os.method_sym,os.args]
|
47
|
+
dao.send(method_sym,*args)
|
48
|
+
end
|
41
49
|
}.to change{ $redis.info["total_commands_processed"].to_i}.by(4)
|
42
50
|
end
|
43
51
|
|
@@ -46,4 +54,4 @@ describe Patriarch::DAOServices::TripartiteRelationshipBuilderService do
|
|
46
54
|
$redis.del "fallen_angel:#{fallen_angel.id}:patriarch_monsters_prasing_me_via_love_letters"
|
47
55
|
$redis.del "love_letter:#{fallen_angel.id}:patriarch_monsters_prasing_fallen_angels_via_me"
|
48
56
|
end
|
49
|
-
end
|
57
|
+
end
|
@@ -5,6 +5,8 @@ describe 'entities including Patriarch::Behaviours #destroy' do
|
|
5
5
|
before(:all) do
|
6
6
|
Monster.add_behaviour :lure, :by => [:fallenAngel]
|
7
7
|
FallenAngel.add_behaviour :lure, :on => [:monster]
|
8
|
+
FallenAngel.add_behaviour :lure, :by => [:fallenAngel]
|
9
|
+
FallenAngel.add_behaviour :lure, :on => [:fallenAngel]
|
8
10
|
Monster.add_behaviour :like, :on => [:fallenAngel]
|
9
11
|
FallenAngel.add_behaviour :like, :by => [:monster]
|
10
12
|
|
@@ -24,12 +26,65 @@ describe 'entities including Patriarch::Behaviours #destroy' do
|
|
24
26
|
f.lure m
|
25
27
|
m.like f
|
26
28
|
f.destroy
|
29
|
+
f.destroyed?.should be_true
|
27
30
|
f.monsters_i_lure.should be_empty
|
28
31
|
f.monsters_liking_me.should be_empty
|
29
32
|
m.fallen_angels_i_like.include?(f).should be_false
|
30
33
|
m.fallen_angels_luring_me.include?(f).should be_false
|
31
34
|
end
|
32
35
|
|
36
|
+
context "cascading style" do
|
37
|
+
# KIKOOOOOOOO Test for Skelz0r
|
38
|
+
before(:all) do
|
39
|
+
FallenAngel.class_eval do
|
40
|
+
before_destroy :destroy_fallen_angels_i_lure
|
41
|
+
def destroy_fallen_angels_i_lure
|
42
|
+
self.fallen_angels_i_lure.each do |lured_fallen_angel|
|
43
|
+
lured_fallen_angel.destroy
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it "cleans safely on top of the 'transitive' behaviour chain" do
|
50
|
+
f,fa,fal = [FallenAngel.create,FallenAngel.create,FallenAngel.create]
|
51
|
+
f.lure fa; fa.lure fal
|
52
|
+
|
53
|
+
f.destroy
|
54
|
+
|
55
|
+
f.fallen_angels_i_lure.should be_empty
|
56
|
+
fa.fallen_angels_i_lure.should be_empty
|
57
|
+
|
58
|
+
fa.destroyed?.should be_false
|
59
|
+
FallenAngel.where(:id => fa.id).should be_empty
|
60
|
+
|
61
|
+
fal.destroyed?.should be_false
|
62
|
+
FallenAngel.where(:id => fal.id).should be_empty
|
63
|
+
|
64
|
+
f.destroyed?.should be_true
|
65
|
+
FallenAngel.where(:id => f.id).should be_empty
|
66
|
+
end
|
67
|
+
|
68
|
+
it "cleans safely anywhere in the 'transitive' behaviour chain" do
|
69
|
+
f,fa,fal = [FallenAngel.create,FallenAngel.create,FallenAngel.create]
|
70
|
+
f.lure fa; fa.lure fal
|
71
|
+
|
72
|
+
fa.destroy
|
73
|
+
|
74
|
+
f.fallen_angels_i_lure.should be_empty
|
75
|
+
fa.fallen_angels_i_lure.should be_empty
|
76
|
+
|
77
|
+
fa.destroyed?.should be_true
|
78
|
+
FallenAngel.where(:id => fa.id).should be_empty
|
79
|
+
|
80
|
+
fal.destroyed?.should be_false
|
81
|
+
FallenAngel.where(:id => fa.id).should be_empty
|
82
|
+
|
83
|
+
f.destroyed?.should be_false
|
84
|
+
Array(FallenAngel.where(:id => f.id)).should == [f]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
33
88
|
context ' when another callback fails' do
|
34
89
|
|
35
90
|
# they do not trigger a rollback when they return false
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
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.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Hugo Lepetit
|
9
|
+
- Loïc Delmaire
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
+
date: 2013-02-09 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: verbs
|
@@ -127,11 +128,13 @@ description: Patriach is about adding behaviours on the fly to good old active r
|
|
127
128
|
models.
|
128
129
|
email:
|
129
130
|
- hugo@blackbid.co
|
131
|
+
- loic@blackbird.co
|
130
132
|
executables: []
|
131
133
|
extensions: []
|
132
134
|
extra_rdoc_files: []
|
133
135
|
files:
|
134
136
|
- .gitignore
|
137
|
+
- .travis.yml
|
135
138
|
- Gemfile
|
136
139
|
- LICENSE
|
137
140
|
- README.md
|