penetrator 0.0.1 → 0.1.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/README.md +13 -4
- data/lib/penetrator/version.rb +1 -1
- data/lib/penetrator.rb +31 -6
- data/penetrator.gemspec +1 -0
- data/spec/coerce_spec.rb +92 -0
- data/spec/core_spec.rb +8 -47
- metadata +28 -5
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
This gem aimed to help with reuse code in ruby projects.
|
4
4
|
Highly inspired from http://github.com/makandra/modularity gem but slightly modified for supporting
|
5
5
|
conventional *super* inheritance chaining methods.
|
6
|
-
|
6
|
+
Also shameless borrowed code from ActiveSupport::Coerce and I should say thanks that Ruby Hackers, who wrote it.
|
7
7
|
|
8
8
|
## Installation
|
9
9
|
|
@@ -24,7 +24,7 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
*config/application.rb*
|
26
26
|
```ruby
|
27
|
-
config.autoload_paths +=
|
27
|
+
config.autoload_paths += Rails.root.join( 'app', 'traits' )
|
28
28
|
```
|
29
29
|
|
30
30
|
*app/controllers/traits/crudable_trait.rb*
|
@@ -51,7 +51,7 @@ config.autoload_paths += Dir[Rails.root.join( 'app', '**/*' )].select { |fn| Fil
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
# ... and so on
|
54
|
+
# ... and so on ...
|
55
55
|
|
56
56
|
private
|
57
57
|
def take_layout
|
@@ -68,7 +68,7 @@ config.autoload_paths += Dir[Rails.root.join( 'app', '**/*' )].select { |fn| Fil
|
|
68
68
|
```ruby
|
69
69
|
class AccomodationsController < ApplicationController
|
70
70
|
#
|
71
|
-
# CrudableTrait required
|
71
|
+
# CrudableTrait required this mehod
|
72
72
|
private
|
73
73
|
def resource_class
|
74
74
|
Accomodation
|
@@ -91,6 +91,15 @@ config.autoload_paths += Dir[Rails.root.join( 'app', '**/*' )].select { |fn| Fil
|
|
91
91
|
def default_order
|
92
92
|
"accomodations.name desc"
|
93
93
|
end
|
94
|
+
|
95
|
+
public
|
96
|
+
# Override traits methods
|
97
|
+
# with respecting call chaining
|
98
|
+
#
|
99
|
+
def kill_all_humans
|
100
|
+
"Yes" or super
|
101
|
+
end
|
102
|
+
|
94
103
|
end
|
95
104
|
```
|
96
105
|
|
data/lib/penetrator/version.rb
CHANGED
data/lib/penetrator.rb
CHANGED
@@ -3,23 +3,48 @@ require "penetrator/inflector"
|
|
3
3
|
require "penetrator/version"
|
4
4
|
|
5
5
|
module Penetrator
|
6
|
-
module
|
6
|
+
module Concern
|
7
|
+
def self.extended(base) #:nodoc:
|
8
|
+
base.instance_variable_set("@_dependencies", [])
|
9
|
+
end
|
10
|
+
|
11
|
+
def append_features(base)
|
12
|
+
if base.instance_variable_defined?("@_dependencies")
|
13
|
+
base.instance_variable_get("@_dependencies") << self
|
14
|
+
return false
|
15
|
+
else
|
16
|
+
return false if base < self
|
17
|
+
@_dependencies.each { |dep| base.send(:include, dep) }
|
18
|
+
super
|
19
|
+
base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
|
20
|
+
base.class_exec(*@_trait_args, &@_included_block) if instance_variable_defined?("@_included_block")
|
21
|
+
end
|
22
|
+
end
|
7
23
|
|
24
|
+
def included(base = nil, &block)
|
25
|
+
if base.nil?
|
26
|
+
@_included_block = block
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end # Concern
|
32
|
+
|
33
|
+
module Behavior
|
8
34
|
def self.included(base)
|
9
35
|
base.extend ClassMethods
|
10
36
|
end
|
11
37
|
|
12
38
|
module ClassMethods
|
13
|
-
def
|
39
|
+
def behaves_like(trait_name, *args)
|
14
40
|
full_name = "#{Penetrator::Inflector.camelize(trait_name.to_s)}Trait"
|
15
41
|
trait = Penetrator::Inflector.constantize(full_name)
|
16
|
-
|
17
|
-
self.class_variable_set(trait_args_var.to_sym, (args || nil))
|
42
|
+
trait.instance_variable_set(:@_trait_args, args)
|
18
43
|
include trait
|
19
44
|
end
|
20
|
-
end
|
45
|
+
end # ClassMethods
|
46
|
+
end # Behavior
|
21
47
|
|
22
|
-
end
|
23
48
|
end
|
24
49
|
|
25
50
|
Object.send :include, Penetrator::Behavior
|
data/penetrator.gemspec
CHANGED
data/spec/coerce_spec.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'penetrator'
|
3
|
+
require 'minitest/spec'
|
4
|
+
require 'minitest/autorun'
|
5
|
+
|
6
|
+
describe 'behavior when trait can be parameterized by arguments passed into included module' do
|
7
|
+
module CanHaveArgsTrait
|
8
|
+
extend Penetrator::Concern
|
9
|
+
included do |*args|
|
10
|
+
args.each do |method_name|
|
11
|
+
define_method(method_name) do
|
12
|
+
method_name.to_s
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end # included
|
16
|
+
end # CanHaveArgs
|
17
|
+
|
18
|
+
it 'receive trait arguments' do
|
19
|
+
class Victim
|
20
|
+
behaves_like :CanHaveArgs, 'arg1', 'arg2'
|
21
|
+
end
|
22
|
+
obj = Victim.new
|
23
|
+
obj.must_respond_to :arg1
|
24
|
+
obj.arg1.must_be :==, 'arg1'
|
25
|
+
obj.must_respond_to :arg2
|
26
|
+
obj.arg2.must_be :==, 'arg2'
|
27
|
+
|
28
|
+
class OtherVictim
|
29
|
+
behaves_like :CanHaveArgs
|
30
|
+
end
|
31
|
+
obj = OtherVictim.new
|
32
|
+
obj.wont_respond_to :arg1
|
33
|
+
obj.wont_respond_to :arg2
|
34
|
+
end
|
35
|
+
|
36
|
+
end # trait argument
|
37
|
+
|
38
|
+
describe 'behavior when trait add ClassMethods and Instance methods' do
|
39
|
+
module RichTrait
|
40
|
+
extend Penetrator::Concern
|
41
|
+
module ClassMethods
|
42
|
+
def class_method
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def instance_method
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'add class and instance methods from traits' do
|
51
|
+
class VictimWithNoArguments
|
52
|
+
behaves_like 'rich'
|
53
|
+
end
|
54
|
+
obj = VictimWithNoArguments.new
|
55
|
+
obj.must_respond_to :instance_method
|
56
|
+
VictimWithNoArguments.must_respond_to :class_method
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
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
|
+
|
70
|
+
def instance_method(arg)
|
71
|
+
"From Trait with chaining"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
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
|
+
|
84
|
+
behaves_like 'super_rich'
|
85
|
+
end
|
86
|
+
|
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
|
data/spec/core_spec.rb
CHANGED
@@ -6,7 +6,7 @@ require 'mocha'
|
|
6
6
|
|
7
7
|
describe 'Class' do
|
8
8
|
it 'should be accesable' do
|
9
|
-
Class.must_respond_to :
|
9
|
+
Class.must_respond_to :behaves_like
|
10
10
|
end
|
11
11
|
end # Class method
|
12
12
|
|
@@ -19,7 +19,7 @@ describe 'mixing behavior' do
|
|
19
19
|
|
20
20
|
it 'add trait methods' do
|
21
21
|
class Victim
|
22
|
-
|
22
|
+
behaves_like 'first'
|
23
23
|
end
|
24
24
|
|
25
25
|
Victim.new.must_respond_to :test
|
@@ -35,7 +35,7 @@ describe 'mixing behavior' do
|
|
35
35
|
|
36
36
|
it 'add traits methods from nested modules' do
|
37
37
|
class Victim
|
38
|
-
|
38
|
+
behaves_like 'outer/inner'
|
39
39
|
end
|
40
40
|
Victim.new.must_respond_to :inner_test
|
41
41
|
end
|
@@ -53,7 +53,7 @@ describe 'methods chainings' do
|
|
53
53
|
|
54
54
|
it 'have traits methods' do
|
55
55
|
class Victim
|
56
|
-
|
56
|
+
behaves_like 'super'
|
57
57
|
def test
|
58
58
|
'this from class and that ' + super
|
59
59
|
end
|
@@ -72,23 +72,23 @@ describe 'callbacks' do
|
|
72
72
|
class Victim; end
|
73
73
|
CallbackTrait.expects(:included).with(Victim)
|
74
74
|
class Victim
|
75
|
-
|
75
|
+
behaves_like 'callback'
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end # callbacks
|
79
79
|
|
80
80
|
describe 'visibility' do
|
81
81
|
module VisibilityTrait
|
82
|
-
def public_method_from_trait;
|
82
|
+
def public_method_from_trait; end
|
83
83
|
protected
|
84
|
-
def protected_method_from_trait;
|
84
|
+
def protected_method_from_trait; end
|
85
85
|
private
|
86
86
|
def private_method_from_trait; end
|
87
87
|
end
|
88
88
|
|
89
89
|
it 'allow trait to define methods with different visibility' do
|
90
90
|
class Victim
|
91
|
-
|
91
|
+
behaves_like 'visibility'
|
92
92
|
end
|
93
93
|
|
94
94
|
instance = Victim.new
|
@@ -99,42 +99,3 @@ describe 'visibility' do
|
|
99
99
|
end
|
100
100
|
|
101
101
|
end # visibility
|
102
|
-
|
103
|
-
describe 'trait arguments' do
|
104
|
-
module HaveArgsTrait; end
|
105
|
-
|
106
|
-
it 'receive trait arguments' do
|
107
|
-
class Victim; end
|
108
|
-
Victim.expects(:behave_like).with('have_args', 'arg1', 'arg2')
|
109
|
-
|
110
|
-
class Victim
|
111
|
-
behave_like 'have_args', 'arg1', 'arg2'
|
112
|
-
end
|
113
|
-
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'base holds arguments' do
|
117
|
-
class Victim
|
118
|
-
behave_like 'have_args', 'arg1', 'arg2'
|
119
|
-
end
|
120
|
-
Victim.class_variable_get(:@@have_args_args).must_equal ['arg1','arg2']
|
121
|
-
end
|
122
|
-
|
123
|
-
|
124
|
-
describe 'arguments defined before trait included' do
|
125
|
-
module HandyTrait
|
126
|
-
def self.included(base)
|
127
|
-
base.send :stub, base.class_variable_get(:@@handy_args)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
class Victim; end
|
132
|
-
Victim.expects(:stub).with(['arg'])
|
133
|
-
|
134
|
-
class Victim
|
135
|
-
behave_like :handy, 'arg'
|
136
|
-
end
|
137
|
-
end # 'trait use arguments'
|
138
|
-
|
139
|
-
|
140
|
-
end # trait argument
|
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.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,27 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-10-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !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: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: mocha
|
16
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
17
33
|
none: false
|
18
34
|
requirements:
|
19
35
|
- - ! '>='
|
@@ -21,7 +37,12 @@ dependencies:
|
|
21
37
|
version: '0'
|
22
38
|
type: :development
|
23
39
|
prerelease: false
|
24
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
25
46
|
description: Implement traits behavior to get rid of code repetition
|
26
47
|
email:
|
27
48
|
- jurbat@gmail.com
|
@@ -38,6 +59,7 @@ files:
|
|
38
59
|
- lib/penetrator/inflector.rb
|
39
60
|
- lib/penetrator/version.rb
|
40
61
|
- penetrator.gemspec
|
62
|
+
- spec/coerce_spec.rb
|
41
63
|
- spec/core_spec.rb
|
42
64
|
homepage: https://github.com/svenyurgensson/penetrator
|
43
65
|
licenses: []
|
@@ -59,9 +81,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
81
|
version: '0'
|
60
82
|
requirements: []
|
61
83
|
rubyforge_project:
|
62
|
-
rubygems_version: 1.8.
|
84
|
+
rubygems_version: 1.8.24
|
63
85
|
signing_key:
|
64
86
|
specification_version: 3
|
65
87
|
summary: Implement traits behavior to get rid of code repetition
|
66
88
|
test_files:
|
89
|
+
- spec/coerce_spec.rb
|
67
90
|
- spec/core_spec.rb
|