holywarez-mpt 0.1.3

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/CHANGELOG ADDED
@@ -0,0 +1,4 @@
1
+ v0.1.3 Wrap helpers support added
2
+ v0.1.2 Instance eval with arguments is now supported for any object
3
+ v0.1.1 Sample sources updated
4
+ v0.1.0 First version of MPT gem
data/LICENSE ADDED
File without changes
data/Manifest ADDED
@@ -0,0 +1,18 @@
1
+ CHANGELOG
2
+ install_gem.bat
3
+ lib/event.rb
4
+ lib/mpt.rb
5
+ lib/system.rb
6
+ lib/wrap.rb
7
+ LICENSE
8
+ Manifest
9
+ mpt.gemspec
10
+ Rakefile
11
+ README
12
+ run_samples.bat
13
+ samples/call_experiment.rb
14
+ samples/declarations.rb
15
+ samples/ordered_subscribers.rb
16
+ samples/run_experiments.rb
17
+ samples/unordered_subscribers.rb
18
+ samples/wrap_method_experiment.rb
data/README ADDED
@@ -0,0 +1,2 @@
1
+ = Russian =
2
+ Примеры использования либы можно посмотреть в директории 'samples'
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "echoe"
2
+ Echoe.new( "mpt" ) do |p|
3
+ p.author = "Anatoly Lapshin"
4
+ p.summary = "Monkey Patching Toolkit"
5
+ p.runtime_dependencies = ['activesupport']
6
+ p.development_dependencies = []
7
+ p.need_tar_gz = false
8
+ p.retain_gemspec = true
9
+ p.gemspec_name = 'mpt.gemspec'
10
+ p.clean_pattern.push 'lib/*-*'
11
+ end
data/install_gem.bat ADDED
@@ -0,0 +1,5 @@
1
+ call rake manifest
2
+ call rake install
3
+ cd pkg
4
+ call gem install holywarez-mpt-0.1.3.gem
5
+ cd ..
data/lib/event.rb ADDED
@@ -0,0 +1,69 @@
1
+
2
+ module MPT
3
+ class EventContainer
4
+ attr_accessor :event_object
5
+
6
+ def initialize( val = nil )
7
+ self.event_object = val.dup unless val.nil?
8
+ end
9
+
10
+ end
11
+
12
+ class FilterChain < Array
13
+ def reorganize
14
+ index = 0
15
+ while index < self.size
16
+ filter = self[index]
17
+ filter_opts = filter[:options]
18
+ unless filter_opts[:after].nil?
19
+ for i in index..self.size-1
20
+ fo = self[i][:options]
21
+ unless fo[:as].nil?
22
+ if fo[:as] == filter_opts[:after]
23
+ new_chain = []
24
+ new_chain += self[0..index-1] if index > 0
25
+ new_chain += [self[i]]
26
+ new_chain += self[index..i-1]
27
+ new_chain += self[i+1..self.size-1]
28
+ self.replace new_chain
29
+ index = 0
30
+ break
31
+ end # if :as matched with :after
32
+ end # unless :as is nil
33
+ end # for next items
34
+ end # unless :after is nil
35
+ index += 1
36
+ end # while index < list size
37
+ end # def reorganize
38
+ end # filter chain class
39
+
40
+ class Event
41
+ @@mpt_subscribers = {}
42
+
43
+ class << self
44
+ def subscribe(event_name, options = {}, &block)
45
+ channel = @@mpt_subscribers[event_name] ||= MPT::FilterChain.new
46
+ channel << { :options => options, :proc => block }
47
+ channel.reorganize
48
+ end
49
+
50
+ def trigger_with_object(event_name, object, *args)
51
+ container = MPT::EventContainer.new(object)
52
+ channel = @@mpt_subscribers[event_name]
53
+ if channel.size > 0
54
+
55
+ channel.each do |subscriber|
56
+ container.instance_eval_with_args( subscriber[:proc], *args )
57
+ end
58
+ end
59
+
60
+ container.event_object
61
+ end
62
+
63
+ def trigger(event_name, *args)
64
+ trigger_with_object(event_name, nil, *args)
65
+ end
66
+ end # end of static section
67
+ end # end of class Event
68
+
69
+ end
data/lib/mpt.rb ADDED
@@ -0,0 +1,11 @@
1
+ require "rubygems"
2
+
3
+ gem "activesupport"
4
+ require "activesupport"
5
+
6
+ gem "uuid"
7
+ require "uuid"
8
+
9
+ require "system.rb"
10
+ require "wrap.rb"
11
+ require "event.rb"
data/lib/system.rb ADDED
@@ -0,0 +1,10 @@
1
+
2
+ class Object
3
+ def instance_eval_with_args(proc, *args, &block)
4
+ mod = @mpt_injection_module ||= Module.new
5
+ self.extend mod
6
+ mod.send :define_method, :mpt_instance_with_args_handler, proc
7
+ self.mpt_instance_with_args_handler( *args, &block )
8
+ mod.send :undef_method, :mpt_instance_with_args_handler
9
+ end
10
+ end
data/lib/wrap.rb ADDED
@@ -0,0 +1,140 @@
1
+
2
+ module MPT
3
+ class Wrap
4
+ @@wrap_variables = {}
5
+ @@registry = {}
6
+ class << self
7
+ def with(var ={}, &block)
8
+ thread_id = Thread.current.object_id
9
+ @@wrap_variables[thread_id]||={}
10
+ temp = @@wrap_variables[thread_id].dup
11
+ @@wrap_variables[thread_id].merge!(var)
12
+ yield
13
+ @@wrap_variables[thread_id] = temp
14
+ end
15
+
16
+ def get(wrap_name, default = nil)
17
+ temp = @@wrap_variables[Thread.current.object_id]
18
+ res = nil
19
+
20
+
21
+ if !temp.blank?
22
+ res = temp[wrap_name] unless temp[wrap_name].blank?
23
+ end
24
+
25
+ if res.nil? && !default.nil?
26
+ res = default
27
+ if default.instance_of?( Proc )
28
+ res = default.call
29
+ end
30
+ end
31
+
32
+ res
33
+ end
34
+
35
+ def register(value)
36
+ @@uuid_generator ||= UUID.new
37
+ key = @@uuid_generator.generate(:urn).to_s
38
+ @@registry[key] = value
39
+ key
40
+ end
41
+
42
+ def get_from_registry(key)
43
+ @@registry[key]
44
+ end
45
+ end
46
+
47
+ class Blank
48
+ def self.run(*args)
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ class Class
55
+ def wrap_it(target, options = { :using => :run, :scope => :before }, &block)
56
+ return if options[:by].nil? && block.nil?
57
+
58
+ targets = target
59
+ targets = [target] unless target.instance_of?( Array )
60
+ targets.each do |tgt|
61
+ wrap_it_single(tgt, options, &block)
62
+ end
63
+ end
64
+
65
+ def wrap_with(target, options = {})
66
+ return if options.blank?
67
+
68
+ targets = target
69
+ targets = [target] unless target.instance_of?( Array )
70
+ targets.each do |tgt|
71
+ wrap_with_single(tgt, options)
72
+ end
73
+ end
74
+
75
+ private
76
+ def wrap_it_single(target, options, &block)
77
+ by_name = options[:by]
78
+ old_method_name = "#{target.to_s}_without_wrap_it"
79
+
80
+ instance_to_call_code = "self"
81
+ unless by_name == :self
82
+ instance_to_call_code = "MPT::Wrap.get( #{by_name.inspect}, MPT::Wrap::Blank )"
83
+ end
84
+
85
+ if by_name.nil? && !block.nil?
86
+ block_key = MPT::Wrap.register(block)
87
+ instance_to_call_code = "self.instance_eval( &MPT::Wrap.get_from_registry(#{block_key.inspect}) )"
88
+ end
89
+
90
+ scope_call_code = "target_instance.#{options[:using]}(*args, &block); #{old_method_name}(*args, &block)"
91
+
92
+ if options[:scope] == :after
93
+ scope_call_code = "#{old_method_name}(*args, &block); target_instance.#{options[:using]}(*args, &block)"
94
+ end
95
+
96
+ if options[:scope] == :around
97
+ scope_call_code = "target_instance.#{options[:using]}(*args) { #{old_method_name}(*args, &block) }"
98
+ end
99
+
100
+ code_to_eval = <<-EOC
101
+ def #{target.to_s}_with_wrap_it(*args, &block)
102
+ target_instance = #{instance_to_call_code}
103
+ #{scope_call_code}
104
+ end
105
+
106
+ alias_method_chain #{target.to_sym.inspect}, :wrap_it
107
+ EOC
108
+
109
+ self.class_eval(code_to_eval, __FILE__, __LINE__)
110
+ end
111
+
112
+ def wrap_with_single(target, options)
113
+ key = MPT::Wrap.register(options.dup)
114
+ code = <<-EOC
115
+ def #{target.to_s}_with_wrap_options(*args)
116
+ MPT::Wrap.with MPT::Wrap.get_from_registry(#{key.inspect}) do
117
+ #{target.to_s}_without_wrap_options(*args)
118
+ end
119
+ end
120
+
121
+ alias_method_chain #{target.to_sym.inspect}, :wrap_options
122
+ EOC
123
+
124
+ self.class_eval(code, __FILE__, __LINE__)
125
+ end
126
+ end
127
+
128
+ class Class
129
+ def wrappable(accessor_name, wrap_name)
130
+ code = <<-EOS
131
+ def #{accessor_name.to_s}_with_wrap_support
132
+ MPT::Wrap.get("#{wrap_name}", Proc.new { self.send :"#{accessor_name.to_s}_without_wrap_support" })
133
+ end
134
+
135
+ alias_method_chain :#{accessor_name.to_s}, :wrap_support
136
+ EOS
137
+
138
+ class_eval(code, __FILE__, __LINE__)
139
+ end
140
+ end
data/mpt.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{mpt}
5
+ s.version = "0.1.3"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Anatoly Lapshin"]
9
+ s.date = %q{2009-07-01}
10
+ s.description = %q{Monkey Patching Toolkit}
11
+ s.email = %q{}
12
+ s.extra_rdoc_files = ["CHANGELOG", "lib/event.rb", "lib/mpt.rb", "lib/system.rb", "lib/wrap.rb", "LICENSE", "README"]
13
+ s.files = ["CHANGELOG", "install_gem.bat", "lib/event.rb", "lib/mpt.rb", "lib/system.rb", "lib/wrap.rb", "LICENSE", "Manifest", "mpt.gemspec", "Rakefile", "README", "run_samples.bat", "samples/call_experiment.rb", "samples/declarations.rb", "samples/ordered_subscribers.rb", "samples/run_experiments.rb", "samples/unordered_subscribers.rb", "samples/wrap_method_experiment.rb"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{}
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Mpt", "--main", "README"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{mpt}
19
+ s.rubygems_version = %q{1.3.2}
20
+ s.summary = %q{Monkey Patching Toolkit}
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
28
+ else
29
+ s.add_dependency(%q<activesupport>, [">= 0"])
30
+ end
31
+ else
32
+ s.add_dependency(%q<activesupport>, [">= 0"])
33
+ end
34
+ end
data/run_samples.bat ADDED
@@ -0,0 +1,3 @@
1
+ cd samples
2
+ call ruby run_experiments.rb
3
+ cd ..
@@ -0,0 +1,15 @@
1
+ module CallExperiment
2
+ include ::MPT
3
+ experiment "Call experiment" do
4
+ controller = Controller.new
5
+ controller.logic # must be 4
6
+
7
+ Wrap.with '/system/services/logic-service' => CustomService.new do
8
+ controller.logic # must be 96
9
+ Wrap.with '/system/services/logic-service' => CustomService.new(999) do
10
+ controller.logic # must be 1998
11
+ end
12
+ controller.logic # must be 96 again
13
+ end
14
+ end # end of experiment
15
+ end
@@ -0,0 +1,41 @@
1
+ module Kernel
2
+
3
+ def experiment(title)
4
+ en = @@experiment_number ||= 1
5
+ puts "Experiment ##{en}. #{title}\n\n"
6
+
7
+ yield
8
+
9
+ puts "\nExperiment ##{en} FINISHED!\n\n\n\n"
10
+ @@experiment_number += 1
11
+ end
12
+
13
+ end
14
+
15
+ class GeneralService
16
+ def calculate(input)
17
+ input * input
18
+ end
19
+ end
20
+
21
+ class CustomService < GeneralService
22
+ def initialize(rate = 48)
23
+ @rate = rate
24
+ end
25
+
26
+ def calculate(input)
27
+ input * @rate
28
+ end
29
+ end
30
+
31
+ class Controller
32
+ def service
33
+ @service ||= GeneralService.new
34
+ end
35
+
36
+ def logic
37
+ puts "Logic result is: #{service.calculate(2)}"
38
+ end
39
+
40
+ wrappable :service, '/system/services/logic-service'
41
+ end
@@ -0,0 +1,34 @@
1
+ module OrderedSubscribersExperiment
2
+ include ::MPT
3
+
4
+ experiment "Ordered filter chain with event object" do
5
+ input_object = { :content => "This scintillating new production of Shakespeare's romantic comedy is one of the most accomplished Shakespeare in the Park productions in some time." }
6
+
7
+ Event.subscribe '/filters/count-words', :as => :remove_unimportant_characters do
8
+ event_object[:content].gsub!( /[\!\.\,\?\:\=\-]|('s)/, '' )
9
+ end
10
+
11
+ Event.subscribe '/filters/count-words' do
12
+ # empty filter handler
13
+ end
14
+
15
+ Event.subscribe '/filters/count-words', :as => :word_counter, :after => :normalizer do
16
+ word_counts = {}
17
+ words = event_object[:content].split
18
+ words.each do |word|
19
+ word_counts[word] ||= 0
20
+ word_counts[word] += 1
21
+ end
22
+
23
+ event_object[:counts] = word_counts
24
+ end
25
+
26
+ Event.subscribe '/filters/count-words', :as => :normalizer, :after => :remove_unimportant_characters do
27
+ event_object[:content].downcase!
28
+ end
29
+
30
+ result_object = Event.trigger_with_object '/filters/count-words', input_object
31
+
32
+ puts "Result is:\n#{result_object[:counts].inspect}"
33
+ end
34
+ end
@@ -0,0 +1,11 @@
1
+ require "rubygems"
2
+
3
+ gem "holywarez-mpt"
4
+ require "mpt"
5
+
6
+
7
+ require "declarations.rb"
8
+ require "call_experiment.rb"
9
+ require "unordered_subscribers.rb"
10
+ require "ordered_subscribers.rb"
11
+ require "wrap_method_experiment.rb"
@@ -0,0 +1,16 @@
1
+ module UnorderedSubscribersExperiment
2
+ include ::MPT
3
+
4
+ experiment "Unordered subscribers with void event object" do
5
+ Event.subscribe '/system/special-channel' do |parameter|
6
+ self.event_object = parameter
7
+ end
8
+
9
+ Event.subscribe '/system/special-channel' do |parameter|
10
+ self.event_object = "#{event_object} AND same shit"
11
+ end
12
+
13
+ result = Event.trigger '/system/special-channel', "XXX"
14
+ puts "Result is: #{result}"
15
+ end
16
+ end
@@ -0,0 +1,78 @@
1
+
2
+ module WrapMethodsExperiment
3
+ include ::MPT
4
+
5
+ class TargetORM
6
+ def initialize(name = 'default')
7
+ @name = 'default'
8
+ end
9
+
10
+ def execute(sql)
11
+ puts "#{@name} execute '#{sql}'"
12
+ end
13
+
14
+ def query(sql)
15
+ puts "#{@name} query '#{sql}'"
16
+ end
17
+
18
+ def transaction
19
+ puts "TRANSACTION BEGIN"
20
+ yield
21
+ puts "TRANSACTION COMMIT"
22
+ end
23
+ end
24
+
25
+ class TargetController
26
+ attr_reader :orm
27
+ wrappable :orm, '/system/orm'
28
+
29
+ def initialize(system_orm)
30
+ @orm = system_orm
31
+ end
32
+
33
+ def process
34
+ orm.execute( "ControllerSQL" )
35
+ end
36
+ end
37
+
38
+ class TargetDispatcher
39
+ def initialize
40
+ @orm = TargetORM.new
41
+ end
42
+
43
+ def process
44
+ @orm.query("dispatcher-sql")
45
+
46
+ controller = TargetController.new(@orm)
47
+ controller.process
48
+ end
49
+ end
50
+
51
+ class MonkeyPatch
52
+ def run(sql)
53
+ puts "Patcher run: '#{sql}'"
54
+ end
55
+ end
56
+
57
+ experiment "Wrap methods experiment" do
58
+ TargetORM.wrap_it [:execute, :query], :by => '/patches/monkey-patch', :using => :run, :scope => :before
59
+
60
+ orm = TargetORM.new
61
+ orm.execute "First SQL"
62
+
63
+ patch = MonkeyPatch.new
64
+ Wrap.with '/patches/monkey-patch' => patch do
65
+ orm.execute "Second SQL"
66
+ end
67
+
68
+ end
69
+
70
+ experiment "Wrap by around methods" do
71
+ TargetDispatcher.wrap_it( :process, :using => :transaction, :scope => :around ) { @orm }
72
+ TargetController.wrap_with :process, '/system/orm' => TargetORM.new('custom')
73
+
74
+ dispatcher = TargetDispatcher.new
75
+ dispatcher.process
76
+ end
77
+
78
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: holywarez-mpt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Anatoly Lapshin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-01 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: Monkey Patching Toolkit
26
+ email: ""
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - CHANGELOG
33
+ - lib/event.rb
34
+ - lib/mpt.rb
35
+ - lib/system.rb
36
+ - lib/wrap.rb
37
+ - LICENSE
38
+ - README
39
+ files:
40
+ - CHANGELOG
41
+ - install_gem.bat
42
+ - lib/event.rb
43
+ - lib/mpt.rb
44
+ - lib/system.rb
45
+ - lib/wrap.rb
46
+ - LICENSE
47
+ - Manifest
48
+ - mpt.gemspec
49
+ - Rakefile
50
+ - README
51
+ - run_samples.bat
52
+ - samples/call_experiment.rb
53
+ - samples/declarations.rb
54
+ - samples/ordered_subscribers.rb
55
+ - samples/run_experiments.rb
56
+ - samples/unordered_subscribers.rb
57
+ - samples/wrap_method_experiment.rb
58
+ has_rdoc: true
59
+ homepage: ""
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --line-numbers
63
+ - --inline-source
64
+ - --title
65
+ - Mpt
66
+ - --main
67
+ - README
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "1.2"
81
+ version:
82
+ requirements: []
83
+
84
+ rubyforge_project: mpt
85
+ rubygems_version: 1.2.0
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: Monkey Patching Toolkit
89
+ test_files: []
90
+