better_struct 0.2.0 → 0.2.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.
- checksums.yaml +4 -4
- data/README.md +13 -18
- data/better_struct.gemspec +0 -2
- data/lib/better_struct.rb +11 -22
- data/lib/better_struct/methodize.rb +46 -0
- data/lib/better_struct/version.rb +1 -1
- metadata +3 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63739e5a654591d3d685a383a163fca50902f3b2
|
4
|
+
data.tar.gz: 8ac3510abea38370cbe2d67a951deec7d1c002bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45b9c991c3010cfd5ce2b25a853bbffd2f0bef51b6479770571141b8b293b01ceef9ab93102d6054e14a91aae4715b1172768afd37791d0a0d4130d457dc9b76
|
7
|
+
data.tar.gz: 03f58914d44f74f1d4a2eafb045066b338723f13e603fa32af51f9555aec93ecc1097d1c4aab056d3c7f1803a75807ebc1fef0d3651a10f2fb49661bbb9d0363
|
data/README.md
CHANGED
@@ -10,12 +10,12 @@ It behaves like an OpenStruct on steroids with monad.
|
|
10
10
|
hash = { "FooBar1" => { foo_bar2: "Hello World!" } }
|
11
11
|
|
12
12
|
# Instead of this:
|
13
|
-
if hash["FooBar1"] && hash["FooBar1"][:foo_bar2]
|
14
|
-
|
13
|
+
if hash["FooBar1"] && hash["FooBar1"][:foo_bar2] && hash["FooBar1"][:foo_bar2].respond_to?(:sub)
|
14
|
+
hash["FooBar1"][:foo_bar2].sub("Hello ", "") # => "World!"
|
15
15
|
end
|
16
16
|
|
17
17
|
# Simply use:
|
18
|
-
|
18
|
+
BetterStruct.new(hash).foo_bar1.foo_bar2.sub("Hello ", "").value # => "World!"
|
19
19
|
```
|
20
20
|
|
21
21
|
## Installation
|
@@ -39,7 +39,7 @@ Or install it yourself as:
|
|
39
39
|
#### Maybe monad
|
40
40
|
|
41
41
|
```ruby
|
42
|
-
BetterStruct.new(nil) == BetterStruct.new(nil).
|
42
|
+
BetterStruct.new(nil) == BetterStruct.new(nil).this_method.does_not_exist # => true
|
43
43
|
```
|
44
44
|
|
45
45
|
#### Everything is wrapped
|
@@ -47,21 +47,16 @@ BetterStruct.new(nil) == BetterStruct.new(nil).some_method # => true
|
|
47
47
|
```ruby
|
48
48
|
better_struct = BetterStruct.new("foobar")
|
49
49
|
|
50
|
-
better_struct[0..2].is_a?(BetterStruct) # => true
|
51
50
|
better_struct[0..2] == BetterStruct.new("foo") # => true
|
52
51
|
```
|
53
52
|
|
54
53
|
```ruby
|
55
54
|
better_struct = BetterStruct.new([1, 2, 3])
|
56
55
|
|
57
|
-
|
58
|
-
|
59
|
-
result.is_a?(BetterStruct) # => true
|
60
|
-
result == BetterStruct.new(true) # => true
|
61
|
-
|
56
|
+
better_struct.all? { |i| i.is_a?(BetterStruct) } == BetterStruct.new(true) # => true
|
62
57
|
```
|
63
58
|
|
64
|
-
#### Like OpenStruct
|
59
|
+
#### Like an OpenStruct on steroids
|
65
60
|
|
66
61
|
```ruby
|
67
62
|
some_hash = { "FooBar1" => { foo_bar2: "Hello World!" } }
|
@@ -85,21 +80,21 @@ better_struct.gsub("foo", "super-").value == "super-foo" # => true
|
|
85
80
|
|
86
81
|
## Benchmarking
|
87
82
|
|
88
|
-
|
83
|
+
**BetterStruct** is even faster than an OpenStruct:
|
89
84
|
|
90
85
|
```
|
91
86
|
$ ruby scripts/benchmark.rb
|
92
87
|
|
93
88
|
Calculating -------------------------------------
|
94
|
-
OpenStruct
|
95
|
-
BetterStruct 7.
|
89
|
+
OpenStruct 7.334k i/100ms
|
90
|
+
BetterStruct 7.856k i/100ms
|
96
91
|
-------------------------------------------------
|
97
|
-
OpenStruct 75.
|
98
|
-
BetterStruct
|
92
|
+
OpenStruct 75.971k (± 7.1%) i/s - 381.368k
|
93
|
+
BetterStruct 84.520k (± 4.5%) i/s - 424.224k
|
99
94
|
|
100
95
|
Comparison:
|
101
|
-
BetterStruct:
|
102
|
-
OpenStruct:
|
96
|
+
BetterStruct: 84519.8 i/s
|
97
|
+
OpenStruct: 75971.1 i/s - 1.11x slower
|
103
98
|
```
|
104
99
|
|
105
100
|
## Contributing
|
data/better_struct.gemspec
CHANGED
@@ -18,8 +18,6 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "activesupport", ">= 3.2.0"
|
22
|
-
|
23
21
|
spec.add_development_dependency "bundler", "~> 1.7"
|
24
22
|
spec.add_development_dependency "rake", "~> 10.0"
|
25
23
|
spec.add_development_dependency "minitest", "~> 5.5"
|
data/lib/better_struct.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require "
|
2
|
-
|
1
|
+
require "set"
|
2
|
+
require_relative "./better_struct/version"
|
3
|
+
require_relative "./better_struct/methodize"
|
3
4
|
|
4
5
|
class BetterStruct
|
5
|
-
PARAMETERIZE_SEPARATOR = "_".freeze
|
6
6
|
EQUAL_SIGN = "=".freeze
|
7
7
|
MAP_METHOD_NAMES = %i(map map!).to_set.freeze
|
8
8
|
|
@@ -26,21 +26,11 @@ class BetterStruct
|
|
26
26
|
|
27
27
|
private
|
28
28
|
|
29
|
-
def methodize(string)
|
30
|
-
result = ActiveSupport::Inflector.underscore(string)
|
31
|
-
|
32
|
-
if result =~ /[^\w]/
|
33
|
-
ActiveSupport::Inflector.parameterize(result, PARAMETERIZE_SEPARATOR)
|
34
|
-
else
|
35
|
-
result
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
29
|
def wrap(value)
|
40
30
|
value.is_a?(self.class) ? self : self.class.new(value)
|
41
31
|
end
|
42
32
|
|
43
|
-
def wrap_block_args(
|
33
|
+
def wrap_block_args(&block)
|
44
34
|
return if block.nil?
|
45
35
|
|
46
36
|
Proc.new do |*args|
|
@@ -52,16 +42,15 @@ private
|
|
52
42
|
def method_missing(method_name, *args, &block)
|
53
43
|
if value.respond_to?(method_name)
|
54
44
|
delegate_method(method_name, *args, &block)
|
55
|
-
elsif assignment?(method_name
|
56
|
-
|
57
|
-
@defined_methods[attribute] = args.first
|
45
|
+
elsif assignment?(method_name) && defined_methods
|
46
|
+
@defined_methods[methodize(method_name[0...-1])] = args.first
|
58
47
|
else
|
59
48
|
wrap(defined_methods[method_name.to_s])
|
60
49
|
end
|
61
50
|
end
|
62
51
|
|
63
|
-
def assignment?(method_name
|
64
|
-
method_name[-1] == EQUAL_SIGN
|
52
|
+
def assignment?(method_name)
|
53
|
+
method_name[-1] == EQUAL_SIGN
|
65
54
|
end
|
66
55
|
|
67
56
|
def defined_methods
|
@@ -77,12 +66,12 @@ private
|
|
77
66
|
end
|
78
67
|
|
79
68
|
def delegate_method(method_name, *args, &block)
|
80
|
-
result =
|
69
|
+
result = value.public_send(method_name, *unwrap_items(args), &wrap_block_args(&block))
|
81
70
|
|
82
71
|
if MAP_METHOD_NAMES.include?(method_name)
|
83
|
-
wrap(unwrap_items(result
|
72
|
+
wrap(unwrap_items(result))
|
84
73
|
else
|
85
|
-
result
|
74
|
+
wrap(result)
|
86
75
|
end
|
87
76
|
end
|
88
77
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class BetterStruct
|
2
|
+
EMPTY_STRING = "".freeze
|
3
|
+
UNDERSCORE_SIGN = "_".freeze
|
4
|
+
|
5
|
+
TRANSLITERATION_FROM = "ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž".freeze
|
6
|
+
TRANSLITERATION_TO = "AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz".freeze
|
7
|
+
|
8
|
+
UPCASE_REGEXP = /[A-Z]/.freeze
|
9
|
+
NOT_UNDERSCORED_REGEXP = /[^a-z0-9_]/.freeze
|
10
|
+
NON_ENGLISH_REGEXP = /[#{ TRANSLITERATION_FROM }]/.freeze
|
11
|
+
UNDERSCORE_DUPLICATES_REGEXP = /#{ UNDERSCORE_SIGN }{2,}/.freeze
|
12
|
+
UNDERSCORE_BEGIN_OR_END_REGEXP = /^#{ UNDERSCORE_SIGN }|#{ UNDERSCORE_SIGN }$/.freeze
|
13
|
+
CAMELCASE_ABBREVIATION_REGEX = /([A-Z\d]+)([A-Z][a-z])/.freeze
|
14
|
+
CAMELCASE_REGEX = /([a-z\d])([A-Z])/.freeze
|
15
|
+
|
16
|
+
UNDERSCORE_MASK = '\1_\2'.freeze
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def methodize(string)
|
21
|
+
return string unless string =~ NOT_UNDERSCORED_REGEXP
|
22
|
+
|
23
|
+
string = string.dup
|
24
|
+
|
25
|
+
transliterate!(string)
|
26
|
+
underscore!(string)
|
27
|
+
string
|
28
|
+
end
|
29
|
+
|
30
|
+
def transliterate!(string)
|
31
|
+
if string =~ NON_ENGLISH_REGEXP
|
32
|
+
string.tr!(TRANSLITERATION_FROM, TRANSLITERATION_TO)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def underscore!(string)
|
37
|
+
if string =~ NOT_UNDERSCORED_REGEXP
|
38
|
+
string.gsub!(CAMELCASE_ABBREVIATION_REGEX, UNDERSCORE_MASK)
|
39
|
+
string.gsub!(CAMELCASE_REGEX, UNDERSCORE_MASK)
|
40
|
+
string.downcase!
|
41
|
+
string.gsub!(NOT_UNDERSCORED_REGEXP, UNDERSCORE_SIGN)
|
42
|
+
string.gsub!(UNDERSCORE_DUPLICATES_REGEXP, UNDERSCORE_SIGN)
|
43
|
+
string.gsub!(UNDERSCORE_BEGIN_OR_END_REGEXP, EMPTY_STRING)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: better_struct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evgeny Li
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: activesupport
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ! '>='
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 3.2.0
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ! '>='
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 3.2.0
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: bundler
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +108,7 @@ files:
|
|
122
108
|
- Rakefile
|
123
109
|
- better_struct.gemspec
|
124
110
|
- lib/better_struct.rb
|
111
|
+
- lib/better_struct/methodize.rb
|
125
112
|
- lib/better_struct/version.rb
|
126
113
|
- test/better_struct_test.rb
|
127
114
|
homepage: https://github.com/exAspArk/better_struct
|