meta_module 0.0.1
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/.gitignore +19 -0
- data/.rspec +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +42 -0
- data/lib/meta_module.rb +35 -0
- data/lib/meta_module/version.rb +3 -0
- data/meta_module.gemspec +27 -0
- data/spec/example_spec.rb +60 -0
- data/spec/support/remove_const.rb +5 -0
- data/spec/support/self.rb +2 -0
- data/spec/support/spec_helper.rb +10 -0
- data/spec/unit/meta_module/m_module/class_methods/new_spec.rb +16 -0
- data/spec/unit/meta_module/m_module/class_methods/used_spec.rb +15 -0
- data/spec/unit/meta_module/m_module2/class_methods/new_spec.rb +37 -0
- metadata +155 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Alexander K
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# MetaModule
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'meta_module'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install meta_module
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
# task :default => :spec
|
6
|
+
|
7
|
+
task :+ => [:spec, :mutant]
|
8
|
+
task :default => :+
|
9
|
+
|
10
|
+
|
11
|
+
desc 'mutate-test given class'
|
12
|
+
task :mutate, [:who, :file] do |t,args|
|
13
|
+
# args.with_defaults who: 'Map'; who = args.who
|
14
|
+
who, file = args.who, args.file
|
15
|
+
klass = who
|
16
|
+
# file = who.underscore
|
17
|
+
system "mutant -I lib -r #{ file } --rspec-dm2 ::#{ klass }"
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
desc 'run all mutation tests'
|
22
|
+
task :mutant do
|
23
|
+
Rake::Task[:mutate].invoke 'MetaModule::MModule', 'meta_module'
|
24
|
+
Rake::Task[:mutate].reenable
|
25
|
+
Rake::Task[:mutate].invoke 'MetaModule::MModule2', 'meta_module'
|
26
|
+
# use file instead of class, get all files in lib/**?
|
27
|
+
end
|
28
|
+
task :m => :mutant
|
29
|
+
|
30
|
+
|
31
|
+
BEGIN{
|
32
|
+
class String
|
33
|
+
def underscore
|
34
|
+
self.gsub(/::/, '/').
|
35
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
36
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
37
|
+
tr("-", "_").
|
38
|
+
downcase
|
39
|
+
end
|
40
|
+
def +@; inspect end
|
41
|
+
end
|
42
|
+
}
|
data/lib/meta_module.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require "meta_module/version"
|
2
|
+
|
3
|
+
module MetaModule
|
4
|
+
# subclassing of mmodule sort of sucks?
|
5
|
+
# use mixin with anonymous module instead?
|
6
|
+
class MModule < Module
|
7
|
+
|
8
|
+
# I use .new so don't bother user to use super in #initialize
|
9
|
+
def self.new(*)
|
10
|
+
super.tap { |x| x.send :include, self::Methods }
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.used &block
|
14
|
+
eval 'define_method :extended, &block' # to hide this line from mutant!
|
15
|
+
# define_method :extended # because this works too! with some warnings though:)
|
16
|
+
end
|
17
|
+
|
18
|
+
module Methods
|
19
|
+
# monkey patch me...
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class MModule2 # < Class ...
|
24
|
+
def self.new *params
|
25
|
+
_params = params.join ?,
|
26
|
+
a_params = params.map { |x| "@#{x}" }.join ?,
|
27
|
+
|
28
|
+
Class.new(MModule) do
|
29
|
+
eval "def initialize(#{_params}); #{a_params} = #{_params} end"
|
30
|
+
#private
|
31
|
+
attr_reader *params
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/meta_module.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'meta_module/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "meta_module"
|
8
|
+
spec.version = MetaModule::VERSION
|
9
|
+
spec.authors = ["Alexander K"]
|
10
|
+
spec.email = ["xpyro@ya.ru"]
|
11
|
+
spec.description = %q{ few things around module subclassing }.strip
|
12
|
+
spec.summary = spec.description #%q{TODO: Write a gem summary}
|
13
|
+
spec.homepage = "https://github.com/sowcow/meta_module"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
|
24
|
+
spec.add_development_dependency "rspec"
|
25
|
+
spec.add_development_dependency "mutant"
|
26
|
+
spec.add_development_dependency "pry"
|
27
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# TODO: without .new, using Method
|
2
|
+
describe 'usage of MetaModule::' do
|
3
|
+
after { remove_const :My, :A }
|
4
|
+
|
5
|
+
describe 'MModule' do
|
6
|
+
subject { MModule }
|
7
|
+
|
8
|
+
example 'ok' do
|
9
|
+
|
10
|
+
# definition
|
11
|
+
class My < subject
|
12
|
+
def initialize name
|
13
|
+
@name = name
|
14
|
+
end
|
15
|
+
|
16
|
+
used do |at|
|
17
|
+
at.abc @name
|
18
|
+
end
|
19
|
+
|
20
|
+
module Methods
|
21
|
+
def abc value; @abc = value end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# sort of usage
|
26
|
+
module A
|
27
|
+
extend RSpec::Matchers
|
28
|
+
expect { extend My.new 1 }.to change { @abc }.from(nil).to 1
|
29
|
+
end
|
30
|
+
|
31
|
+
Class.new do
|
32
|
+
extend RSpec::Matchers
|
33
|
+
expect { extend My.new 1 }.to change { @abc }.from(nil).to 1
|
34
|
+
end
|
35
|
+
|
36
|
+
Object.new.instance_eval do
|
37
|
+
extend RSpec::Matchers
|
38
|
+
expect { extend My.new 1 }.to change { @abc }.from(nil).to 1
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'MModule2' do
|
45
|
+
subject { MModule2 }
|
46
|
+
example :ok do
|
47
|
+
class My < MModule2.new :the_value
|
48
|
+
used do |x|
|
49
|
+
x.abc! the_value
|
50
|
+
end
|
51
|
+
|
52
|
+
module Methods
|
53
|
+
def abc! value; @abc = value end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
Object.new.extend(My.new 100).instance_eval { @abc }.should == 100
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
2
|
+
|
3
|
+
Dir["./spec/support/**/*.rb"].each { |f| require f }
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
7
|
+
config.run_all_when_everything_filtered = true
|
8
|
+
config.filter_run :focus
|
9
|
+
config.order = 'random'
|
10
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
describe :MModule do
|
2
|
+
subject { MModule }
|
3
|
+
after { remove_const :My }
|
4
|
+
|
5
|
+
describe '.new' do
|
6
|
+
it 'extends result object with self::Methods' do
|
7
|
+
class My < subject
|
8
|
+
module Methods
|
9
|
+
def abc; 5 end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
My.new.instance_methods.should include :abc
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
describe :MModule do
|
2
|
+
subject { MModule }
|
3
|
+
|
4
|
+
describe '.used' do
|
5
|
+
it 'defines extended hook with given block' do
|
6
|
+
my = Class.new(subject) do
|
7
|
+
used do |at|
|
8
|
+
@used = true
|
9
|
+
end
|
10
|
+
attr_reader :used
|
11
|
+
end.new
|
12
|
+
expect { my.send :extend, my }.to change { my.used }.from(nil).to true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
describe :MModule2 do
|
2
|
+
#subject { MModule2 }
|
3
|
+
#after { remove_const :My }
|
4
|
+
|
5
|
+
describe '.new' do
|
6
|
+
subject { MModule2.new(*params) }
|
7
|
+
|
8
|
+
let(:n) { rand(1..5) }
|
9
|
+
let(:params) { (:a..:z).take n }
|
10
|
+
let(:instance) { subject.new *params }
|
11
|
+
|
12
|
+
it 'returns class' do
|
13
|
+
subject.class.should == Class
|
14
|
+
end
|
15
|
+
it 'result superclass is MModule' do
|
16
|
+
subject.superclass.should == MModule
|
17
|
+
end
|
18
|
+
it 'instance of resulting class has attr reader for each argument given to subject.new with given values' do
|
19
|
+
params.each { |name| instance.send(name).should == name }
|
20
|
+
end
|
21
|
+
it 'resulting class.new takes as many arguments as given to subject.new' do
|
22
|
+
expect { subject.new *params }.not_to raise_error
|
23
|
+
expect { subject.new *params.drop(1) }.to raise_error
|
24
|
+
expect { subject.new *(params + [:excess]) }.to raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
#it 'extends result object with self::Methods' do
|
28
|
+
# class My < subject
|
29
|
+
# module Methods
|
30
|
+
# def abc; 5 end
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# My.new.instance_methods.should include :abc
|
35
|
+
#end
|
36
|
+
end
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: meta_module
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alexander K
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.3'
|
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: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: mutant
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: pry
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: few things around module subclassing
|
95
|
+
email:
|
96
|
+
- xpyro@ya.ru
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- .rspec
|
103
|
+
- Gemfile
|
104
|
+
- LICENSE.txt
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- lib/meta_module.rb
|
108
|
+
- lib/meta_module/version.rb
|
109
|
+
- meta_module.gemspec
|
110
|
+
- spec/example_spec.rb
|
111
|
+
- spec/support/remove_const.rb
|
112
|
+
- spec/support/self.rb
|
113
|
+
- spec/support/spec_helper.rb
|
114
|
+
- spec/unit/meta_module/m_module/class_methods/new_spec.rb
|
115
|
+
- spec/unit/meta_module/m_module/class_methods/used_spec.rb
|
116
|
+
- spec/unit/meta_module/m_module2/class_methods/new_spec.rb
|
117
|
+
homepage: https://github.com/sowcow/meta_module
|
118
|
+
licenses:
|
119
|
+
- MIT
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
none: false
|
126
|
+
requirements:
|
127
|
+
- - ! '>='
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
segments:
|
131
|
+
- 0
|
132
|
+
hash: -2961995576848703100
|
133
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
|
+
none: false
|
135
|
+
requirements:
|
136
|
+
- - ! '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
segments:
|
140
|
+
- 0
|
141
|
+
hash: -2961995576848703100
|
142
|
+
requirements: []
|
143
|
+
rubyforge_project:
|
144
|
+
rubygems_version: 1.8.25
|
145
|
+
signing_key:
|
146
|
+
specification_version: 3
|
147
|
+
summary: few things around module subclassing
|
148
|
+
test_files:
|
149
|
+
- spec/example_spec.rb
|
150
|
+
- spec/support/remove_const.rb
|
151
|
+
- spec/support/self.rb
|
152
|
+
- spec/support/spec_helper.rb
|
153
|
+
- spec/unit/meta_module/m_module/class_methods/new_spec.rb
|
154
|
+
- spec/unit/meta_module/m_module/class_methods/used_spec.rb
|
155
|
+
- spec/unit/meta_module/m_module2/class_methods/new_spec.rb
|