inheritance_module_eval 0.0.1 → 1.0.0
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 +7 -0
- data/README.md +65 -0
- data/Rakefile +3 -0
- data/inheritance_module_eval.gemspec +1 -0
- data/lib/inheritance_module_eval/version.rb +1 -1
- data/lib/inheritance_module_eval.rb +32 -1
- data/spec/inheritance_spec.rb +199 -0
- metadata +17 -3
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -7,6 +7,71 @@ Installation
|
|
7
7
|
------------
|
8
8
|
gem inheritance_module_eval
|
9
9
|
|
10
|
+
Usage
|
11
|
+
-----
|
12
|
+
There are 2 methods:
|
13
|
+
|
14
|
+
* instance_module_eval
|
15
|
+
* class_module_eval
|
16
|
+
|
17
|
+
instance_module_eval method used to eval instance methods (ie: methods of an object)
|
18
|
+
|
19
|
+
class_module_eval method used to eval class methods (ie: methods of an class)
|
20
|
+
|
21
|
+
|
22
|
+
Below is some simple example of inheritance_module_eval usage:
|
23
|
+
|
24
|
+
require 'inheritance_module_eval'
|
25
|
+
|
26
|
+
# Some dummy class that uses #instance_module_eval
|
27
|
+
class Content
|
28
|
+
self.field(name)
|
29
|
+
instance_module_eval %{
|
30
|
+
def #{name}
|
31
|
+
instance_valiable_get(@#{name})
|
32
|
+
end
|
33
|
+
|
34
|
+
def #{name}=(new_value)
|
35
|
+
instance_valiable_set(@#{name}, new_value)
|
36
|
+
end
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
class Article < Content
|
44
|
+
field :title
|
45
|
+
field :content
|
46
|
+
field :etc
|
47
|
+
|
48
|
+
# you can use inheritance!
|
49
|
+
# you dont need to call alias_method anymore!
|
50
|
+
# make it simple
|
51
|
+
def title
|
52
|
+
super.to_s.titelize
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
Requirements
|
57
|
+
------------
|
58
|
+
none
|
59
|
+
|
60
|
+
rspec2 for testing
|
61
|
+
|
62
|
+
Compatibility
|
63
|
+
-------------
|
64
|
+
tested with Ruby
|
65
|
+
|
66
|
+
* 1.8.7 # (current default)
|
67
|
+
* 1.9.2
|
68
|
+
* 1.9.3
|
69
|
+
* jruby
|
70
|
+
* ruby-head
|
71
|
+
* ree
|
72
|
+
|
73
|
+
see [build history](http://travis-ci.org/#!/AlexParamonov/inheritance_module_eval/builds)
|
74
|
+
|
10
75
|
Copyright
|
11
76
|
---------
|
12
77
|
Copyright © 2011 Alexander N Paramonov. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -21,5 +21,6 @@ Allows to redefine dynamic method in the same class or in any child class, and c
|
|
21
21
|
|
22
22
|
# specify any dependencies here; for example:
|
23
23
|
s.add_development_dependency "rspec", ">= 2.6"
|
24
|
+
s.add_development_dependency "rake"
|
24
25
|
# s.add_runtime_dependency "rest-client"
|
25
26
|
end
|
@@ -1,5 +1,36 @@
|
|
1
1
|
require "inheritance_module_eval/version"
|
2
2
|
|
3
|
+
class Module
|
4
|
+
# acts same as module_eval, but saves method hierarchy
|
5
|
+
# should be called only for instance methods evaluation
|
6
|
+
# @params (see Module#module_eval)
|
7
|
+
def instance_module_eval(code = nil, &block)
|
8
|
+
InheritanceModuleEval.instance_eval_on self, code, &block
|
9
|
+
end
|
10
|
+
|
11
|
+
# acts same as module_eval, but saves method hierarchy
|
12
|
+
# should be called only for class methods evaluation
|
13
|
+
# @params (see Module#module_eval)
|
14
|
+
def class_module_eval(code = nil, &block)
|
15
|
+
InheritanceModuleEval.class_eval_on self, code, &block
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
3
19
|
module InheritanceModuleEval
|
4
|
-
|
20
|
+
def self.instance_eval_on(sender, code, &block)
|
21
|
+
sender.send :include, (get_module_for code, &block)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.class_eval_on(sender, code, &block)
|
25
|
+
sender.send :extend, (get_module_for code, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def self.get_module_for(code, &block)
|
30
|
+
raise ArgumentError, "Empty code given" if (code.nil? or code.empty?) and not block_given?
|
31
|
+
include_module = Module.new
|
32
|
+
if code.nil? then include_module.module_eval &block else include_module.module_eval code end
|
33
|
+
|
34
|
+
include_module
|
35
|
+
end
|
5
36
|
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
require "inheritance_module_eval"
|
2
|
+
|
3
|
+
class Parent
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
class Child < Parent
|
8
|
+
|
9
|
+
end
|
10
|
+
describe InheritanceModuleEval do
|
11
|
+
describe "integration" do
|
12
|
+
specify "class should respond to instance_module_eval" do
|
13
|
+
Class.new.should respond_to(:instance_module_eval)
|
14
|
+
end
|
15
|
+
|
16
|
+
specify "module should respond to instance_module_eval" do
|
17
|
+
Module.new.should respond_to(:instance_module_eval)
|
18
|
+
end
|
19
|
+
|
20
|
+
specify "class should respond to class_module_eval" do
|
21
|
+
Class.new.should respond_to(:class_module_eval)
|
22
|
+
end
|
23
|
+
|
24
|
+
specify "module should respond to class_module_eval" do
|
25
|
+
Module.new.should respond_to(:class_module_eval)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "add dynamic methods" do
|
30
|
+
before(:each) do
|
31
|
+
@test_object = Class.new
|
32
|
+
end
|
33
|
+
|
34
|
+
pending "should delegate to module_eval" do
|
35
|
+
Module.should_receive(:module_eval).twice
|
36
|
+
@test_object.instance_module_eval %{
|
37
|
+
def say_hi
|
38
|
+
puts hi
|
39
|
+
end
|
40
|
+
}
|
41
|
+
@test_object.class_module_eval %{
|
42
|
+
def say_hi
|
43
|
+
puts hi
|
44
|
+
end
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "instance methods" do
|
49
|
+
it "should eval a string" do
|
50
|
+
@test_object.instance_module_eval %{
|
51
|
+
def say_hi
|
52
|
+
puts 'hi'
|
53
|
+
end
|
54
|
+
}
|
55
|
+
@test_object.new.should respond_to :say_hi
|
56
|
+
|
57
|
+
end
|
58
|
+
it "should eval a block" do
|
59
|
+
@test_object.instance_module_eval do
|
60
|
+
def say_hi
|
61
|
+
puts 'hi'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
@test_object.new.should respond_to :say_hi
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "class_methods" do
|
69
|
+
it "should eval a string" do
|
70
|
+
@test_object.class_module_eval %{
|
71
|
+
def say_hi
|
72
|
+
puts 'hi'
|
73
|
+
end
|
74
|
+
}
|
75
|
+
@test_object.should respond_to :say_hi
|
76
|
+
|
77
|
+
end
|
78
|
+
it "should eval a block" do
|
79
|
+
@test_object.class_module_eval do
|
80
|
+
def say_hi
|
81
|
+
puts 'hi'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
@test_object.should respond_to :say_hi
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
describe "collisions" do
|
90
|
+
describe "define already defined method in a class" do
|
91
|
+
describe "redefine it after class declaration" do
|
92
|
+
it "should has lower priority then method, declared in a class" do
|
93
|
+
klass = Class.new
|
94
|
+
klass.class_eval do
|
95
|
+
def say_hi
|
96
|
+
"hi from method" << " " << super
|
97
|
+
end
|
98
|
+
instance_module_eval %{
|
99
|
+
def say_hi
|
100
|
+
"hi from eval"
|
101
|
+
end
|
102
|
+
}
|
103
|
+
end
|
104
|
+
klass.new.say_hi.should == "hi from method hi from eval"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "redefine it before class declaration" do
|
109
|
+
it "should push dynamic method up in the inheritance tree" do
|
110
|
+
klass = Class.new
|
111
|
+
klass.class_eval do
|
112
|
+
instance_module_eval %{
|
113
|
+
def say_hi
|
114
|
+
"tiny hi"
|
115
|
+
end
|
116
|
+
}
|
117
|
+
def say_hi
|
118
|
+
super.upcase
|
119
|
+
end
|
120
|
+
end
|
121
|
+
klass.new.say_hi.should == "TINY HI"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "redefine as much as you want" do
|
126
|
+
it "should push dynamic method up in the inheritance tree" do
|
127
|
+
klass = Class.new
|
128
|
+
klass.class_eval do
|
129
|
+
instance_module_eval %{
|
130
|
+
def say_hi
|
131
|
+
[5]
|
132
|
+
end
|
133
|
+
}
|
134
|
+
instance_module_eval %{
|
135
|
+
def say_hi
|
136
|
+
[4] + super
|
137
|
+
end
|
138
|
+
}
|
139
|
+
instance_module_eval %{
|
140
|
+
def say_hi
|
141
|
+
[3] + super
|
142
|
+
end
|
143
|
+
}
|
144
|
+
instance_module_eval %{
|
145
|
+
def say_hi
|
146
|
+
[2] + super
|
147
|
+
end
|
148
|
+
}
|
149
|
+
def say_hi
|
150
|
+
[1] + super
|
151
|
+
end
|
152
|
+
end
|
153
|
+
klass.new.say_hi.should == [1, 2, 3, 4, 5]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe "redefine it inside a module" do
|
158
|
+
it "should push dynamic method before module and after class declaration" do
|
159
|
+
test_module = Module.new
|
160
|
+
test_module.module_eval do
|
161
|
+
def say_hi
|
162
|
+
["hi from module"]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
klass = Class.new
|
167
|
+
klass.class_eval do
|
168
|
+
include test_module
|
169
|
+
instance_module_eval do
|
170
|
+
def say_hi
|
171
|
+
["hi from eval"] + super
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def say_hi
|
176
|
+
["hi from method"] + super
|
177
|
+
end
|
178
|
+
end
|
179
|
+
klass.new.say_hi.should == ["hi from method", "hi from eval", "hi from module"]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
describe "#get_module_for" do
|
187
|
+
it "should return Module" do
|
188
|
+
InheritanceModuleEval.send :get_module_for, "puts('hi')"
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should raise ArgumentError if no code given" do
|
192
|
+
["", nil, []].each do |empty|
|
193
|
+
expect{InheritanceModuleEval.send :get_module_for, empty}.to raise_error ArgumentError
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inheritance_module_eval
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2011-11-12 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &10342840 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,18 @@ dependencies:
|
|
21
21
|
version: '2.6'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *10342840
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &10342420 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *10342420
|
25
36
|
description: ! 'saves inheritance structure of dynamically created methods.
|
26
37
|
|
27
38
|
Allows to redefine dynamic method in the same class or in any child class, and call
|
@@ -34,6 +45,7 @@ extra_rdoc_files: []
|
|
34
45
|
files:
|
35
46
|
- .gitignore
|
36
47
|
- .rspec
|
48
|
+
- .travis.yml
|
37
49
|
- Gemfile
|
38
50
|
- HISTORY.md
|
39
51
|
- LICENSE
|
@@ -42,6 +54,7 @@ files:
|
|
42
54
|
- inheritance_module_eval.gemspec
|
43
55
|
- lib/inheritance_module_eval.rb
|
44
56
|
- lib/inheritance_module_eval/version.rb
|
57
|
+
- spec/inheritance_spec.rb
|
45
58
|
homepage: http://github.com/AlexParamonov/inheritance_module_eval
|
46
59
|
licenses: []
|
47
60
|
post_install_message:
|
@@ -67,3 +80,4 @@ signing_key:
|
|
67
80
|
specification_version: 3
|
68
81
|
summary: inheritance safe module_eval.
|
69
82
|
test_files: []
|
83
|
+
has_rdoc:
|