patriarch 0.0.1 → 0.0.2
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/lib/generators/patriarch/USAGE +8 -0
- data/lib/generators/patriarch/patriarch_generator.rb +69 -0
- data/lib/generators/patriarch/templates/after_manager_service.rb +6 -0
- data/lib/generators/patriarch/templates/after_service.rb +6 -0
- data/lib/generators/patriarch/templates/authorization_service.rb +6 -0
- data/lib/generators/patriarch/templates/before_manager_service.rb +6 -0
- data/lib/generators/patriarch/templates/before_service.rb +6 -0
- data/lib/generators/patriarch/templates/empty_behaviour_module.rb +2 -0
- data/lib/generators/patriarch/templates/manager_service.rb +29 -0
- data/lib/generators/patriarch/templates/service.rb +5 -0
- data/lib/generators/patriarch/templates/tools_methods.rb +3 -0
- data/lib/generators/patriarch/templates/undo_service.rb +5 -0
- data/lib/patriarch/authorization_service.rb +10 -0
- data/lib/patriarch/behaviours.rb +160 -0
- data/lib/patriarch/dao_services/.DAOinstancier.rb.swp +0 -0
- data/lib/patriarch/dao_services/bipartite_relationship_builder_service.rb +43 -0
- data/lib/patriarch/dao_services/redis_mapper_service.rb +41 -0
- data/lib/patriarch/dao_services/retriever_service.rb +51 -0
- data/lib/patriarch/manager_service.rb +15 -0
- data/lib/patriarch/service.rb +5 -0
- data/lib/patriarch/tool_services/redis_cleaner.rb +47 -0
- data/lib/patriarch/tool_services/redis_extractor_service.rb +37 -0
- data/lib/patriarch/transaction.rb +68 -0
- data/lib/patriarch/transaction_services/transaction_manager_service.rb +13 -0
- data/lib/patriarch/transaction_step.rb +39 -0
- data/lib/patriarch/version.rb +1 -1
- data/patriarch.gemspec +5 -2
- data/spec/lib/patriarch/add_behaviour_spec.rb +72 -0
- data/spec/lib/patriarch/bipartite_relationship_builder_spec.rb +51 -0
- data/spec/lib/patriarch/clean_reclip_spec.rb +31 -0
- data/spec/lib/patriarch/like_service_spec.rb +18 -0
- data/spec/lib/patriarch/reclip_spec.rb +39 -0
- data/spec/lib/patriarch/redis_mapper_service_spec.rb +20 -0
- data/spec/lib/patriarch/retriever_service_spec.rb +37 -0
- metadata +65 -4
@@ -0,0 +1,69 @@
|
|
1
|
+
class PatriarchGenerator < Rails::Generators::Base
|
2
|
+
source_root File.expand_path('../templates', __FILE__)
|
3
|
+
|
4
|
+
desc "Generate files needed to implement the BEHAVIOUR you specified. Don't forget to add declarations into models"
|
5
|
+
|
6
|
+
argument :behaviour, :type => :string
|
7
|
+
|
8
|
+
public
|
9
|
+
def init_directories
|
10
|
+
empty_directory "lib/patriarch/services/#{behaviour.underscore.downcase}"
|
11
|
+
empty_directory "lib/patriarch/services/#{undo(behaviour.underscore.downcase)}"
|
12
|
+
template "empty_behaviour_module.rb", "lib/patriarch/services/#{behaviour.underscore.downcase}.rb"
|
13
|
+
template "tools_methods.rb", "lib/patriarch/behaviours/#{behaviour.underscore.downcase}/tools_methods.rb"
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate_services
|
17
|
+
create_services(behaviour)
|
18
|
+
# implémenter un switch ici, plus zoli ...
|
19
|
+
self.class.send(:define_method,:class_name) do
|
20
|
+
undo(behaviour).classify
|
21
|
+
end
|
22
|
+
create_undo_services(behaviour)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def class_name
|
27
|
+
behaviour.classify
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_services(behaviour)
|
31
|
+
behaviour_str = behaviour.underscore.downcase
|
32
|
+
template "authorization_service.rb", "lib/patriarch/services/#{behaviour_str}/authorization_service.rb"
|
33
|
+
|
34
|
+
template "before_manager_service.rb", "lib/patriarch/services/#{behaviour_str}/before_manager_service.rb"
|
35
|
+
template "before_service.rb", "lib/patriarch/services/#{behaviour_str}/before_service.rb"
|
36
|
+
|
37
|
+
template "manager_service.rb", "lib/patriarch/services/#{behaviour_str}/manager_service.rb"
|
38
|
+
|
39
|
+
template "service.rb", "lib/patriarch/services/#{behaviour_str}/service.rb"
|
40
|
+
|
41
|
+
|
42
|
+
template "after_manager_service.rb", "lib/patriarch/services/#{behaviour_str}/after_manager_service.rb"
|
43
|
+
template "after_service.rb", "lib/patriarch/services/#{behaviour_str}/after_service.rb"
|
44
|
+
end
|
45
|
+
|
46
|
+
def create_undo_services(behaviour)
|
47
|
+
undo_behaviour_str = undo(behaviour).underscore.downcase
|
48
|
+
|
49
|
+
template "authorization_service.rb", "lib/patriarch/services/#{undo_behaviour_str}/authorization_service.rb"
|
50
|
+
|
51
|
+
template "before_manager_service.rb", "lib/patriarch/services/#{undo_behaviour_str}/before_manager_service.rb"
|
52
|
+
template "before_service.rb", "lib/patriarch/services/#{undo_behaviour_str}/before_service.rb"
|
53
|
+
|
54
|
+
template "manager_service.rb", "lib/patriarch/services/#{undo_behaviour_str}/manager_service.rb"
|
55
|
+
|
56
|
+
template "undo_service.rb", "lib/patriarch/services/#{undo_behaviour_str}/service.rb"
|
57
|
+
|
58
|
+
template "after_manager_service.rb", "lib/patriarch/services/#{undo_behaviour_str}/after_manager_service.rb"
|
59
|
+
template "after_service.rb", "lib/patriarch/services/#{undo_behaviour_str}/after_service.rb"
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def undo(str)
|
64
|
+
undo = "undo_"
|
65
|
+
undo << str
|
66
|
+
undo
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Patriarch::Services::<%= class_name %>::ManagerService < Patriarch::ManagerService
|
2
|
+
# Return true or false
|
3
|
+
def resolve(actor, target, transac = nil)
|
4
|
+
|
5
|
+
# On plante le "drapeau" transac_first_step pour signifier le début
|
6
|
+
if transac
|
7
|
+
transac_first_step = false
|
8
|
+
else
|
9
|
+
transac_first_step = true
|
10
|
+
end
|
11
|
+
|
12
|
+
transac ||= Patriarch::TransactionServices::TransactionManagerService.instance.new_transaction(:<%= class_name.underscore.to_sym %>)
|
13
|
+
# Do not listen Loïc anymore ... DO NOT MOVE, LikeAuthorizationService needs us to build
|
14
|
+
# a transaction step
|
15
|
+
transac.add_step(:<%= class_name.underscore.to_sym %>,actor,target)
|
16
|
+
|
17
|
+
callbacks_were_completed = false
|
18
|
+
|
19
|
+
if Patriarch::Services::<%= class_name %>::AuthorizationService.instance.grant?(transac)
|
20
|
+
Patriarch::Services::<%= class_name %>::Service.instance.call(transac)
|
21
|
+
if Patriarch::Services::<%= class_name %>::AfterManagerService.instance.resolve(transac)
|
22
|
+
callbacks_were_completed = true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Si tout s'est bien passé et que les callbacks ont été exécutés
|
27
|
+
transac.execute if (transac_first_step && callbacks_were_completed)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
#require 'patriarch/behaviours/own'
|
2
|
+
#require 'patriarch/behaviours/subscribe'
|
3
|
+
#require 'patriarch/behaviours/tagging'
|
4
|
+
#require 'patriarch/behaviours/join'
|
5
|
+
|
6
|
+
module Patriarch
|
7
|
+
module Behaviours
|
8
|
+
|
9
|
+
class AddBehaviourSyntaxError < Exception ; end
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
def complete_custom_active_module(module_to_complete,relation_type,acted_on_model_list)
|
14
|
+
module_to_complete.class_eval do
|
15
|
+
|
16
|
+
acted_on_model_list.each do |acted_on_model|
|
17
|
+
|
18
|
+
# Compute names based on conventions
|
19
|
+
classic_tool_method_name = "#{acted_on_model.to_s.tableize}_i_#{relation_type.to_s}"
|
20
|
+
raw_tool_method_name = classic_tool_method_name + "_ids"
|
21
|
+
redis_key = "patriarch_" + classic_tool_method_name
|
22
|
+
|
23
|
+
# Define methods with the pattern : items_i_like that returns models and items_i_like_ids that return
|
24
|
+
# Redis key has the same radical as the method in class by convention (but has a patriarch_ prefix to avoid collisions with other gems)
|
25
|
+
define_method(classic_tool_method_name) do |options={}|
|
26
|
+
Patriarch::ToolServices::RedisExtractorService.instance.
|
27
|
+
get_models_from_ids(self,acted_on_model.to_s.classify.constantize,raw_tool_method_name,options)
|
28
|
+
end
|
29
|
+
|
30
|
+
define_method(raw_tool_method_name) do |options={}|
|
31
|
+
Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def complete_custom_passive_module(module_to_complete,relation_type,targetted_by_model_list)
|
39
|
+
module_to_complete.class_eval do
|
40
|
+
|
41
|
+
targetted_by_model_list.each do |targetted_by_model|
|
42
|
+
|
43
|
+
# Compute names based on conventions
|
44
|
+
progressive_present_relation_type = (Verbs::Conjugator.conjugate relation_type.to_sym, :aspect => :progressive).split(/ /).last
|
45
|
+
classic_tool_method_name = "#{targetted_by_model.to_s.tableize}_#{progressive_present_relation_type}_me"
|
46
|
+
raw_tool_method_name = classic_tool_method_name + "_ids"
|
47
|
+
redis_key = "patriarch_" + classic_tool_method_name
|
48
|
+
|
49
|
+
# Define methods with the pattern : items_i_like that returns models and items_i_like_ids that return
|
50
|
+
# Redis key has the same radical as the method in class by convention (but has a patriarch_ prefix to avoid collisions with other gems)
|
51
|
+
define_method(classic_tool_method_name) do |options={}|
|
52
|
+
Patriarch::ToolServices::RedisExtractorService.instance.
|
53
|
+
get_models_from_ids(self,targetted_by_model.to_s.classify.constantize,raw_tool_method_name,options)
|
54
|
+
end
|
55
|
+
|
56
|
+
define_method(raw_tool_method_name) do |options={}|
|
57
|
+
Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def undo(str)
|
65
|
+
undo = "undo_"
|
66
|
+
undo << str
|
67
|
+
undo
|
68
|
+
end
|
69
|
+
|
70
|
+
def included(klass)
|
71
|
+
klass.extend ClassMethods
|
72
|
+
klass.extend ActiveModel::Callbacks
|
73
|
+
class << klass;
|
74
|
+
attr_accessor :patriarch_behaviours
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module ClassMethods
|
80
|
+
def add_behaviours(*behaviours)
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_behaviour(behaviour,options)
|
84
|
+
# add_behaviour :like, :by => bla, :on => [:item,:user] || :community, :as => :aimer, :reverse_as => :haïr ...
|
85
|
+
|
86
|
+
behaviour = behaviour.to_s.downcase
|
87
|
+
|
88
|
+
# Ou exclusif sur les options on et by
|
89
|
+
unless options[:by].nil? ^ options[:on].nil?
|
90
|
+
raise AddBehaviourSyntaxError, "you must not define a behaviour as active (using on) and passive at the same time (using by)"
|
91
|
+
end
|
92
|
+
|
93
|
+
methods_mod = Module.new do;
|
94
|
+
end
|
95
|
+
methods_mod.const_set(:Behaviour,behaviour)
|
96
|
+
|
97
|
+
if options[:on]
|
98
|
+
# Adds active methods and defines the hook to set callbacks on them
|
99
|
+
methods_mod.instance_eval do
|
100
|
+
|
101
|
+
# Defines the hook thing ...
|
102
|
+
# TODO
|
103
|
+
def self.included(klass)
|
104
|
+
klass.extend ActiveModel::Callbacks
|
105
|
+
klass.send(:define_model_callbacks, self.const_get(:Behaviour).to_sym, Patriarch::Behaviours.undo(self.const_get(:Behaviour)).to_sym)
|
106
|
+
end
|
107
|
+
|
108
|
+
# like
|
109
|
+
define_method(methods_mod.const_get(:Behaviour).to_sym) do |entity,options={}|
|
110
|
+
run_callbacks methods_mod.const_get(:Behaviour).to_sym do
|
111
|
+
"Patriarch::Services::#{methods_mod.const_get(:Behaviour).classify}::ManagerService".constantize.instance.resolve(self,entity)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# undo_like
|
116
|
+
define_method(Patriarch::Behaviours.undo(methods_mod.const_get(:Behaviour)).to_sym) do |entity,options={}|
|
117
|
+
run_callbacks Patriarch::Behaviours.undo(methods_mod.const_get(:Behaviour)).to_sym do
|
118
|
+
"Patriarch::Services::#{(Patriarch::Behaviours.undo(methods_mod.const_get(:Behaviour))).classify}::ManagerService".constantize.instance.resolve(self,entity)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# likes?
|
123
|
+
define_method((Verbs::Conjugator.conjugate methods_mod.const_get(:Behaviour).to_sym, :person => :third).split(/ /).last) do |entity|
|
124
|
+
self.send("#{entity.class.name.tableize}_i_#{methods_mod.const_get(:Behaviour)}_ids").include? entity.id
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
if options[:by]
|
130
|
+
methods_mod.instance_eval do
|
131
|
+
# reverse_of_likes?
|
132
|
+
# TODO find naming convention and build general ...
|
133
|
+
# define_method(:reverse_of_likes) do |entity|
|
134
|
+
# progressive_present_relation_type = (Verbs::Conjugator.conjugate methods_mod.const_get(:Behaviour).to_sym, :aspect => :progressive).split(/ /).last
|
135
|
+
# self.send("#{entity.class.name.tableize}_#{progressive_present_relation_type}_me_ids").include? entity.id
|
136
|
+
#end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
if options[:on]
|
141
|
+
acted_on_model_list = Array(options[:on])
|
142
|
+
Patriarch::Behaviours.complete_custom_active_module(methods_mod,behaviour,acted_on_model_list)
|
143
|
+
else
|
144
|
+
targetted_by_model_list = Array(options[:by])
|
145
|
+
Patriarch::Behaviours.complete_custom_passive_module(methods_mod,behaviour,targetted_by_model_list)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Finally ...
|
149
|
+
self.send(:include,methods_mod)
|
150
|
+
# include in which we can overwite the methods of the previous custom module included there ...
|
151
|
+
self.send(:include,"Patriarch::Behaviours::#{behaviour.classify}::ToolsMethods".constantize)
|
152
|
+
|
153
|
+
# register the behaviour we just added
|
154
|
+
self.patriarch_behaviours ||= []
|
155
|
+
self.patriarch_behaviours = self.patriarch_behaviours << behaviour.to_sym
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end # Behaviours
|
160
|
+
end # Patriarch
|
Binary file
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Patriarch::DAOServices::BipartiteRelationshipBuilderService < Patriarch::Service
|
2
|
+
def create(transaction_item)
|
3
|
+
# t => changer nom pour différencier de la date créée pour le Patriarch::Transaction
|
4
|
+
t = Time.now.to_f
|
5
|
+
dao_tab = Patriarch::DAOServices::RetrieverService.instance.call(transaction_item)
|
6
|
+
|
7
|
+
# Go hash plz
|
8
|
+
actor_dao = dao_tab[:actor]
|
9
|
+
target_dao = dao_tab[:target]
|
10
|
+
|
11
|
+
l = build_lambda_for_create(actor_dao,transaction_item.target_id,t)
|
12
|
+
ll = build_lambda_for_create(target_dao,transaction_item.actor_id,t)
|
13
|
+
|
14
|
+
# care about that, should be encapsulated into a beautiful add_to_queue method
|
15
|
+
transaction_item.add_to_queue l
|
16
|
+
transaction_item.add_to_queue ll
|
17
|
+
end
|
18
|
+
|
19
|
+
def destroy(transaction_item)
|
20
|
+
dao_tab = Patriarch::DAOServices::RetrieverService.instance.call(transaction_item)
|
21
|
+
|
22
|
+
# Go hash plz
|
23
|
+
actor_dao = dao_tab[:actor]
|
24
|
+
target_dao = dao_tab[:target]
|
25
|
+
|
26
|
+
l = lambda { actor_dao.delete transaction_item.target_id }
|
27
|
+
ll = lambda { target_dao.delete transaction_item.actor_id }
|
28
|
+
|
29
|
+
# care about that, should be encapsulated into a beautiful add_to_queue method
|
30
|
+
transaction_item.add_to_queue l
|
31
|
+
transaction_item.add_to_queue ll
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def build_lambda_for_create(dao,id,time)
|
37
|
+
if dao.is_a? Redis::SortedSet
|
38
|
+
return lambda { dao.add id, time }
|
39
|
+
else
|
40
|
+
return lambda { dao.add id }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Patriarch::DAOServices::RedisMapperService < Patriarch::Service
|
2
|
+
def call(transac,protagonist_type)
|
3
|
+
|
4
|
+
# Getting symbols here ...
|
5
|
+
relation_type = transac.relation_type
|
6
|
+
actor_type = transac.actor_type
|
7
|
+
target_type = transac.target_type
|
8
|
+
|
9
|
+
relation_type_str = sanitize_relation_type(relation_type.to_s)
|
10
|
+
|
11
|
+
if protagonist_type == :actor
|
12
|
+
redis_config_for_actor_on(target_type,relation_type_str)
|
13
|
+
else
|
14
|
+
redis_config_for_target_by(actor_type,relation_type_str)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def redis_config_for_actor_on(model_name,relation_type_str)
|
20
|
+
# example : items_i_like ...
|
21
|
+
{
|
22
|
+
:type => "sorted_set", :key => "patriarch_#{model_name.to_s.tableize}_i_#{relation_type_str}"
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def redis_config_for_target_by(model_name,relation_type_str)
|
27
|
+
# example : items_liking_me ...
|
28
|
+
{
|
29
|
+
:type => "sorted_set", :key => "patriarch_#{model_name.to_s.tableize}_#{progressive_present(relation_type_str)}_me"
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def progressive_present(behaviour_verb)
|
34
|
+
# like becomes => liking
|
35
|
+
(Verbs::Conjugator.conjugate behaviour_verb.to_sym, :aspect => :progressive).split(/ /).last
|
36
|
+
end
|
37
|
+
|
38
|
+
def sanitize_relation_type(relation_type)
|
39
|
+
relation_type.sub(/^undo_/,'')
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class InvalidRedisTypeException < Exception
|
2
|
+
end
|
3
|
+
|
4
|
+
class Patriarch::DAOServices::RetrieverService < Patriarch::Service
|
5
|
+
# go hash
|
6
|
+
def call(transaction_item)
|
7
|
+
result = {}
|
8
|
+
result[:actor] = instantiate_DAO_for_actor(transaction_item)
|
9
|
+
result[:target] = instantiate_DAO_for_target(transaction_item)
|
10
|
+
result
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def get_DAO_info_for_actor(transaction_item)
|
16
|
+
Patriarch::DAOServices::RedisMapperService.instance.call(transaction_item,:actor)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_DAO_info_for_target(transaction_item)
|
20
|
+
Patriarch::DAOServices::RedisMapperService.instance.call(transaction_item,:target)
|
21
|
+
end
|
22
|
+
|
23
|
+
def instantiate_DAO_for_actor(transaction_item)
|
24
|
+
dao_info = get_DAO_info_for_actor(transaction_item)
|
25
|
+
actor_id = transaction_item.actor_id
|
26
|
+
actor_type = transaction_item.actor_type
|
27
|
+
|
28
|
+
if Redis.constants.map(&:to_s).include?("#{dao_info[:type].camelize}")
|
29
|
+
redis_dao_class = "Redis::#{dao_info[:type].camelize}".constantize
|
30
|
+
else
|
31
|
+
raise InvalidRedisTypeException
|
32
|
+
end
|
33
|
+
|
34
|
+
redis_dao_class.new("#{actor_type}:#{actor_id}:#{dao_info[:key]}")
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def instantiate_DAO_for_target(transaction_item)
|
39
|
+
dao_info = get_DAO_info_for_target(transaction_item)
|
40
|
+
target_id = transaction_item.target_id
|
41
|
+
target_type = transaction_item.target_type
|
42
|
+
|
43
|
+
if Redis.constants.map(&:to_s).include?("#{dao_info[:type].camelize}")
|
44
|
+
redis_dao_class = "Redis::#{dao_info[:type].camelize}".constantize
|
45
|
+
else
|
46
|
+
raise InvalidRedisTypeException
|
47
|
+
end
|
48
|
+
redis_dao_class.new("#{target_type}:#{target_id}:#{dao_info[:key]}")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
# Interface avec les couches les plus hautes
|
4
|
+
class Patriarch::ManagerService
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
# /!\ Changer l'architecture ici, l'idée est là
|
8
|
+
#def resolve(*args, options={})
|
9
|
+
# Traitement des options
|
10
|
+
# ...
|
11
|
+
|
12
|
+
# Traitement normal
|
13
|
+
# after_resolve(*args)
|
14
|
+
#end
|
15
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Patriarch::ToolServices::RedisExtractorService < Patriarch::Service
|
2
|
+
def clean_reclip_id(reclip_id)
|
3
|
+
# Go get the hash of this reclip to clean depencies
|
4
|
+
reclip_hash = Redis::HashKey.new("reclip:#{reclip_id}")
|
5
|
+
|
6
|
+
# Clean dependencies on the recliped_on entity, the recliper entity and the reclipped item
|
7
|
+
|
8
|
+
recliped_on_sorted_set = Redis::SortedSet.new("#{reclip_hash['recliped_on_type'].downcase}:#{reclip_hash['recliped_on_id']}:redis_reclipeds_on_me")
|
9
|
+
recliper_sorted_set = Redis::SortedSet.new("#{reclip_hash['recliper_type'].downcase}:#{reclip_hash['recliper_id']}:redis_reclipeds_by_me")
|
10
|
+
item_reclip_ids_sorted_set = Redis::SortedSet.new("item:#{reclip_hash['recliped_item_id']}:redis_reclips_of_me")
|
11
|
+
|
12
|
+
$redis.multi do
|
13
|
+
recliped_on_sorted_set.delete reclip_id # recliped_on is cleaned
|
14
|
+
recliper_sorted_set.delete reclip_id # recliper is cleaned
|
15
|
+
reclip_hash.del # hash is deleted properly
|
16
|
+
item_reclip_ids_sorted_set.delete reclip_id # item_key is cleaned from this reclip_id
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def clean_reclip_for_item_before_delete(item)
|
21
|
+
item_reclip_ids = Redis::SortedSet.new("item:#{item.id}:redis_reclips_of_me")
|
22
|
+
|
23
|
+
# For each reclip involving our item
|
24
|
+
item_reclip_ids.members.each do |reclip_id|
|
25
|
+
clean_reclip_id(reclip_id)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def clean_reclip_for_group_before_delete(group)
|
30
|
+
# Goal here is to clean reclipeds_on_me dependencies and reclipeds_by_me before the group dies
|
31
|
+
|
32
|
+
# reclipeds_on_me
|
33
|
+
reclipeds_on_me_sorted_set = group.redis_reclipeds_on_me
|
34
|
+
|
35
|
+
reclipeds_on_me_sorted_set.members.each do |reclip_id|
|
36
|
+
clean_reclip_id(reclip_id)
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
# reclipeds_by_me
|
41
|
+
reclipeds_by_me_sorted_set = group.redis_reclipeds_by_me
|
42
|
+
|
43
|
+
reclipeds_by_me_sorted_set.members.each do |reclip_id|
|
44
|
+
clean_reclip_id(reclip_id)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Patriarch::ToolServices::RedisExtractorService < Patriarch::Service
|
2
|
+
def get_ids_from_sorted_set(calling_entity,redis_key,options={})
|
3
|
+
from = options[:from] || 0
|
4
|
+
limit = options[:limit] || :infinity
|
5
|
+
|
6
|
+
if limit == :infinity
|
7
|
+
to = -1
|
8
|
+
else
|
9
|
+
to = from + limit -1
|
10
|
+
end
|
11
|
+
|
12
|
+
dao = Redis::SortedSet.new("#{calling_entity.class.name.downcase}:#{calling_entity.id}:#{redis_key}")
|
13
|
+
|
14
|
+
if options[:with_scores]
|
15
|
+
# Do not use this anymore, go take the right redis objects not using this kind of methods ...
|
16
|
+
# DEGOLASSE
|
17
|
+
Redis::SortedSet.new
|
18
|
+
ids_with_scores_from_redis = dao.revrange(from,to,:with_scores => true) || []
|
19
|
+
ids_with_scores_from_redis.map{ |id,score| [id.to_i,score] }
|
20
|
+
else
|
21
|
+
ids_from_redis = dao.revrange(from,to) || []
|
22
|
+
ids_from_redis.map &:to_i
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_models_from_ids(calling_entity,model,get_id_method,options={})
|
27
|
+
if options[:with_scores]
|
28
|
+
ids_with_scores_from_redis = calling_entity.send(get_id_method,options)
|
29
|
+
ids_with_scores_from_redis.map! do |id,score|
|
30
|
+
[model.find(id),score]
|
31
|
+
end
|
32
|
+
else
|
33
|
+
ids_from_redis = calling_entity.send(get_id_method,options)
|
34
|
+
model.find(ids_from_redis)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class Patriarch::Transaction
|
2
|
+
attr_reader :id, :steps, :current_step_number
|
3
|
+
attr_reader :type
|
4
|
+
|
5
|
+
forwarded_methods_syms = [:relation_type,:actor_type,:target_type,:actor_id,:target_id,
|
6
|
+
:context,:actor,:target]
|
7
|
+
|
8
|
+
# Forward methods that are not this transaction's job to step object
|
9
|
+
forwarded_methods_syms.each do |method_sym|
|
10
|
+
define_method(method_sym) do
|
11
|
+
current_step.send(method_sym)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
# id => go $redis.incr
|
17
|
+
def initialize(type,id) #relation_type,actor,target,
|
18
|
+
@type = type
|
19
|
+
@id = id
|
20
|
+
@steps = []
|
21
|
+
@current_step_number = 0
|
22
|
+
end
|
23
|
+
|
24
|
+
# Initializes a new step and stores it in the steps array right away
|
25
|
+
# A step matches a "like", "follow", "own", etc.
|
26
|
+
# Register that we went a step further into the transaction processus
|
27
|
+
# Medium is nil by default (bipartite transactions does not require more than target/actor)
|
28
|
+
def add_step(relation_type,actor,target,medium=nil)
|
29
|
+
# Initializes a new step and stores it in the steps array right away
|
30
|
+
new_step = Patriarch::TransactionStep.new(relation_type,actor,target,medium)
|
31
|
+
|
32
|
+
# if initilization failed we should not move forward ...
|
33
|
+
raise PatriarchTransactionStepInstanciationException unless new_step
|
34
|
+
|
35
|
+
# Register that we went a step further into the transaction processus
|
36
|
+
@steps << new_step
|
37
|
+
@current_step_number += 1
|
38
|
+
end
|
39
|
+
|
40
|
+
# Executes the calls to redis in one block here.
|
41
|
+
def execute
|
42
|
+
$redis.multi do
|
43
|
+
steps.each do |step|
|
44
|
+
step.execute
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def transaction_queue
|
50
|
+
transaction_queue = []
|
51
|
+
steps.each do |step|
|
52
|
+
transaction_queue.concat(step.queue)
|
53
|
+
end
|
54
|
+
transaction_queue
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_to_queue(proc)
|
58
|
+
current_step.add_to_queue(proc)
|
59
|
+
end
|
60
|
+
|
61
|
+
alias :queue :transaction_queue
|
62
|
+
|
63
|
+
protected
|
64
|
+
|
65
|
+
def current_step
|
66
|
+
steps[current_step_number-1]
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
class PatriarchTransactionStepInstanciationException < Exception
|
4
|
+
end
|
5
|
+
|
6
|
+
class Patriarch::TransactionServices::TransactionManagerService < Patriarch::ManagerService
|
7
|
+
# Fill with logic to manage ressources with transactions ...
|
8
|
+
# Can registers transactions and so on ...
|
9
|
+
def new_transaction(type)
|
10
|
+
id = Time.now.to_f
|
11
|
+
Patriarch::Transaction.new(type,id)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class Patriarch::TransactionStep
|
2
|
+
attr_accessor :context, :queue
|
3
|
+
|
4
|
+
def initialize(relation_type,actor,target,medium)
|
5
|
+
@context = {
|
6
|
+
:relation_type => relation_type,
|
7
|
+
:actor_type => actor.class.name.underscore.to_sym,
|
8
|
+
:target_type => target.class.name.underscore.to_sym,
|
9
|
+
:actor_id => actor.id,
|
10
|
+
:target_id => target.id,
|
11
|
+
}
|
12
|
+
@queue = []
|
13
|
+
end
|
14
|
+
|
15
|
+
# defines access methods to context fields letting it be encapsulated nicely
|
16
|
+
[:relation_type,:actor_type,:target_type,:actor_id,:target_id].each do |context_key|
|
17
|
+
define_method(context_key) do
|
18
|
+
context[context_key]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def actor
|
23
|
+
actor_type.to_s.camelize.constantize.find actor_id
|
24
|
+
end
|
25
|
+
|
26
|
+
def target
|
27
|
+
target_type.to_s.camelize.constantize.find target_id
|
28
|
+
end
|
29
|
+
|
30
|
+
def execute
|
31
|
+
queue.each do |redis_instruction|
|
32
|
+
redis_instruction.call
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_to_queue(proc)
|
37
|
+
queue << proc
|
38
|
+
end
|
39
|
+
end
|
data/lib/patriarch/version.rb
CHANGED
data/patriarch.gemspec
CHANGED
@@ -6,12 +6,15 @@ Gem::Specification.new do |spec|
|
|
6
6
|
spec.email = ["hugo@blackbid.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
|
-
spec.homepage = "https://github.com/
|
9
|
+
spec.homepage = "https://github.com/giglemad/patriarch"
|
10
10
|
|
11
11
|
spec.platform = Gem::Platform::RUBY
|
12
12
|
spec.licenses = ['MIT']
|
13
|
+
|
14
|
+
spec.add_development_dependency "rspec"
|
15
|
+
spec.add_runtime_dependency "redis-objects"
|
13
16
|
|
14
|
-
|
17
|
+
spec.files = `git ls-files`.split($\)
|
15
18
|
spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
16
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
20
|
spec.name = "patriarch"
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe Patriarch::Behaviours do
|
5
|
+
|
6
|
+
# setup with empty fake klasses here
|
7
|
+
|
8
|
+
class ModelClass;
|
9
|
+
include Patriarch::Behaviours
|
10
|
+
end
|
11
|
+
|
12
|
+
class ModelKlass;
|
13
|
+
include Patriarch::Behaviours
|
14
|
+
end
|
15
|
+
|
16
|
+
ModelClass.add_behaviour :like, :on => [:modelKlass]
|
17
|
+
ModelKlass.add_behaviour :like, :by => [:modelClass]
|
18
|
+
|
19
|
+
|
20
|
+
context "when adding a behaviour" do
|
21
|
+
it "should implement basic tool methods" do
|
22
|
+
progressive_like = (Verbs::Conjugator.conjugate :like, :aspect => :progressive).split(/ /).last
|
23
|
+
ModelClass.new.should respond_to("#{"model_klass".pluralize}_i_like")
|
24
|
+
ModelClass.new.should respond_to("#{"model_klass".pluralize}_i_like_ids")
|
25
|
+
ModelKlass.new.should respond_to("#{"model_class".pluralize}_#{progressive_like}_me")
|
26
|
+
ModelKlass.new.should respond_to("#{"model_class".pluralize}_#{progressive_like}_me_ids")
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should implement actions only on model being added behaviours with ':on' options" do
|
30
|
+
mc = ModelClass.new
|
31
|
+
mk = ModelKlass.new
|
32
|
+
mc.should respond_to(:like)
|
33
|
+
mc.should respond_to(:undo_like)
|
34
|
+
mk.should_not respond_to(:like)
|
35
|
+
mk.should_not respond_to(:undo_like)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when using an added behaviour" do
|
40
|
+
User.add_behaviour :smoke, :on => [:User]
|
41
|
+
User.add_behaviour :smoke, :by => [:User]
|
42
|
+
|
43
|
+
before(:all) do
|
44
|
+
@userA = create_user
|
45
|
+
@userB = create_user
|
46
|
+
@userA.smoke @userB
|
47
|
+
end
|
48
|
+
|
49
|
+
it "shall play the transaction nicely" do
|
50
|
+
@userA.users_i_smoke.should == [@userB]
|
51
|
+
@userB.users_smoking_me.should == [@userA]
|
52
|
+
|
53
|
+
@userA.users_i_smoke_ids.should == [@userB.id]
|
54
|
+
@userB.users_smoking_me_ids.should == [@userA.id]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "shall play reverse transaction nicely" do
|
58
|
+
@userA.undo_smoke @userB
|
59
|
+
@userA.users_i_smoke.include?(@userB).should be_false
|
60
|
+
@userB.users_smoking_me.include?(@userA).should be_false
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
# @userA.users_i_smoke_ids.should be_empty
|
65
|
+
#@userB.users_smoking_me_ids.should be_empty
|
66
|
+
end
|
67
|
+
|
68
|
+
after(:all) do
|
69
|
+
@userA.undo_smoke @userB
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Patriarch::DAOServices::BipartiteRelationshipBuilderService do
|
4
|
+
before(:each) do
|
5
|
+
@instance = Patriarch::DAOServices::BipartiteRelationshipBuilderService.instance
|
6
|
+
@user = create_user
|
7
|
+
@item = create_item(@user)
|
8
|
+
@transac ||= Patriarch::TransactionServices::TransactionManagerService.instance.new_transaction(:like)
|
9
|
+
@transac.add_step(:like,@user,@item)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "shall insert processable lambdas into queues when create is called" do
|
13
|
+
# Stubs the DAO retriever service so it gives DAO arrays back
|
14
|
+
dao_sample = {
|
15
|
+
:actor => Redis::SortedSet.new("user:1:redis_likes"),
|
16
|
+
:target => Redis::Set.new("item:1:redis_liker_users")
|
17
|
+
}
|
18
|
+
Patriarch::DAOServices::RetrieverService.instance.stub(:call).with(any_args()).and_return(dao_sample)
|
19
|
+
|
20
|
+
expect{
|
21
|
+
@instance.create(@transac)
|
22
|
+
}.to change{ @transac.transaction_queue.select{ |queue_element| queue_element.is_a? Proc}.size }.by(2)
|
23
|
+
|
24
|
+
expect{
|
25
|
+
@transac.transaction_queue.each{ |proc| proc.call }
|
26
|
+
}.to change{ $redis.keys.size}.by(2)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "shall insert processable lambdas into queues when destroy is called" do
|
30
|
+
# Stubs the DAO retriever service so it gives DAO arrays back
|
31
|
+
dao_sample = {
|
32
|
+
:actor => Redis::SortedSet.new("user:1:redis_likes"),
|
33
|
+
:target => Redis::Set.new("item:1:redis_liker_users")
|
34
|
+
}
|
35
|
+
Patriarch::DAOServices::RetrieverService.instance.stub(:call).with(any_args()).and_return(dao_sample)
|
36
|
+
|
37
|
+
|
38
|
+
expect{
|
39
|
+
@instance.destroy(@transac)
|
40
|
+
}.to change{ @transac.transaction_queue.select{ |queue_element| queue_element.is_a? Proc}.size }.by(2)
|
41
|
+
|
42
|
+
expect{
|
43
|
+
@transac.transaction_queue.each{ |proc| proc.call }
|
44
|
+
}.to change{ $redis.info["total_commands_processed"].to_i}.by(3)
|
45
|
+
end
|
46
|
+
|
47
|
+
after(:each) do
|
48
|
+
$redis.del "user:#{@user.id}:redis_likes"
|
49
|
+
$redis.del "item:#{@item.id}:redis_liker_users"
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "reclip cleaner" do
|
4
|
+
before (:each) do
|
5
|
+
@recliper_user = create_user
|
6
|
+
@item = create_item(create_user)
|
7
|
+
@recliped_on_user = create_user
|
8
|
+
@recliper_user.reclip(@item,@recliped_on_user)
|
9
|
+
@reclip_id = @item.reclips_of_me_reclips_ids.first
|
10
|
+
end
|
11
|
+
|
12
|
+
it "shall clean reclips everywhere when given a single item" do
|
13
|
+
Patriarch::Behaviours::Reclip.clean_reclip_id(@reclip_id)
|
14
|
+
|
15
|
+
@recliped_on_user.reclipeds_on_me_reclips_ids.include?(@reclip_id).should be_false
|
16
|
+
@recliper_user.reclipeds_by_me_reclips_ids.include?(@reclip_id).should be_false
|
17
|
+
@item.reclips_of_me_reclips_ids.include?(@reclip_id).should be_false
|
18
|
+
end
|
19
|
+
|
20
|
+
it "shall clean all the reclip stuff (on him, by him) of a given user properly" do
|
21
|
+
pending('like the test above but in the adequate loop')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "shall clean all the reclip stuff (on him, by him) of a given group properly" do
|
25
|
+
pending('like the test above but in the adequate loop')
|
26
|
+
end
|
27
|
+
|
28
|
+
it "shall clean all the reclip stuff of a given item properly" do
|
29
|
+
pending('like the test above but in the adequate loop')
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Patriarch::Services do
|
4
|
+
before (:each) do
|
5
|
+
@user = create_user
|
6
|
+
@item = create_item(@user)
|
7
|
+
end
|
8
|
+
|
9
|
+
context "LikeService" do
|
10
|
+
it "should register like informations properly" do
|
11
|
+
# Wrong way of doing tests, test should not know about what's inside ...
|
12
|
+
Patriarch::Services::Like::ManagerService.instance.resolve(@user,@item)
|
13
|
+
Redis::SortedSet.new("user:#{@user.id}:redis_likes").members.include?(@item.id.to_s).should be_true
|
14
|
+
Redis::SortedSet.new("item:#{@item.id}:redis_liker_users").members.include?(@user.id.to_s).should be_true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "reclip" do
|
4
|
+
before (:each) do
|
5
|
+
@recliper_user = create_user
|
6
|
+
@item = create_item(create_user)
|
7
|
+
@recliped_on_user = create_user
|
8
|
+
end
|
9
|
+
|
10
|
+
it "stores informations in redis properly" do
|
11
|
+
@recliper_user.reclip(@item,@recliped_on_user)
|
12
|
+
|
13
|
+
# Guy being recliped on remembers it
|
14
|
+
@recliped_on_user.reclipeds_on_me.should == [@item]
|
15
|
+
# Recliper remembers the reclip it did
|
16
|
+
@recliper_user.reclipeds_by_me.should == [@item]
|
17
|
+
|
18
|
+
# Item
|
19
|
+
@recliper_user.reclipeds_by_me.should have(1).reclip_hash
|
20
|
+
end
|
21
|
+
|
22
|
+
it "only updates information when clipped twice" do
|
23
|
+
@recliper_user.reclip(@item,@recliped_on_user)
|
24
|
+
old_time = @recliper_user.reclipeds_by_me(:with_scores => true).first[1]
|
25
|
+
@recliper_user.reclip(@item,@recliped_on_user)
|
26
|
+
new_time = @recliper_user.reclipeds_by_me(:with_scores => true).first[1]
|
27
|
+
|
28
|
+
new_time.should_not eq(old_time)
|
29
|
+
|
30
|
+
# Guy being recliped on remembers it
|
31
|
+
@recliped_on_user.reclipeds_on_me.should == [@item]
|
32
|
+
# Recliper remembers the reclip it did
|
33
|
+
@recliper_user.reclipeds_by_me.should == [@item]
|
34
|
+
|
35
|
+
# Item
|
36
|
+
@recliper_user.reclipeds_by_me.should have(1).reclip_hash
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Patriarch::DAOServices::RedisMapperService do
|
4
|
+
before(:each) do
|
5
|
+
@instance = Patriarch::DAOServices::RedisMapperService.instance
|
6
|
+
@context = {:relation_type => :like, :actor_type => :user, :target_type => :item,
|
7
|
+
:actor_id => 1, :target_id => 1}
|
8
|
+
@transaction_item = double()
|
9
|
+
@transaction_item.stub(:context).and_return(@context)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "shall retrieve right DAO information" do
|
13
|
+
@instance.call(@transaction_item,:actor).should eq({:type => "sorted_set", :key => "redis_likes"})
|
14
|
+
@instance.call(@transaction_item,:target).should eq({:type => "sorted_set", :key => "redis_liker_users"})
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Patriarch::DAOServices::RetrieverService do
|
4
|
+
before(:each) do
|
5
|
+
@instance = Patriarch::DAOServices::RetrieverService.instance
|
6
|
+
@context = {:relation_type => :like, :actor_type => :user, :target_type => :item,
|
7
|
+
:actor_id => 1, :target_id => 1}
|
8
|
+
@transaction_item = double()
|
9
|
+
@transaction_item.stub(:actor_id).and_return(@context[:actor_id])
|
10
|
+
@transaction_item.stub(:actor_type).and_return(@context[:actor_type])
|
11
|
+
@transaction_item.stub(:target_type).and_return(@context[:target_type])
|
12
|
+
@transaction_item.stub(:target_id).and_return(@context[:target_id])
|
13
|
+
end
|
14
|
+
|
15
|
+
it "shall return nice Redis::Object instances" do
|
16
|
+
Patriarch::DAOServices::RedisMapperService.instance.should_receive(:call).twice.with(any_args()).and_return({:type => "sorted_set", :key =>"abc"})
|
17
|
+
dao_tab = @instance.call(@transaction_item)
|
18
|
+
|
19
|
+
dao_tab[:actor].key.should == "user:1:abc"
|
20
|
+
dao_tab[:actor].is_a?(Redis::SortedSet).should be_true
|
21
|
+
|
22
|
+
dao_tab[:target].key.should == "item:1:abc"
|
23
|
+
dao_tab[:target].is_a?(Redis::SortedSet).should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
it "shall reject types that are not suited" do
|
28
|
+
Patriarch::DAOServices::RedisMapperService.instance.should_receive(:call).with(any_args()).and_return({:type => "sorted", :key =>"abc"})
|
29
|
+
expect{
|
30
|
+
@instance.call(@transaction_item)
|
31
|
+
}.to raise_error(InvalidRedisTypeException)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
|
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.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,29 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
date: 2012-11-25 00:00:00.000000000 Z
|
13
|
-
dependencies:
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &23131200 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *23131200
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: redis-objects
|
27
|
+
requirement: &23130660 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *23130660
|
14
36
|
description: Patriach is about adding behaviours on the fly to good old active record
|
15
37
|
models.
|
16
38
|
email:
|
@@ -24,10 +46,42 @@ files:
|
|
24
46
|
- LICENSE
|
25
47
|
- README.md
|
26
48
|
- Rakefile
|
49
|
+
- lib/generators/patriarch/USAGE
|
50
|
+
- lib/generators/patriarch/patriarch_generator.rb
|
51
|
+
- lib/generators/patriarch/templates/after_manager_service.rb
|
52
|
+
- lib/generators/patriarch/templates/after_service.rb
|
53
|
+
- lib/generators/patriarch/templates/authorization_service.rb
|
54
|
+
- lib/generators/patriarch/templates/before_manager_service.rb
|
55
|
+
- lib/generators/patriarch/templates/before_service.rb
|
56
|
+
- lib/generators/patriarch/templates/empty_behaviour_module.rb
|
57
|
+
- lib/generators/patriarch/templates/manager_service.rb
|
58
|
+
- lib/generators/patriarch/templates/service.rb
|
59
|
+
- lib/generators/patriarch/templates/tools_methods.rb
|
60
|
+
- lib/generators/patriarch/templates/undo_service.rb
|
27
61
|
- lib/patriarch.rb
|
62
|
+
- lib/patriarch/authorization_service.rb
|
63
|
+
- lib/patriarch/behaviours.rb
|
64
|
+
- lib/patriarch/dao_services/.DAOinstancier.rb.swp
|
65
|
+
- lib/patriarch/dao_services/bipartite_relationship_builder_service.rb
|
66
|
+
- lib/patriarch/dao_services/redis_mapper_service.rb
|
67
|
+
- lib/patriarch/dao_services/retriever_service.rb
|
68
|
+
- lib/patriarch/manager_service.rb
|
69
|
+
- lib/patriarch/service.rb
|
70
|
+
- lib/patriarch/tool_services/redis_cleaner.rb
|
71
|
+
- lib/patriarch/tool_services/redis_extractor_service.rb
|
72
|
+
- lib/patriarch/transaction.rb
|
73
|
+
- lib/patriarch/transaction_services/transaction_manager_service.rb
|
74
|
+
- lib/patriarch/transaction_step.rb
|
28
75
|
- lib/patriarch/version.rb
|
29
76
|
- patriarch.gemspec
|
30
|
-
|
77
|
+
- spec/lib/patriarch/add_behaviour_spec.rb
|
78
|
+
- spec/lib/patriarch/bipartite_relationship_builder_spec.rb
|
79
|
+
- spec/lib/patriarch/clean_reclip_spec.rb
|
80
|
+
- spec/lib/patriarch/like_service_spec.rb
|
81
|
+
- spec/lib/patriarch/reclip_spec.rb
|
82
|
+
- spec/lib/patriarch/redis_mapper_service_spec.rb
|
83
|
+
- spec/lib/patriarch/retriever_service_spec.rb
|
84
|
+
homepage: https://github.com/giglemad/patriarch
|
31
85
|
licenses:
|
32
86
|
- MIT
|
33
87
|
post_install_message:
|
@@ -52,4 +106,11 @@ rubygems_version: 1.8.10
|
|
52
106
|
signing_key:
|
53
107
|
specification_version: 3
|
54
108
|
summary: Manage relationships between instances of your models easily
|
55
|
-
test_files:
|
109
|
+
test_files:
|
110
|
+
- spec/lib/patriarch/add_behaviour_spec.rb
|
111
|
+
- spec/lib/patriarch/bipartite_relationship_builder_spec.rb
|
112
|
+
- spec/lib/patriarch/clean_reclip_spec.rb
|
113
|
+
- spec/lib/patriarch/like_service_spec.rb
|
114
|
+
- spec/lib/patriarch/reclip_spec.rb
|
115
|
+
- spec/lib/patriarch/redis_mapper_service_spec.rb
|
116
|
+
- spec/lib/patriarch/retriever_service_spec.rb
|