Module: Patriarch::Behaviours

Defined in:
lib/patriarch/behaviours.rb,
lib/generators/patriarch/templates/empty_behaviours_declaration.rb

Overview

Patriarch::Behaviours is meant to be included into any class we want to enhance with Patriarch handled behaviours Thus it defines the included hook so we enhance the class in which it is included freely and add to it some class methods defined into Patriarch::Behaviours::ClassMethods We define there the add_behaviour method that does three things :

  • it generates an anonymous module containing tool methods defined ad-hoc in function of the arguments supplied

  • it includes another module that lives into a generated file in lib/ allowing us to override existing methods or add new ones if we wish

  • it defines instance methods for the class allowing instances to call behaviour actions

Defined Under Namespace

Modules: ClassMethods Classes: AddBehaviourDependencyError, AddBehaviourSyntaxError

Class Method Summary collapse

Class Method Details

.complete_custom_active_module_bipartite(anon_module, behaviour, acted_on_model_list, options = {}) ⇒ Object

Helper function to complete the anonymous module we include later in the process in the enhanced model class

Parameters:

  • anon_module (Module)

    refers to the anonymous module to be completed

  • behaviour (String)

    the behaviour for which we complete the module with tools method

  • acted_on_model_list (Array)

    the list of model classes that i can target with the behaviour

  • options (Hash) (defaults to: {})

    options can serve to build custom alias for tool methods



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/patriarch/behaviours.rb', line 27

def complete_custom_active_module_bipartite(anon_module,behaviour,acted_on_model_list,options={})
  anon_module.class_eval do

    acted_on_model_list.each do |acted_on_model|

      # Compute names based on conventions
      classic_tool_method_name = "#{acted_on_model.to_s.tableize}_i_#{behaviour}"
      raw_tool_method_name = classic_tool_method_name + "_ids"
      redis_key = "patriarch_" + classic_tool_method_name

      # Define methods with the pattern : items_i_like that returns models and items_i_like_ids that return
      # Redis key has the same radical as the method in class by convention (but has a patriarch_ prefix to avoid collisions with other gems)
      define_method(classic_tool_method_name) do |options={}|
        Patriarch::ToolServices::RedisExtractorService.instance.
          get_models_from_ids(self,acted_on_model.to_s.classify.constantize,raw_tool_method_name,options)
      end
      if options[:as]
        alias_for_classic = classic_tool_method_name.sub(behaviour, options[:as].to_s)
        alias_method alias_for_classic, classic_tool_method_name
      end

      define_method(raw_tool_method_name) do |options={}|
        Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options)
      end
      if options[:as]
        alias_for_raw = raw_tool_method_name.sub(behaviour, options[:as].to_s)
        alias_method alias_for_raw, raw_tool_method_name
      end
    end
  end
end

.complete_custom_active_module_tripartite(anon_module, behaviour, acted_on_model_list, via_model_list, options = {}) ⇒ Object

Helper function to complete the anonymous module we include later in the process in the enhanced model class

Parameters:

  • anon_module (Module)

    refers to the anonymous module to be completed

  • behaviour (String)

    the behaviour for which we complete the module with tools method

  • acted_on_model_list (Array)

    the list of model classes that i can target with the behaviour

  • via_model_list (Array)

    the list of model classes that the behaviour use to act through

  • options (Hash) (defaults to: {})

    options can serve to build custom alias for tool methods



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/patriarch/behaviours.rb', line 108

