konstructor 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/Gemfile +0 -1
- data/README.md +56 -24
- data/bin/console +1 -6
- data/konstructor.gemspec +1 -0
- data/lib/konstructor.rb +2 -82
- data/lib/konstructor/core_ext.rb +0 -1
- data/lib/konstructor/main.rb +82 -0
- data/lib/konstructor/no_core_ext.rb +1 -0
- data/lib/konstructor/version.rb +1 -1
- metadata +17 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c470538008607d588c03a3f68fefb7800a88f83b
|
4
|
+
data.tar.gz: 6517dba98cd9ad1f387d9410dcbbc7d04b19accb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f4bcbf89a42a476af95f78bc08f33d314696f8da99f7c2120f059931d693c4eee149fd39bc64fbec79897d626f2c720a5a85d4def50ddedeae31422492f25d8
|
7
|
+
data.tar.gz: 0ff11473769c2673730bf80222699ee2501067c7cc4e37432a3ab14882ad005a45f75fd4188a6499998ae47460d8d626c80f93a8b2084df2db4e136f36433d5a
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,17 @@
|
|
1
|
+
[][gem]
|
2
|
+
[][travis]
|
3
|
+
[][coveralls]
|
4
|
+
|
5
|
+
[gem]: https://rubygems.org/gems/konstructor
|
6
|
+
[travis]: http://travis-ci.org/snovity/konstructor
|
7
|
+
[coveralls]: https://coveralls.io/r/snovity/konstructor
|
8
|
+
|
1
9
|
# Konstructor
|
2
10
|
|
3
11
|
Konstructor is a small gem that gives you multiple
|
4
12
|
constructors in Ruby.
|
5
13
|
|
6
|
-
|
14
|
+
Use `konstructor` keyword to define constructors additional to the defaul one:
|
7
15
|
```ruby
|
8
16
|
class SomeClass
|
9
17
|
konstructor
|
@@ -27,21 +35,21 @@ It's similar to having overloaded constructors in other languages.
|
|
27
35
|
Via Gemfile:
|
28
36
|
|
29
37
|
```ruby
|
30
|
-
gem 'konstructor'
|
38
|
+
gem 'konstructor'
|
31
39
|
```
|
32
40
|
|
33
41
|
and then execute `bundle`.
|
34
42
|
|
35
|
-
Uncomment require option to skip adding
|
36
|
-
`include Konstructor` every time you want to use `konstructor` keyword.
|
37
|
-
|
38
43
|
You can also install it without Bundler:
|
39
44
|
|
40
45
|
$ gem install konstructor
|
41
46
|
|
47
|
+
If you wish to manually include Konstructor in your classes only when
|
48
|
+
you need it, see [Manual include](https://github.com/snovity/konstructor/wiki/Manual-include) page.
|
49
|
+
|
42
50
|
## Usage
|
43
51
|
|
44
|
-
|
52
|
+
In simplest form `konstructor` creates a constructor from the next method.
|
45
53
|
|
46
54
|
```ruby
|
47
55
|
konstructor
|
@@ -53,11 +61,15 @@ When no names are given `konstructor` just affects the next method:
|
|
53
61
|
end
|
54
62
|
```
|
55
63
|
|
56
|
-
|
64
|
+
When method names are given, it creates constructors from
|
65
|
+
those methods without affecting the next method.
|
57
66
|
|
58
67
|
```ruby
|
59
68
|
konstructor :create, :recreate
|
60
69
|
|
70
|
+
def not_constructor
|
71
|
+
end
|
72
|
+
|
61
73
|
def create
|
62
74
|
end
|
63
75
|
|
@@ -65,7 +77,7 @@ When no names are given `konstructor` just affects the next method:
|
|
65
77
|
end
|
66
78
|
```
|
67
79
|
|
68
|
-
Call with names can be placed anywhere in class definition
|
80
|
+
Call with method names can be placed anywhere in class definition.
|
69
81
|
|
70
82
|
```ruby
|
71
83
|
def create
|
@@ -78,7 +90,7 @@ When no names are given `konstructor` just affects the next method:
|
|
78
90
|
```
|
79
91
|
|
80
92
|
In all above cases the class will have the default constructor
|
81
|
-
and two
|
93
|
+
and two additional ones.
|
82
94
|
|
83
95
|
```ruby
|
84
96
|
obj0 = SomeClass.new
|
@@ -88,8 +100,10 @@ When no names are given `konstructor` just affects the next method:
|
|
88
100
|
|
89
101
|
### Same as default constructor
|
90
102
|
|
91
|
-
|
92
|
-
|
103
|
+
Additional constructors work exactly the same way as
|
104
|
+
built-in Ruby constructor.
|
105
|
+
|
106
|
+
You can pass blocks to them.
|
93
107
|
|
94
108
|
```ruby
|
95
109
|
konstructor
|
@@ -101,7 +115,26 @@ obj = SomeClass.create(3) { |v| v*3 }
|
|
101
115
|
obj.val # 9
|
102
116
|
```
|
103
117
|
|
104
|
-
You can override
|
118
|
+
You can override them in subclasses and call `super`.
|
119
|
+
```ruby
|
120
|
+
class SomeClass
|
121
|
+
konstructor
|
122
|
+
def create(val)
|
123
|
+
@val = val
|
124
|
+
end
|
125
|
+
|
126
|
+
attr_reader :val
|
127
|
+
end
|
128
|
+
|
129
|
+
class SomeSubclass < SomeClass
|
130
|
+
def create(val1, val2)
|
131
|
+
super(val1 * val2)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
obj = SomeSubclass.create(2, 3)
|
136
|
+
obj.val # 6
|
137
|
+
```
|
105
138
|
Once method is a marked as konstructor in hierarchy,
|
106
139
|
it is always a konstructor.
|
107
140
|
|
@@ -111,8 +144,8 @@ mark it as konstructor and call the inherited one.
|
|
111
144
|
|
112
145
|
### Reserved names
|
113
146
|
|
114
|
-
Using reserved method names `new` and `initialize` for
|
115
|
-
constructor
|
147
|
+
Using reserved method names `new` and `initialize` for additional
|
148
|
+
constructor declaration will raise an error:
|
116
149
|
```ruby
|
117
150
|
konstructor
|
118
151
|
def initialize # raises Konstructor::ReservedNameError
|
@@ -133,9 +166,9 @@ define konstructor in `included` block.
|
|
133
166
|
### Using with other gems
|
134
167
|
|
135
168
|
Konstructor doesn't affect other gems, including those
|
136
|
-
that depend on metaprogramming, such as rake, thor, contracts, etc.
|
169
|
+
that depend on metaprogramming, such as [rake](https://github.com/ruby/rake), [thor](https://github.com/erikhuda/thor), [contracts](https://github.com/egonSchiele/contracts.ruby), etc.
|
137
170
|
|
138
|
-
For instnace, Konstructor works with contracts gem:
|
171
|
+
For instnace, this is how Konstructor works with contracts gem:
|
139
172
|
```ruby
|
140
173
|
class SomeClass
|
141
174
|
konstructor
|
@@ -147,11 +180,11 @@ For instnace, Konstructor works with contracts gem:
|
|
147
180
|
```
|
148
181
|
|
149
182
|
If you stumble upon a metaprogramming gem that
|
150
|
-
conflicts with Konstructor, please open an issue.
|
183
|
+
conflicts with Konstructor, please [open an issue](https://github.com/snovity/konstructor/issues/new).
|
151
184
|
|
152
185
|
### Removing default constructor
|
153
186
|
|
154
|
-
You can effectively remove default Ruby
|
187
|
+
You can effectively remove default Ruby constructor
|
155
188
|
by marking it as private:
|
156
189
|
```ruby
|
157
190
|
class SomeClass
|
@@ -163,10 +196,9 @@ end
|
|
163
196
|
|
164
197
|
Konstructor does all its work when class is being defined. Once class
|
165
198
|
has been defined, it's just standard Ruby instance creation.
|
166
|
-
Therefore,
|
199
|
+
Therefore, there is no runtime performance penalty.
|
167
200
|
|
168
|
-
|
169
|
-
to the one of `attr_accessor` or `ActiveSupport::Concern`.
|
201
|
+
Konstructor doesn't depend on other gems.
|
170
202
|
|
171
203
|
## Thread safety
|
172
204
|
|
@@ -175,8 +207,8 @@ Konstructor is thread safe.
|
|
175
207
|
## Details
|
176
208
|
|
177
209
|
Ruby constructor is a pair consisting of public factory method defined
|
178
|
-
on a class and a private instance method. Therefore,
|
179
|
-
`konstructor` marks instance method as private and defines a
|
210
|
+
on a class and a private instance method. Therefore, to achieve
|
211
|
+
its goal `konstructor` marks instance method as private and defines a
|
180
212
|
corresponding public class method with the same name.
|
181
213
|
|
182
214
|
You can check if certain instance method name has been declared as
|
@@ -188,7 +220,7 @@ Konstructor.is?(SomeClass, :recreate) # true
|
|
188
220
|
Konstructor.is?(SomeClass, :something_else) # false
|
189
221
|
```
|
190
222
|
|
191
|
-
It will return true even if
|
223
|
+
It will return true even if no such constructor has
|
192
224
|
been defined yet. Like:
|
193
225
|
```ruby
|
194
226
|
class SomeClass
|
data/bin/console
CHANGED
@@ -2,10 +2,5 @@
|
|
2
2
|
|
3
3
|
require 'bundler/setup'
|
4
4
|
require 'konstructor'
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
5
|
require 'pry'
|
11
|
-
Pry.start
|
6
|
+
Pry.start
|
data/konstructor.gemspec
CHANGED
@@ -31,6 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
32
32
|
spec.add_development_dependency 'pry-byebug', '~> 3.4'
|
33
33
|
spec.add_development_dependency 'activesupport', '~> 4.2'
|
34
|
+
spec.add_development_dependency 'coveralls', '~> 0.8.19'
|
34
35
|
|
35
36
|
# to test conflicts, specifying precise versions since below version 1 and no semver guarantees
|
36
37
|
spec.add_development_dependency 'thor', '0.19.4'
|
data/lib/konstructor.rb
CHANGED
@@ -1,82 +1,2 @@
|
|
1
|
-
require 'konstructor/
|
2
|
-
require 'konstructor/
|
3
|
-
require 'konstructor/simple_method_hook'
|
4
|
-
require 'konstructor/factory'
|
5
|
-
|
6
|
-
module Konstructor
|
7
|
-
|
8
|
-
module KonstructorMethod
|
9
|
-
private
|
10
|
-
|
11
|
-
# TODO: ADD DOCS
|
12
|
-
def konstructor(*new_names)
|
13
|
-
Konstructor.declare(self, new_names)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
DEFAULT_NAMES = [:initialize]
|
18
|
-
RESERVED_NAMES = [:new, :initialize]
|
19
|
-
|
20
|
-
class << self
|
21
|
-
def reserved?(name)
|
22
|
-
RESERVED_NAMES.include?(name.to_sym)
|
23
|
-
end
|
24
|
-
|
25
|
-
def default?(name)
|
26
|
-
DEFAULT_NAMES.include?(name.to_sym)
|
27
|
-
end
|
28
|
-
|
29
|
-
def declared?(klass, name)
|
30
|
-
konstructor = get_factory(klass)
|
31
|
-
if konstructor
|
32
|
-
konstructor.declared?(name.to_sym)
|
33
|
-
else
|
34
|
-
false
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def declare(klass, new_names)
|
39
|
-
setup_method_added_hook(klass)
|
40
|
-
get_or_init_factory(klass).declare(new_names)
|
41
|
-
end
|
42
|
-
|
43
|
-
def method_added_to_klass(klass, name)
|
44
|
-
get_or_init_factory(klass).method_added_to_klass(name)
|
45
|
-
end
|
46
|
-
|
47
|
-
def is?(klass, name)
|
48
|
-
default?(name) || declared?(klass, name)
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def get_factory(klass)
|
54
|
-
klass.instance_variable_get(:@konstructor)
|
55
|
-
end
|
56
|
-
|
57
|
-
def init_factory(klass)
|
58
|
-
# using variable @konstructor to minimize footprint, although saving factory there
|
59
|
-
klass.instance_variable_set(:@konstructor, Factory.new(klass))
|
60
|
-
end
|
61
|
-
|
62
|
-
def get_or_init_factory(klass)
|
63
|
-
get_factory(klass) || init_factory(klass)
|
64
|
-
end
|
65
|
-
|
66
|
-
def setup_method_added_hook(klass)
|
67
|
-
SimpleMethodHook.setup(klass)
|
68
|
-
end
|
69
|
-
|
70
|
-
# Overriden append_features prevents default behavior
|
71
|
-
# of including all the constants, variables to the base class.
|
72
|
-
# It adds only one method 'konstructor'.
|
73
|
-
def append_features(klass)
|
74
|
-
unless klass.is_a? Class
|
75
|
-
raise IncludeInModuleError, klass
|
76
|
-
end
|
77
|
-
|
78
|
-
klass.extend(KonstructorMethod)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|
1
|
+
require 'konstructor/main'
|
2
|
+
require 'konstructor/core_ext'
|
data/lib/konstructor/core_ext.rb
CHANGED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'konstructor/version'
|
2
|
+
require 'konstructor/exceptions'
|
3
|
+
require 'konstructor/simple_method_hook'
|
4
|
+
require 'konstructor/factory'
|
5
|
+
|
6
|
+
module Konstructor
|
7
|
+
|
8
|
+
module KonstructorMethod
|
9
|
+
private
|
10
|
+
|
11
|
+
# TODO: ADD DOCS
|
12
|
+
def konstructor(*new_names)
|
13
|
+
Konstructor.declare(self, new_names)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
DEFAULT_NAMES = [:initialize]
|
18
|
+
RESERVED_NAMES = [:new, :initialize]
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def reserved?(name)
|
22
|
+
RESERVED_NAMES.include?(name.to_sym)
|
23
|
+
end
|
24
|
+
|
25
|
+
def default?(name)
|
26
|
+
DEFAULT_NAMES.include?(name.to_sym)
|
27
|
+
end
|
28
|
+
|
29
|
+
def declared?(klass, name)
|
30
|
+
konstructor = get_factory(klass)
|
31
|
+
if konstructor
|
32
|
+
konstructor.declared?(name.to_sym)
|
33
|
+
else
|
34
|
+
false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def declare(klass, new_names)
|
39
|
+
setup_method_added_hook(klass)
|
40
|
+
get_or_init_factory(klass).declare(new_names)
|
41
|
+
end
|
42
|
+
|
43
|
+
def method_added_to_klass(klass, name)
|
44
|
+
get_or_init_factory(klass).method_added_to_klass(name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def is?(klass, name)
|
48
|
+
default?(name) || declared?(klass, name)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def get_factory(klass)
|
54
|
+
klass.instance_variable_get(:@konstructor)
|
55
|
+
end
|
56
|
+
|
57
|
+
def init_factory(klass)
|
58
|
+
# using variable @konstructor to minimize footprint, although saving factory there
|
59
|
+
klass.instance_variable_set(:@konstructor, Factory.new(klass))
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_or_init_factory(klass)
|
63
|
+
get_factory(klass) || init_factory(klass)
|
64
|
+
end
|
65
|
+
|
66
|
+
def setup_method_added_hook(klass)
|
67
|
+
SimpleMethodHook.setup(klass)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Overriden append_features prevents default behavior
|
71
|
+
# of including all the constants, variables to the base class.
|
72
|
+
# It adds only one method 'konstructor'.
|
73
|
+
def append_features(klass)
|
74
|
+
unless klass.is_a? Class
|
75
|
+
raise IncludeInModuleError, klass
|
76
|
+
end
|
77
|
+
|
78
|
+
klass.extend(KonstructorMethod)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'konstructor/main'
|
data/lib/konstructor/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: konstructor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dima Lashkov
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '4.2'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: coveralls
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.8.19
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.8.19
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: thor
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -146,6 +160,8 @@ files:
|
|
146
160
|
- lib/konstructor/exceptions.rb
|
147
161
|
- lib/konstructor/factory.rb
|
148
162
|
- lib/konstructor/konstructor_method_hook.rb
|
163
|
+
- lib/konstructor/main.rb
|
164
|
+
- lib/konstructor/no_core_ext.rb
|
149
165
|
- lib/konstructor/simple_method_hook.rb
|
150
166
|
- lib/konstructor/version.rb
|
151
167
|
homepage: https://github.com/snovity/konstructor
|