using_yaml 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.0
1
+ 1.1.1
@@ -22,7 +22,12 @@ end
22
22
  #
23
23
  # See +using_yaml+ for usage information.
24
24
  module UsingYAML
25
- NilClass = add_nilclass_extensions(nil, nil)
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
- if pathname
39
- add_nilclass_extensions(object, pathname)
40
- else
41
- UsingYAML::NilClass
42
- end
43
+ UsingYAML::NilClass
43
44
  end
44
45
 
45
46
  object
@@ -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
- # Here we define a Module to extend the array
6
- extensions = Module.new do
7
- # Iterate over the items
8
- array.each do |item|
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.extend(extensions)
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
@@ -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
- # Here we define a Module to extend the hash
6
- extensions = Module.new do
7
- # Recursively continue to extend.
8
- hash.each_pair do |key, value|
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
- define_method(:method_missing) do |*args|
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
- # Define a save method if a pathname was supplied (only happens
43
- # on the top-level object - that is, example.foo will have a
44
- # +save+, but example.foo.bar will not).
45
- if pathname
46
- define_method(:save) do
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
- end
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
@@ -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.0"
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-03-30}
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
- - 0
9
- version: 1.1.0
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-03-30 00:00:00 +02:00
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
@@ -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