def complete_custom_active_module_tripartite(anon_module,behaviour,acted_on_model_list,via_model_list,options={})
  anon_module.class_eval do

    acted_on_model_list.each do |acted_on_model|
      via_model_list.each do |via_model|

        # Compute names based on conventions
        # fallen_angels_i_praise_via_love_letters
        target_classic_tool_method_name = "#{acted_on_model.to_s.tableize}_i_#{behaviour}_via_#{via_model.to_s.tableize}"
        target_raw_tool_method_name = target_classic_tool_method_name + "_ids"

        # love_letters_i_use_to_praise_fallen_angels
        medium_classic_tool_method_name = "#{via_model.to_s.tableize}_i_use_to_#{behaviour}_#{acted_on_model.to_s.tableize}"
        medium_raw_tool_method_name = medium_classic_tool_method_name + "_ids"

        redis_key = "patriarch_" + target_classic_tool_method_name

        # Define methods with the pattern : items_i_like that returns models and items_i_like_ids that return
        # Redis key has the same radical as the method in class by convention (but has a patriarch_ prefix to avoid collisions with other gems)
        define_method(target_classic_tool_method_name) do |options={}|
          Patriarch::ToolServices::RedisExtractorService.instance.
            get_models_from_ids(self,acted_on_model.to_s.classify.constantize,target_raw_tool_method_name,options.merge({:tripartite => true}))
        end
        if options[:as]
          alias_for_classic = target_classic_tool_method_name.sub(behaviour, options[:as].to_s)
          alias_method alias_for_classic, target_classic_tool_method_name
        end

        define_method(target_raw_tool_method_name) do |options={}|
          Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options.merge({:tripartite => true, :protagonist_type  => :target}))
        end
        if options[:as]
          alias_for_target_raw = target_raw_tool_method_name.sub(behaviour, options[:as].to_s)
          alias_method alias_for_target_raw, target_raw_tool_method_name
        end

        #
        define_method(medium_classic_tool_method_name) do |options={}|
          Patriarch::ToolServices::RedisExtractorService.instance.
            get_models_from_ids(self,via_model.to_s.classify.constantize,medium_raw_tool_method_name,options.merge({:tripartite => true}))
        end
        if options[:as]
          alias_for_medium_classic = medium_classic_tool_method_name.sub(behaviour, options[:as].to_s)
          alias_method alias_for_medium_classic, medium_classic_tool_method_name
        end
        #

        define_method(medium_raw_tool_method_name) do |options={}|
          Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options.merge({:tripartite => true, :protagonist_type  => :medium}))
        end
        if options[:as]
          alias_for_medium_raw = medium_raw_tool_method_name.sub(behaviour, options[:as].to_s)
          alias_method alias_for_medium_raw, medium_raw_tool_method_name
        end

      end
    end

  end
end

.complete_custom_passive_module_bipartite(anon_module, behaviour, targeted_by_model_list, options = {}) ⇒ Object

Parameters:

  • anon_module (Module)

    refers to the anonymous module to be completed

  • behaviour (String)

    the behaviour for which we complete the module with tools method

  • targeted_by_model_list (Array)

    the list of model classes that can target me with the behaviour

  • options (Hash) (defaults to: {})

    options can serve to build custom alias for tool methods



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/patriarch/behaviours.rb', line 65

def complete_custom_passive_module_bipartite(anon_module,behaviour,targeted_by_model_list,options={})
  anon_module.class_eval do

    targeted_by_model_list.each do |targeted_by_model|

      # Compute names based on conventions
      progressive_present_relation_type = (Verbs::Conjugator.conjugate behaviour.to_sym, :aspect => :progressive).split(/ /).last
      classic_tool_method_name = "#{targeted_by_model.to_s.tableize}_#{progressive_present_relation_type}_me"
      raw_tool_method_name = classic_tool_method_name + "_ids"
      redis_key = "patriarch_" + classic_tool_method_name

      # Define methods with the pattern : items_i_like that returns models and items_i_like_ids that return
      # Redis key has the same radical as the method in class by convention (but has a patriarch_ prefix to avoid collisions with other gems)
      define_method(classic_tool_method_name) do |options={}|
        Patriarch::ToolServices::RedisExtractorService.instance.
          get_models_from_ids(self,targeted_by_model.to_s.classify.constantize,raw_tool_method_name,options)
      end
      if options[:as]
        progressive_present_relation_type_alias = (Verbs::Conjugator.conjugate options[:as], :aspect => :progressive).split(/ /).last
        alias_for_classic = classic_tool_method_name.sub(progressive_present_relation_type,progressive_present_relation_type_alias)
        alias_method alias_for_classic,  classic_tool_method_name
      end

      define_method(raw_tool_method_name) do |options={}|
        Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options)
      end
      if options[:as]
        progressive_present_relation_type_alias = (Verbs::Conjugator.conjugate options[:as], :aspect => :progressive).split(/ /).last
        alias_for_raw = raw_tool_method_name.sub(progressive_present_relation_type,progressive_present_relation_type_alias)
        alias_method alias_for_raw,  raw_tool_method_name
      end

    end

  end
end

.complete_custom_passive_module_tripartite(anon_module, behaviour, targeted_by_model_list, via_model_list, options = {}) ⇒ Object

Helper function to complete the anonymous module we include later in the process in the enhanced model class

Parameters:

  • anon_module (Module)

    refers to the anonymous module to be completed

  • behaviour (String)

    the behaviour for which we complete the module with tools method

  • targeted_by_model_list (Array)

    the list of model classes that can target me with the behaviour

  • via_model_list (Array)

    the list of model classes that the behaviour use to act through

  • options (Hash) (defaults to: {})

    options can serve to build custom alias for tool methods



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/patriarch/behaviours.rb', line 175

