penetrator 0.1.6 → 0.1.8
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/README.md +37 -12
- data/lib/penetrator.rb +16 -4
- data/lib/penetrator/version.rb +1 -1
- data/spec/concern_spec.rb +56 -26
- metadata +2 -2
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# Penetrator
|
2
2
|
|
3
|
-
This gem aimed to help
|
4
|
-
Highly inspired
|
3
|
+
This gem aimed to help improving code reuse in ruby projects.
|
4
|
+
Highly inspired by http://github.com/makandra/modularity gem but slightly modified for supporting
|
5
5
|
conventional *super* inheritance methods chaining.
|
6
|
-
Also much of code was shamelessly borrowed from `ActiveSupport::Concern`
|
7
|
-
All what left to do for me -
|
6
|
+
Also much of code was shamelessly borrowed from `ActiveSupport::Concern` so I should say thanks that Ruby Hackers, who wrote it.
|
7
|
+
All that what left to do for me - just to take the best from both worlds.
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
@@ -16,7 +16,7 @@ And then execute:
|
|
16
16
|
|
17
17
|
$ bundle
|
18
18
|
|
19
|
-
Or install it yourself
|
19
|
+
Or install it yourself:
|
20
20
|
|
21
21
|
$ gem install penetrator
|
22
22
|
|
@@ -70,6 +70,7 @@ File: *app/controllers/traits/crudable_trait.rb*
|
|
70
70
|
@_resources ||= resource_class.order(default_order).all
|
71
71
|
end
|
72
72
|
end
|
73
|
+
|
73
74
|
```
|
74
75
|
|
75
76
|
File: *app/controllers/accomodations_controller.rb*
|
@@ -136,13 +137,13 @@ File: *app/models/my_model.rb*
|
|
136
137
|
```ruby
|
137
138
|
|
138
139
|
class Victim
|
139
|
-
behaves_like :CanHaveArgs, '
|
140
|
+
behaves_like :CanHaveArgs, 'first', 'second'
|
140
141
|
end
|
141
142
|
|
142
143
|
obj = Victim.new
|
143
144
|
|
144
|
-
obj.
|
145
|
-
obj.
|
145
|
+
obj.first # => first-chunked!
|
146
|
+
obj.second # => second-chunked!
|
146
147
|
|
147
148
|
```
|
148
149
|
|
@@ -154,7 +155,7 @@ Also you can freely utilize `ClassMethods` internal module as you usually do wit
|
|
154
155
|
extend Penetrator::Concern
|
155
156
|
module ClassMethods
|
156
157
|
def class_method
|
157
|
-
... add what you want ...
|
158
|
+
# ... add what you want ...
|
158
159
|
end
|
159
160
|
end
|
160
161
|
|
@@ -164,7 +165,7 @@ Also you can freely utilize `ClassMethods` internal module as you usually do wit
|
|
164
165
|
|
165
166
|
```
|
166
167
|
|
167
|
-
You can
|
168
|
+
You can even extend arbitrary instance of any class with your trait:
|
168
169
|
|
169
170
|
```ruby
|
170
171
|
|
@@ -172,15 +173,39 @@ You can ever extend arbitrary instance of any class with your trait:
|
|
172
173
|
extend Penetrator::Concern
|
173
174
|
|
174
175
|
def cleanup
|
175
|
-
|
176
|
+
# ...
|
176
177
|
end
|
177
178
|
end
|
178
179
|
|
179
|
-
string_of_dirty_html = "Something <span>dirty</span> and even <marquee>fearing ugly</marquee>
|
180
|
+
string_of_dirty_html = "Something <span>dirty</span> and even <marquee>fearing ugly</marquee>"
|
180
181
|
string_of_dirty_html.behave_like 'html_sanitizer'
|
181
182
|
|
182
183
|
```
|
183
184
|
|
185
|
+
`behave_like` also accepts block which can be used in `included` section.
|
186
|
+
I have no idea whom need that, but decided to make it possible.
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
|
190
|
+
module HtmlSanitizerTrait
|
191
|
+
included do |*args, block|
|
192
|
+
args.each do |method_name|
|
193
|
+
define_method(method_name) do
|
194
|
+
method_name.to_s
|
195
|
+
end
|
196
|
+
end
|
197
|
+
block.call if block
|
198
|
+
end # included
|
199
|
+
|
200
|
+
class VictimWithBlock
|
201
|
+
behaves_like :HtmlSanitizerTrait, 'cleanup_processor' do
|
202
|
+
class_variable_set(:@@foo, "I'm set")
|
203
|
+
# ... something useful
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
```
|
208
|
+
|
184
209
|
|
185
210
|
## Contributing
|
186
211
|
|
data/lib/penetrator.rb
CHANGED
@@ -18,13 +18,23 @@ module Penetrator
|
|
18
18
|
@_dependencies.each { |dep| base.send(:include, dep) }
|
19
19
|
super
|
20
20
|
base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
|
21
|
-
|
21
|
+
return unless instance_variable_defined?("@_included_block")
|
22
|
+
if @_trait_block
|
23
|
+
base.class_exec(*@_trait_args, @_trait_block, &@_included_block)
|
24
|
+
else
|
25
|
+
base.class_exec(*@_trait_args, &@_included_block)
|
26
|
+
end
|
22
27
|
end
|
23
28
|
end
|
24
29
|
|
25
30
|
def extend_object(obj)
|
26
31
|
super
|
27
|
-
|
32
|
+
return unless instance_variable_defined?("@_included_block")
|
33
|
+
if @_trait_block
|
34
|
+
(class << obj; self; end).instance_exec(*@_trait_args, @_trait_block, &@_included_block)
|
35
|
+
else
|
36
|
+
(class << obj; self; end).instance_exec(*@_trait_args, &@_included_block)
|
37
|
+
end
|
28
38
|
end
|
29
39
|
|
30
40
|
def included(base = nil, &block)
|
@@ -42,18 +52,20 @@ module Penetrator
|
|
42
52
|
end
|
43
53
|
|
44
54
|
module ClassMethods
|
45
|
-
def behaves_like(trait_name, *args)
|
55
|
+
def behaves_like(trait_name, *args, &block)
|
46
56
|
full_name = "#{Penetrator::Inflector.camelize(trait_name.to_s)}Trait"
|
47
57
|
trait = Penetrator::Inflector.constantize(full_name)
|
48
58
|
trait.instance_variable_set(:@_trait_args, args)
|
59
|
+
trait.instance_variable_set(:@_trait_block, block)
|
49
60
|
include trait
|
50
61
|
end
|
51
62
|
end # ClassMethods
|
52
63
|
|
53
|
-
def behaves_like(trait_name, *args)
|
64
|
+
def behaves_like(trait_name, *args, &block)
|
54
65
|
full_name = "#{Penetrator::Inflector.camelize(trait_name.to_s)}Trait"
|
55
66
|
trait = Penetrator::Inflector.constantize(full_name)
|
56
67
|
trait.instance_variable_set(:@_trait_args, args)
|
68
|
+
trait.instance_variable_set(:@_trait_block, block)
|
57
69
|
extend trait
|
58
70
|
end
|
59
71
|
end # Behavior
|
data/lib/penetrator/version.rb
CHANGED
data/spec/concern_spec.rb
CHANGED
@@ -58,35 +58,65 @@ describe 'behavior when trait add ClassMethods and Instance methods' do
|
|
58
58
|
end
|
59
59
|
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
61
|
+
describe 'behavior when trait add ClassMethods and Instance methods alongside with existing' do
|
62
|
+
module SuperRichTrait
|
63
|
+
extend Penetrator::Concern
|
64
|
+
module ClassMethods
|
65
|
+
def class_method(arg)
|
66
|
+
"From Trait with chaining"
|
67
|
+
end
|
68
|
+
end
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
70
|
+
def instance_method(arg)
|
71
|
+
"From Trait with chaining"
|
72
|
+
end
|
73
|
+
end
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
75
|
+
it 'add class and instance methods from traits' do
|
76
|
+
class Innocent
|
77
|
+
def self.class_method arg
|
78
|
+
"This is class argument: #{arg} " + super
|
79
|
+
end
|
80
|
+
def instance_method arg
|
81
|
+
"This is instance argument: #{arg} " + super
|
82
|
+
end
|
83
83
|
|
84
|
-
|
85
|
-
|
84
|
+
behaves_like 'super_rich'
|
85
|
+
end
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
87
|
+
obj = Innocent.new
|
88
|
+
obj.instance_method('iarg').must_be :==, 'This is instance argument: iarg From Trait with chaining'
|
89
|
+
Innocent.class_method('carg').must_be :==, 'This is class argument: carg From Trait with chaining'
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
describe 'behavior when trait utilize arguments and block' do
|
97
|
+
module WithArgsAndBlockTrait
|
98
|
+
extend Penetrator::Concern
|
99
|
+
included do |*args, block|
|
100
|
+
args.each do |method_name|
|
101
|
+
define_method(method_name) do
|
102
|
+
method_name.to_s
|
103
|
+
end
|
104
|
+
end
|
105
|
+
block.call if block
|
106
|
+
end # included
|
107
|
+
|
108
|
+
end # WithArgsAndBlockTrait
|
109
|
+
|
110
|
+
it 'receive trait block' do
|
111
|
+
class VictimWithBlock
|
112
|
+
behaves_like :WithArgsAndBlock, 'arg1' do
|
113
|
+
class_variable_set(:@@foo, "I'm set")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
obj = VictimWithBlock.new
|
117
|
+
obj.must_respond_to :arg1
|
118
|
+
obj.arg1.must_be :==, 'arg1'
|
119
|
+
VictimWithBlock.class_variable_get(:@@foo).must_be :==, "I'm set"
|
120
|
+
end
|
91
121
|
|
92
122
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: penetrator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|