using_yaml 1.1.0 → 1.1.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/README.rdoc +27 -0
- data/Rakefile +9 -0
- data/VERSION +1 -1
- data/lib/using_yaml.rb +7 -6
- data/lib/using_yaml/array.rb +14 -21
- data/lib/using_yaml/hash.rb +17 -27
- data/using_yaml.gemspec +2 -3
- metadata +3 -4
- data/lib/using_yaml/nilclass.rb +0 -34
data/README.rdoc
CHANGED
@@ -82,6 +82,33 @@ By default, UsingYAML will return nil for missing files. It will also complain o
|
|
82
82
|
|
83
83
|
UsingYAML.squelch!
|
84
84
|
|
85
|
+
== Benchmark
|
86
|
+
|
87
|
+
There are two extremes when navigating hashes. Either we hit a nil
|
88
|
+
early, or we traverse successfully to the end. UsingYAML performs well regardless. Here are results using `ruby-1.8.7-p249 [ x86_64 ]`
|
89
|
+
|
90
|
+
=== Testing chains of nils
|
91
|
+
|
92
|
+
user system total real
|
93
|
+
normal 0.920000 0.040000 0.960000 ( 0.980095)
|
94
|
+
chained 0.900000 0.060000 0.960000 ( 0.973219)
|
95
|
+
|
96
|
+
=== Testing where the keys exist
|
97
|
+
|
98
|
+
user system total real
|
99
|
+
normal 2.780000 0.150000 2.930000 ( 2.930808)
|
100
|
+
chained 0.960000 0.060000 1.020000 ( 1.031477)
|
101
|
+
|
102
|
+
=== Results
|
103
|
+
|
104
|
+
While there are certainly other things to test, these benchmarks show
|
105
|
+
that the method chaining performs either almost as well (in the case
|
106
|
+
of nil.nil..) or significantly better (in the case of key.key..).
|
107
|
+
|
108
|
+
I'd definitely like to do some more testing. However, this is
|
109
|
+
primarily a convenience library to improve programmer happiness, so
|
110
|
+
these tests have made me happy enough for now.
|
111
|
+
|
85
112
|
== Note on Patches/Pull Requests
|
86
113
|
|
87
114
|
* Fork the project.
|
data/Rakefile
CHANGED
@@ -51,6 +51,15 @@ task :benchmark do
|
|
51
51
|
p = Person.new
|
52
52
|
p.children # "cache" the nil
|
53
53
|
n = 10000
|
54
|
+
|
55
|
+
puts "** Testing chains of nils **"
|
56
|
+
Benchmark.bmbm(10) do |x|
|
57
|
+
x.report("normal") { n.times do; p.children && p.children['something'] && p.children['invalid']; end }
|
58
|
+
x.report("chained") { n.times do; p.children.something.invalid; end }
|
59
|
+
end
|
60
|
+
|
61
|
+
p.children = { 'something' => { 'valid' => 1 } }
|
62
|
+
puts "\n** Testing where the keys exist **"
|
54
63
|
Benchmark.bmbm(10) do |x|
|
55
64
|
x.report("normal") { n.times do; p.children && p.children['something'] && p.children['invalid']; end }
|
56
65
|
x.report("chained") { n.times do; p.children.something.invalid; end }
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.1.
|
1
|
+
1.1.1
|
data/lib/using_yaml.rb
CHANGED
@@ -22,7 +22,12 @@ end
|
|
22
22
|
#
|
23
23
|
# See +using_yaml+ for usage information.
|
24
24
|
module UsingYAML
|
25
|
-
|
25
|
+
NilExt = Module.new do
|
26
|
+
define_method(:method_missing) do |*args|
|
27
|
+
self
|
28
|
+
end
|
29
|
+
end
|
30
|
+
NilClass = nil.extend(NilExt)
|
26
31
|
|
27
32
|
class << self
|
28
33
|
# Extends the incoming Array/Hash with magic which makes it
|
@@ -35,11 +40,7 @@ module UsingYAML
|
|
35
40
|
when Hash
|
36
41
|
add_hash_extensions(object, pathname)
|
37
42
|
when ::NilClass
|
38
|
-
|
39
|
-
add_nilclass_extensions(object, pathname)
|
40
|
-
else
|
41
|
-
UsingYAML::NilClass
|
42
|
-
end
|
43
|
+
UsingYAML::NilClass
|
43
44
|
end
|
44
45
|
|
45
46
|
object
|
data/lib/using_yaml/array.rb
CHANGED
@@ -2,29 +2,22 @@ module UsingYAML
|
|
2
2
|
# Calls add_extensions on all children. Also defines a +save+ method
|
3
3
|
# iff this is a top-level UsingYAML object (see below for details).
|
4
4
|
def self.add_array_extensions(array, pathname)
|
5
|
-
#
|
6
|
-
|
7
|
-
#
|
8
|
-
|
9
|
-
# Recursively continue to extend.
|
10
|
-
UsingYAML.add_extensions(item)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Define a save method if a pathname was supplied (only happens
|
14
|
-
# on the top-level object - that is, example.foo will have a
|
15
|
-
# +save+, but example.foo.bar will not).
|
16
|
-
if pathname
|
17
|
-
define_method(:save) do
|
18
|
-
# Serialise using +to_yaml+
|
19
|
-
File.open(pathname, 'w') do |f|
|
20
|
-
f.puts self.to_yaml
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
5
|
+
# Iterate over the items
|
6
|
+
array.each do |item|
|
7
|
+
# Recursively continue to extend.
|
8
|
+
UsingYAML.add_extensions(item)
|
24
9
|
end
|
25
|
-
|
10
|
+
|
26
11
|
# Load in the extensions for this instance
|
27
|
-
array.
|
12
|
+
array.instance_eval <<-RUBY
|
13
|
+
def save
|
14
|
+
# Serialise using +to_yaml+
|
15
|
+
File.open("#{pathname}", 'w') do |f|
|
16
|
+
f.puts self.to_yaml
|
17
|
+
end
|
18
|
+
end
|
19
|
+
RUBY
|
20
|
+
|
28
21
|
array
|
29
22
|
end
|
30
23
|
end
|
data/lib/using_yaml/hash.rb
CHANGED
@@ -2,14 +2,13 @@ module UsingYAML
|
|
2
2
|
# Calls add_extensions on all children. Also defines a +save+ method
|
3
3
|
# iff this is a top-level UsingYAML object (see below for details).
|
4
4
|
def self.add_hash_extensions(hash, pathname)
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
UsingYAML.add_extensions(value)
|
10
|
-
end
|
5
|
+
# Recursively continue to extend.
|
6
|
+
hash.each_pair do |key, value|
|
7
|
+
UsingYAML.add_extensions(value)
|
8
|
+
end
|
11
9
|
|
12
|
-
|
10
|
+
hash.instance_eval <<-RUBY
|
11
|
+
def method_missing(*args)
|
13
12
|
name = args.shift.to_s
|
14
13
|
|
15
14
|
if args.empty?
|
@@ -21,39 +20,30 @@ module UsingYAML
|
|
21
20
|
# consistently with the other key-value pairs.
|
22
21
|
key = $1
|
23
22
|
value = args.first
|
24
|
-
|
23
|
+
|
25
24
|
# Save the value in the hashtable
|
26
25
|
send(:[]=, key, UsingYAML.add_extensions(value))
|
27
|
-
|
28
|
-
# Define the new reader (as above)
|
29
|
-
new_reader_extension = Module.new do
|
30
|
-
define_method(key) do
|
31
|
-
send(:[], key) || UsingYAML.add_extensions(nil)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
extend(new_reader_extension)
|
35
|
-
|
36
26
|
value
|
37
27
|
else
|
38
28
|
super(name, args)
|
39
29
|
end
|
40
30
|
end
|
31
|
+
RUBY
|
41
32
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
33
|
+
# Define a save method if a pathname was supplied (only happens
|
34
|
+
# on the top-level object - that is, example.foo will have a
|
35
|
+
# +save+, but example.foo.bar will not).
|
36
|
+
if pathname
|
37
|
+
hash.instance_eval <<-RUBY
|
38
|
+
def save
|
47
39
|
# Serialise using +to_yaml+
|
48
|
-
File.open(pathname, 'w') do |f|
|
40
|
+
File.open("#{pathname}", 'w') do |f|
|
49
41
|
f.puts self.to_yaml
|
50
42
|
end
|
51
43
|
end
|
52
|
-
|
44
|
+
RUBY
|
53
45
|
end
|
54
|
-
|
55
|
-
# Load in the extensions for this instance
|
56
|
-
hash.extend(extensions)
|
46
|
+
|
57
47
|
hash
|
58
48
|
end
|
59
49
|
end
|
data/using_yaml.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{using_yaml}
|
8
|
-
s.version = "1.1.
|
8
|
+
s.version = "1.1.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Marc Bowes"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-04-21}
|
13
13
|
s.description = %q{"Load, save and use YAML files as if they were objects"}
|
14
14
|
s.email = %q{marcbowes@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -26,7 +26,6 @@ Gem::Specification.new do |s|
|
|
26
26
|
"lib/using_yaml.rb",
|
27
27
|
"lib/using_yaml/array.rb",
|
28
28
|
"lib/using_yaml/hash.rb",
|
29
|
-
"lib/using_yaml/nilclass.rb",
|
30
29
|
"spec/spec_helper.rb",
|
31
30
|
"spec/using_yaml/path_spec.rb",
|
32
31
|
"spec/using_yaml/using_yaml_spec.rb",
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 1.1.
|
8
|
+
- 1
|
9
|
+
version: 1.1.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Marc Bowes
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-04-21 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -48,7 +48,6 @@ files:
|
|
48
48
|
- lib/using_yaml.rb
|
49
49
|
- lib/using_yaml/array.rb
|
50
50
|
- lib/using_yaml/hash.rb
|
51
|
-
- lib/using_yaml/nilclass.rb
|
52
51
|
- spec/spec_helper.rb
|
53
52
|
- spec/using_yaml/path_spec.rb
|
54
53
|
- spec/using_yaml/using_yaml_spec.rb
|
data/lib/using_yaml/nilclass.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
module UsingYAML
|
2
|
-
def self.add_nilclass_extensions(instance, pathname)
|
3
|
-
extensions = Module.new do
|
4
|
-
define_method(:method_missing) do |*args|
|
5
|
-
# Child objects should not have #save
|
6
|
-
if respond_to? :save
|
7
|
-
UsingYAML::NilClass
|
8
|
-
else
|
9
|
-
# One nil is the same as the next :)
|
10
|
-
self
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
# Define a save method if a pathname was supplied (only happens
|
15
|
-
# on the top-level object - that is, example.foo will have a
|
16
|
-
# +save+, but example.foo.bar will not).
|
17
|
-
if pathname
|
18
|
-
# Being nil translates to "no file", not to "empty file", so we
|
19
|
-
# want to actually delete any existing file. This is a semantic
|
20
|
-
# difference, but important: there is a huge different between
|
21
|
-
# an _empty_ file and a _non-existant_ file. YAML does not
|
22
|
-
# reflect this difference, so we do.
|
23
|
-
define_method(:save) do
|
24
|
-
# If we can't delete it (permissions, ENOENT..), then there
|
25
|
-
# ain't much we can do, so just squelch the error.
|
26
|
-
FileUtils.rm(pathname) rescue nil
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
instance.extend(extensions)
|
32
|
-
instance
|
33
|
-
end
|
34
|
-
end
|