def complete_custom_passive_module_tripartite(anon_module,behaviour,targeted_by_model_list,via_model_list,options={})
  anon_module.class_eval do

    targeted_by_model_list.each do |targeted_by_model|
      via_model_list.each do |via_model|
        # Compute names based on conventions
        progressive_present_relation_type = (Verbs::Conjugator.conjugate behaviour.to_sym, :aspect => :progressive).split(/ /).last

        actor_classic_tool_method_name  = "#{targeted_by_model.to_s.tableize}_#{progressive_present_relation_type}_me_via_#{via_model.to_s.tableize}"
        actor_raw_tool_method_name      = actor_classic_tool_method_name + "_ids"

        #"love_letters_used_by_monsters_to_praise_me"
        medium_classic_tool_method_name = "#{via_model.to_s.tableize}_used_by_#{targeted_by_model.to_s.tableize}_to_#{behaviour}_me"
        medium_raw_tool_method_name     = medium_classic_tool_method_name + "_ids"

        redis_key = "patriarch_" + actor_classic_tool_method_name

        define_method(actor_classic_tool_method_name) do |options={}|
          Patriarch::ToolServices::RedisExtractorService.instance.
            get_models_from_ids(self,targeted_by_model.to_s.classify.constantize,actor_raw_tool_method_name,options.merge({:tripartite => true}))
        end
        if options[:as]
          progressive_present_relation_type_alias = (Verbs::Conjugator.conjugate options[:as], :aspect => :progressive).split(/ /).last
          alias_for_actor_classic = actor_classic_tool_method_name.sub(progressive_present_relation_type,progressive_present_relation_type_alias)
          alias_method alias_for_actor_classic,  actor_classic_tool_method_name
        end

        define_method(actor_raw_tool_method_name) do |options={}|
          Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options.merge({:tripartite => true , :protagonist_type  => :actor}))
        end
        if options[:as]
          progressive_present_relation_type_alias = (Verbs::Conjugator.conjugate options[:as], :aspect => :progressive).split(/ /).last
          alias_for_actor_raw = actor_raw_tool_method_name.sub(progressive_present_relation_type,progressive_present_relation_type_alias)
          alias_method alias_for_actor_raw,  actor_raw_tool_method_name
        end

        define_method(medium_classic_tool_method_name) do |options={}|
          Patriarch::ToolServices::RedisExtractorService.instance.
            get_models_from_ids(self,via_model.to_s.classify.constantize,medium_raw_tool_method_name,options.merge({:tripartite => true}))
        end
        #TODO add alias there
        # FIXME id in it is wrong ...
        define_method(medium_raw_tool_method_name) do |options={}|
          Patriarch::ToolServices::RedisExtractorService.instance.get_ids_from_sorted_set(self,redis_key,options.merge({:tripartite => true , :protagonist_type  => :medium}))
        end

      end
    end

  end
end

.included(klass) ⇒ Object

:nodoc:



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/patriarch/behaviours.rb', line 228

def included(klass)
  # Classic extend of ClassMethods module embedded within this module
  klass.extend ClassMethods
  unless klass.respond_to?(:before_destroy) && klass.respond_to?(:after_destroy)
    raise AddBehaviourDependencyError, "class #{klass.name} including Patriarch::Behaviours does not support callbacks"
  end

  # insert callback logic here : behaviours have to be cleaned when a destroy occur in SQL
  # First we build the transaction with #compute_redis_dependencies
  # We execute the clean only when the SQL transaction commit to avoid data inconsistency if a SQL Rollback occurs
  # in a middle of a cascading transaction
  klass.class_eval do

    before_destroy :compute_redis_dependencies
    def compute_redis_dependencies
      @redis_destroy_transac_object = Patriarch::ToolServices::RedisCleanerService.instance.clean_all(self)
    end

    after_commit  :clean_redis_dependencies
    def clean_redis_dependencies
      unless @redis_destroy_transac_object.nil?
        @redis_destroy_transac_object.execute
      end
      @redis_destroy_transac_object = nil
    end

    after_rollback :clean_redis_transac_object
    def clean_redis_transac_object
      @redis_destroy_transac_object = nil
    end

  end

  class << klass;
    # not sure if should add an alias like behaviours here
    # might override other behaviour methods from other namespaces
    # but patriarch is damn heavy here
    attr_accessor :patriarch_behaviours
  end
end