method_repository 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ vendor/bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in inserts.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Kentaro Kuribayashi
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,136 @@
1
+ # MethodRepository
2
+
3
+ Extracting redandunt code and commonalizing it in a different way.
4
+
5
+ ## Problem
6
+
7
+ To extract redandunt codes into a method to commonalize them is a usual strategy for OOP. It allows us to streamline our codes and modify at one stop even though the method is used at anywhere, anytimes.
8
+
9
+ I don't like when highly commonalized OOP structure disturbes me from quick tracing where such methods are defined. It's OOP's natural defect, I think. Once classed/modules are defined, it's inevitable that the classes/modules are inherited/included at anywhere we don't know.
10
+
11
+ In that way, inheritance/inclusion-based OOP resembles `goto` programming; There's no clear reason why some classes/modules are inherited/included by another classes/modules. Even though there's some structural thought in your classes/modules design, such an excessively free inheritance/inclusion prevent them from grasping the whole code quickily.
12
+
13
+ ## Solution
14
+
15
+ This library provides a "method repository" in which you can add your methods to commonalize redandunt codes here and there in your whole codes, which is just same as usual module usage. However, the methods you define in the "repository" will never be included automatically into other classes/modules unless not permitted explicitely.
16
+
17
+ This is the point; There's no chance the methods in the "repository" appear at somewhere the "repository" don't know. To commonalize redanduncy is our intension, but we don't want the methods to be used where we don't know. The way this library provides solves the problem.
18
+
19
+ ## Usage
20
+
21
+ Imagine there's such a code below:
22
+
23
+ ```ruby
24
+ module Repository
25
+ include MethodRepository
26
+
27
+ insert :method1, in: %w[Foo Bar] do; end
28
+ insert :method2, in: %w[Baz] do; end
29
+ end
30
+
31
+ class Foo; end
32
+ class Bar; end
33
+ class Baz; end
34
+ class Qux; end
35
+ ```
36
+
37
+ * `method1` is declared it can be inserted in `Foo` and `Bar`
38
+ * `method2` is declared it can be inserted in only `Baz`
39
+ * No method is declared it can be inserted in `Qux`
40
+
41
+ ### Extending
42
+
43
+ When the classes/objects are extended by `Repository` module:
44
+
45
+ ```ruby
46
+ Foo.extend(Repository)
47
+ Bar.extend(Repository)
48
+ Baz.extend(Repository)
49
+ Qux.extend(Repository)
50
+ ```
51
+
52
+ or
53
+
54
+ ```ruby
55
+ foo = Foo.new; foo.extend(Repository)
56
+ bar = Bar.new; bar.extend(Repository)
57
+ baz = Baz.new; bar.extend(Repository)
58
+ qux = Qux.new; qux.extend(Repository)
59
+ ```
60
+
61
+ Only explicitely permitted methods are defined as singleton methods of each classes/objects. That results in:
62
+
63
+ ```ruby
64
+ Foo.respond_to?(:method1)) #=> true
65
+ Bar.respond_to?(:method1)) #=> true
66
+ Baz.respond_to?(:method1)) #=> false
67
+ Qux.respond_to?(:method1)) #=> false
68
+
69
+ Foo.respond_to?(:method2)) #=> false
70
+ Bar.respond_to?(:method2)) #=> false
71
+ Baz.respond_to?(:method2)) #=> true
72
+ Qux.respond_to?(:method1)) #=> false
73
+ ```
74
+
75
+ or
76
+
77
+ ```ruby
78
+ foo.respond_to?(:method1)) #=> true
79
+ bar.respond_to?(:method1)) #=> true
80
+ baz.respond_to?(:method1)) #=> false
81
+ qux.respond_to?(:method1)) #=> false
82
+
83
+ foo.respond_to?(:method2)) #=> false
84
+ bar.respond_to?(:method2)) #=> false
85
+ baz.respond_to?(:method2)) #=> true
86
+ qux.respond_to?(:method1)) #=> false
87
+ ```
88
+
89
+ ### Including
90
+
91
+ The rule is also applicable to `include`:
92
+
93
+ ```ruby
94
+ Foo.send(:include, Repository)
95
+ Bar.send(:include, Repository)
96
+ Baz.send(:include, Repository)
97
+ Qux.send(:include, Repository)
98
+ ```
99
+
100
+ Results in:
101
+
102
+ ```ruby
103
+ Foo.new.respond_to?(:method1)) #=> true
104
+ Bar.new.respond_to?(:method1)) #=> true
105
+ Baz.new.respond_to?(:method1)) #=> false
106
+ Qux.new.respond_to?(:method1)) #=> false
107
+
108
+ Foo.new.respond_to?(:method2)) #=> false
109
+ Bar.new.respond_to?(:method2)) #=> false
110
+ Baz.new.respond_to?(:method2)) #=> true
111
+ Qux.new.respond_to?(:method1)) #=> false
112
+ ```
113
+
114
+ In this case, the methods in `Repository` are, of course, defined as instance methods of each classes, not singleton methods of each objects.
115
+
116
+ ## Installation
117
+
118
+ Add this line to your application's Gemfile:
119
+
120
+ gem 'inserts'
121
+
122
+ And then execute:
123
+
124
+ $ bundle
125
+
126
+ Or install it yourself as:
127
+
128
+ $ gem install inserts
129
+
130
+ ## Contributing
131
+
132
+ 1. Fork it
133
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
134
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
135
+ 4. Push to the branch (`git push origin my-new-feature`)
136
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,47 @@
1
+ require "method_repository/version"
2
+
3
+ module MethodRepository
4
+ def self.included(base)
5
+ base.instance_variable_set(:@targets, {})
6
+ base.extend(ModuleMethods)
7
+ end
8
+
9
+ module ModuleMethods
10
+ def extended(base)
11
+ klass_name = base.class.to_s == 'Class' ? base.to_s : base.class.to_s
12
+
13
+ if (methods = @targets[klass_name])
14
+ singleton_class = class << base; self; end
15
+ singleton_class.class_eval do
16
+ methods.each do |method|
17
+ define_method method[:name], method[:block]
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ def included(base)
24
+ if (methods = @targets[base.to_s])
25
+ base.class_eval do
26
+ methods.each do |method|
27
+ define_method method[:name], method[:block]
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ def insert(name, klasses = {}, &block)
34
+ if !klasses[:in]
35
+ raise ArgumentError.new("`:in' parameter is required")
36
+ end
37
+
38
+ klasses[:in].each do |klass|
39
+ @targets[klass] ||= []
40
+ @targets[klass] << {
41
+ :name => name,
42
+ :block => block,
43
+ }
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module MethodRepository
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'method_repository/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "method_repository"
8
+ gem.version = MethodRepository::VERSION
9
+ gem.authors = ["Kentaro Kuribayashi"]
10
+ gem.email = ["kentarok@gmail.com"]
11
+ gem.description = %q{Extracting redandunt code and commonalizing it in a different way.}
12
+ gem.summary = %q{Extracting redandunt code and commonalizing it in a different way}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_development_dependency "rspec", "~> 2.12"
21
+ end
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+
3
+ describe MethodRepository do
4
+ module Repository
5
+ include MethodRepository
6
+
7
+ insert :method1, in: %w[Foo Bar] do; end
8
+ insert :method2, in: %w[Baz] do; end
9
+ end
10
+
11
+ class Foo; end
12
+ class Bar; end
13
+ class Baz; end
14
+ class Qux; end
15
+
16
+ describe '.insert' do
17
+ it {
18
+ expect {
19
+ module Repository
20
+ insert :method3
21
+ end
22
+ }.to raise_error(
23
+ ArgumentError,
24
+ "`:in' parameter is required",
25
+ )
26
+ }
27
+ end
28
+
29
+ describe '.extended' do
30
+ context 'when classes are extended' do
31
+ before {
32
+ Foo.extend(Repository)
33
+ Bar.extend(Repository)
34
+ Baz.extend(Repository)
35
+ Qux.extend(Repository)
36
+ }
37
+
38
+ it {
39
+ expect(Foo.respond_to?(:method1)).to be true
40
+ expect(Bar.respond_to?(:method1)).to be true
41
+ expect(Baz.respond_to?(:method1)).to be false
42
+ expect(Qux.respond_to?(:method1)).to be false
43
+
44
+ expect(Foo.respond_to?(:method2)).to be false
45
+ expect(Bar.respond_to?(:method2)).to be false
46
+ expect(Baz.respond_to?(:method2)).to be true
47
+ expect(Qux.respond_to?(:method1)).to be false
48
+ }
49
+ end
50
+
51
+ context 'when objects are extended' do
52
+ let(:foo) { Foo.new }
53
+ let(:bar) { Bar.new }
54
+ let(:baz) { Baz.new }
55
+ let(:qux) { Qux.new }
56
+
57
+ before {
58
+ foo.extend(Repository)
59
+ bar.extend(Repository)
60
+ baz.extend(Repository)
61
+ qux.extend(Repository)
62
+ }
63
+
64
+ it {
65
+ expect(foo.respond_to?(:method1)).to be true
66
+ expect(bar.respond_to?(:method1)).to be true
67
+ expect(baz.respond_to?(:method1)).to be false
68
+ expect(qux.respond_to?(:method1)).to be false
69
+
70
+ expect(foo.respond_to?(:method2)).to be false
71
+ expect(bar.respond_to?(:method2)).to be false
72
+ expect(baz.respond_to?(:method2)).to be true
73
+ expect(qux.respond_to?(:method1)).to be false
74
+ }
75
+ end
76
+ end
77
+
78
+ describe '.included' do
79
+ before {
80
+ Foo.send(:include, Repository)
81
+ Bar.send(:include, Repository)
82
+ Baz.send(:include, Repository)
83
+ Qux.send(:include, Repository)
84
+ }
85
+
86
+ it {
87
+ expect(Foo.new.respond_to?(:method1)).to be true
88
+ expect(Bar.new.respond_to?(:method1)).to be true
89
+ expect(Baz.new.respond_to?(:method1)).to be false
90
+ expect(Qux.new.respond_to?(:method1)).to be false
91
+
92
+ expect(Foo.new.respond_to?(:method2)).to be false
93
+ expect(Bar.new.respond_to?(:method2)).to be false
94
+ expect(Baz.new.respond_to?(:method2)).to be true
95
+ expect(Qux.new.respond_to?(:method1)).to be false
96
+ }
97
+ end
98
+ end
@@ -0,0 +1,5 @@
1
+ $:.unshift File.expand_path("../../lib", __FILE__)
2
+ require 'method_repository'
3
+
4
+ RSpec.configure do |config|
5
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: method_repository
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kentaro Kuribayashi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.12'
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: '2.12'
30
+ description: Extracting redandunt code and commonalizing it in a different way.
31
+ email:
32
+ - kentarok@gmail.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - .gitignore
38
+ - Gemfile
39
+ - LICENSE.txt
40
+ - README.md
41
+ - Rakefile
42
+ - lib/method_repository.rb
43
+ - lib/method_repository/version.rb
44
+ - method_repository.gemspec
45
+ - spec/lib/method_repository_spec.rb
46
+ - spec/spec_helper.rb
47
+ homepage: ''
48
+ licenses: []
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 1.8.23
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Extracting redandunt code and commonalizing it in a different way
71
+ test_files:
72
+ - spec/lib/method_repository_spec.rb
73
+ - spec/spec_helper.rb
74
+ has_rdoc: