thinreports 0.6.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. data/.yardopts +1 -0
  2. data/README.rdoc +100 -0
  3. data/Rakefile +10 -0
  4. data/doc/yardoc_templates/default/layout/html/footer.erb +10 -0
  5. data/lib/thinreports.rb +11 -0
  6. data/lib/thinreports/core.rb +20 -0
  7. data/lib/thinreports/core/errors.rb +58 -0
  8. data/lib/thinreports/core/events.rb +71 -0
  9. data/lib/thinreports/core/ext.rb +5 -0
  10. data/lib/thinreports/core/ext/array.rb +19 -0
  11. data/lib/thinreports/core/ext/hash.rb +19 -0
  12. data/lib/thinreports/core/ext/object.rb +25 -0
  13. data/lib/thinreports/core/format.rb +14 -0
  14. data/lib/thinreports/core/format/base.rb +93 -0
  15. data/lib/thinreports/core/format/builder.rb +65 -0
  16. data/lib/thinreports/core/ordered_hash.rb +39 -0
  17. data/lib/thinreports/core/page.rb +91 -0
  18. data/lib/thinreports/core/shape.rb +53 -0
  19. data/lib/thinreports/core/shape/base.rb +16 -0
  20. data/lib/thinreports/core/shape/base/interface.rb +38 -0
  21. data/lib/thinreports/core/shape/base/internal.rb +60 -0
  22. data/lib/thinreports/core/shape/basic.rb +15 -0
  23. data/lib/thinreports/core/shape/basic/format.rb +26 -0
  24. data/lib/thinreports/core/shape/basic/interface.rb +57 -0
  25. data/lib/thinreports/core/shape/basic/internal.rb +29 -0
  26. data/lib/thinreports/core/shape/list.rb +25 -0
  27. data/lib/thinreports/core/shape/list/configuration.rb +33 -0
  28. data/lib/thinreports/core/shape/list/events.rb +30 -0
  29. data/lib/thinreports/core/shape/list/format.rb +72 -0
  30. data/lib/thinreports/core/shape/list/manager.rb +209 -0
  31. data/lib/thinreports/core/shape/list/page.rb +118 -0
  32. data/lib/thinreports/core/shape/list/page_state.rb +40 -0
  33. data/lib/thinreports/core/shape/list/section_format.rb +32 -0
  34. data/lib/thinreports/core/shape/list/section_interface.rb +48 -0
  35. data/lib/thinreports/core/shape/list/section_internal.rb +29 -0
  36. data/lib/thinreports/core/shape/list/store.rb +34 -0
  37. data/lib/thinreports/core/shape/manager.rb +14 -0
  38. data/lib/thinreports/core/shape/manager/format.rb +28 -0
  39. data/lib/thinreports/core/shape/manager/internal.rb +87 -0
  40. data/lib/thinreports/core/shape/manager/target.rb +85 -0
  41. data/lib/thinreports/core/shape/tblock.rb +16 -0
  42. data/lib/thinreports/core/shape/tblock/format.rb +36 -0
  43. data/lib/thinreports/core/shape/tblock/formatter.rb +32 -0
  44. data/lib/thinreports/core/shape/tblock/formatter/basic.rb +38 -0
  45. data/lib/thinreports/core/shape/tblock/formatter/datetime.rb +21 -0
  46. data/lib/thinreports/core/shape/tblock/formatter/number.rb +49 -0
  47. data/lib/thinreports/core/shape/tblock/formatter/padding.rb +43 -0
  48. data/lib/thinreports/core/shape/tblock/interface.rb +52 -0
  49. data/lib/thinreports/core/shape/tblock/internal.rb +70 -0
  50. data/lib/thinreports/core/shape/text.rb +15 -0
  51. data/lib/thinreports/core/shape/text/format.rb +25 -0
  52. data/lib/thinreports/core/shape/text/interface.rb +16 -0
  53. data/lib/thinreports/core/shape/text/internal.rb +17 -0
  54. data/lib/thinreports/core/utils.rb +48 -0
  55. data/lib/thinreports/generator.rb +30 -0
  56. data/lib/thinreports/generator/base.rb +49 -0
  57. data/lib/thinreports/generator/pdf.rb +63 -0
  58. data/lib/thinreports/generator/pdf/document.rb +171 -0
  59. data/lib/thinreports/generator/pdf/document/draw_shape.rb +74 -0
  60. data/lib/thinreports/generator/pdf/document/font.rb +59 -0
  61. data/lib/thinreports/generator/pdf/document/graphics.rb +42 -0
  62. data/lib/thinreports/generator/pdf/document/graphics/attributes.rb +92 -0
  63. data/lib/thinreports/generator/pdf/document/graphics/basic.rb +132 -0
  64. data/lib/thinreports/generator/pdf/document/graphics/image.rb +51 -0
  65. data/lib/thinreports/generator/pdf/document/graphics/text.rb +130 -0
  66. data/lib/thinreports/generator/pdf/document/parse_color.rb +51 -0
  67. data/lib/thinreports/generator/pdf/document/parse_svg.rb +102 -0
  68. data/lib/thinreports/generator/pdf/drawer.rb +16 -0
  69. data/lib/thinreports/generator/pdf/drawer/base.rb +56 -0
  70. data/lib/thinreports/generator/pdf/drawer/list.rb +39 -0
  71. data/lib/thinreports/generator/pdf/drawer/list_section.rb +46 -0
  72. data/lib/thinreports/generator/pdf/drawer/page.rb +101 -0
  73. data/lib/thinreports/generator/pdf/prawn_ext.rb +36 -0
  74. data/lib/thinreports/generator/pxd.rb +75 -0
  75. data/lib/thinreports/generator/pxd/helper.rb +33 -0
  76. data/lib/thinreports/generator/pxd/list_renderer.rb +58 -0
  77. data/lib/thinreports/generator/pxd/page_renderer.rb +75 -0
  78. data/lib/thinreports/layout.rb +17 -0
  79. data/lib/thinreports/layout/base.rb +78 -0
  80. data/lib/thinreports/layout/configuration.rb +27 -0
  81. data/lib/thinreports/layout/format.rb +77 -0
  82. data/lib/thinreports/layout/version.rb +43 -0
  83. data/lib/thinreports/report.rb +31 -0
  84. data/lib/thinreports/report/base.rb +160 -0
  85. data/lib/thinreports/report/events.rb +32 -0
  86. data/lib/thinreports/report/internal.rb +131 -0
  87. data/resources/fonts/IPA_Font_License_Agreement_v1.0.txt +117 -0
  88. data/resources/fonts/ipag.ttf +0 -0
  89. data/resources/fonts/ipagp.ttf +0 -0
  90. data/resources/fonts/ipam.ttf +0 -0
  91. data/resources/fonts/ipamp.ttf +0 -0
  92. data/tasks/clean.rake +6 -0
  93. data/tasks/doc.rake +13 -0
  94. data/tasks/test.rake +18 -0
  95. data/test/unit/core/ext/array_spec.rb +29 -0
  96. data/test/unit/core/ext/hash_spec.rb +29 -0
  97. data/test/unit/core/ext/object_spec.rb +30 -0
  98. data/test/unit/core/format/test_base.rb +148 -0
  99. data/test/unit/core/format/test_builder.rb +114 -0
  100. data/test/unit/core/ordered_hash_spec.rb +51 -0
  101. data/test/unit/core/shape/base/test_interface.rb +52 -0
  102. data/test/unit/core/shape/base/test_internal.rb +109 -0
  103. data/test/unit/core/shape/basic/test_format.rb +59 -0
  104. data/test/unit/core/shape/basic/test_interface.rb +70 -0
  105. data/test/unit/core/shape/basic/test_internal.rb +42 -0
  106. data/test/unit/core/shape/list/test_configuration.rb +52 -0
  107. data/test/unit/core/shape/list/test_events.rb +28 -0
  108. data/test/unit/core/shape/list/test_format.rb +71 -0
  109. data/test/unit/core/shape/list/test_page.rb +10 -0
  110. data/test/unit/core/shape/list/test_page_state.rb +31 -0
  111. data/test/unit/core/shape/list/test_section_format.rb +46 -0
  112. data/test/unit/core/shape/list/test_section_interface.rb +52 -0
  113. data/test/unit/core/shape/list/test_section_internal.rb +30 -0
  114. data/test/unit/core/shape/list/test_store.rb +41 -0
  115. data/test/unit/core/shape/manager/test_format.rb +40 -0
  116. data/test/unit/core/shape/manager/test_internal.rb +137 -0
  117. data/test/unit/core/shape/manager/test_target.rb +109 -0
  118. data/test/unit/core/shape/tblock/formatter/test_basic.rb +24 -0
  119. data/test/unit/core/shape/tblock/formatter/test_datetime.rb +47 -0
  120. data/test/unit/core/shape/tblock/formatter/test_number.rb +76 -0
  121. data/test/unit/core/shape/tblock/formatter/test_padding.rb +72 -0
  122. data/test/unit/core/shape/tblock/test_format.rb +125 -0
  123. data/test/unit/core/shape/tblock/test_formatter.rb +28 -0
  124. data/test/unit/core/shape/tblock/test_interface.rb +40 -0
  125. data/test/unit/core/shape/tblock/test_internal.rb +139 -0
  126. data/test/unit/core/shape/text/test_format.rb +73 -0
  127. data/test/unit/core/shape/text/test_internal.rb +21 -0
  128. data/test/unit/core/test_events.rb +91 -0
  129. data/test/unit/core/test_shape.rb +35 -0
  130. data/test/unit/core/utils_spec.rb +56 -0
  131. data/test/unit/generator/pdf/document/graphics/test_attributes.rb +103 -0
  132. data/test/unit/generator/pdf/document/test_font.rb +54 -0
  133. data/test/unit/generator/pdf/document/test_graphics.rb +43 -0
  134. data/test/unit/generator/pdf/document/test_parse_color.rb +30 -0
  135. data/test/unit/generator/test_base.rb +51 -0
  136. data/test/unit/helper.rb +37 -0
  137. data/test/unit/layout/test_base.rb +92 -0
  138. data/test/unit/layout/test_configuration.rb +46 -0
  139. data/test/unit/layout/test_format.rb +104 -0
  140. data/test/unit/layout/test_version.rb +62 -0
  141. data/test/unit/report/test_base.rb +187 -0
  142. data/test/unit/report/test_events.rb +22 -0
  143. data/test/unit/report/test_internal.rb +234 -0
  144. data/test/unit/test_layout.rb +12 -0
  145. data/test/unit/test_report.rb +30 -0
  146. metadata +218 -0
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --no-private
data/README.rdoc ADDED
@@ -0,0 +1,100 @@
1
+ = ThinReports Generator
2
+
3
+ ThinReports is Open Source Reporting Solution for Ruby.
4
+ And it provide you these tools.
5
+
6
+ * ThinReports Editor (GUI Layout Editor)
7
+ * ThinReports Generator (Report Generation Interface for Ruby)
8
+
9
+ Please refer to {Official Site}[http://www.thinreports.org/] and
10
+ {Project Site}[http://osc.matsukei.net/projects/thinreports/wiki] for more details.
11
+
12
+ == Quick Start
13
+
14
+ Getting started with ThinReports Generator can be as simple as:
15
+
16
+ require 'thinreports'
17
+
18
+ report = ThinReports::Report.new :layout => 'report.tlf'
19
+ report.start_new_page do
20
+ page.item(:title).value('ThinReports')
21
+ end
22
+
23
+ report.generate_file(:pdf, 'report.pdf')
24
+
25
+ Or can be as:
26
+
27
+ ThinReports::Report.generate_file(:pdf, 'report.pdf', :layout => 'report.tlf') do
28
+ start_new_page
29
+
30
+ page.item(:title).value('ThinReports')
31
+
32
+ start_new_page
33
+
34
+ page.item(:title).value('ThinReports').style(:fill, 'red')
35
+ end
36
+
37
+ {Learn more}[http://osc.matsukei.net/projects/thinreports/wiki/Getting_Started].
38
+
39
+ == Documentation
40
+
41
+ We provide you a few useful resources to help you get started with ThinReports.
42
+
43
+ * {Getting Started}[http://osc.matsukei.net/projects/thinreports/wiki/Getting_Started]
44
+ * {Guide}[http://osc.matsukei.net/projects/thinreports/wiki/Guide]
45
+ * {Roadmap}[http://osc.matsukei.net/projects/thinreports/roadmap]
46
+ * {Changelog}[http://osc.matsukei.net/projects/thinreports/wiki/Changelog]
47
+
48
+ == Source Code
49
+
50
+ Please see {here}[http://osc.matsukei.net/projects/thinreports/wiki/Source_Code].
51
+
52
+ == Community Support
53
+
54
+ * {Open Forum}[http://osc.matsukei.net/projects/thinreports/boards]
55
+ * {Issue Tracker (Read-Only)}[http://osc.matsukei.net/projects/thinreports/issues]
56
+
57
+ == Dependencies
58
+
59
+ * <code>prawn</code> <code>= 0.11.1</code>
60
+ * <code>json</code> <code>>= 1.4.6</code>
61
+ (Only for less than Ruby 1.9)
62
+
63
+ === Note
64
+
65
+ We tested on <code>Ruby 1.8.7</code> and <code>1.9.2</code>.
66
+ We recommend <code>1.9.2+</code>.
67
+
68
+ == Resources
69
+
70
+ === Fonts
71
+
72
+ ThinReports includes the following fonts.
73
+
74
+ * IPAFonts: Copyright(c) 2003-2011 Information-technology Promotion Agency, Japan.
75
+ Please see the lincense file {IPA_Font_License_Agreement_v1.0.txt}[http://ipafont.ipa.go.jp/ipa_font_license_v1.html].
76
+
77
+ == License
78
+
79
+ (The MIT License)
80
+
81
+ Copyright (c) 2010-2011 Matsukei Co.,Ltd.
82
+
83
+ Permission is hereby granted, free of charge, to any person obtaining
84
+ a copy of this software and associated documentation files (the
85
+ 'Software'), to deal in the Software without restriction, including
86
+ without limitation the rights to use, copy, modify, merge, publish,
87
+ distribute, sublicense, and/or sell copies of the Software, and to
88
+ permit persons to whom the Software is furnished to do so, subject to
89
+ the following conditions:
90
+
91
+ The above copyright notice and this permission notice shall be
92
+ included in all copies or substantial portions of the Software.
93
+
94
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
95
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
96
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
97
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
98
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
99
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
100
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # coding: utf-8
2
+
3
+ # Load thinreports
4
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/lib'))
5
+ require 'thinreports'
6
+
7
+ # Load tasks
8
+ Dir.glob('tasks/**/*.rake').each do |r|
9
+ Rake.application.add_import r
10
+ end
@@ -0,0 +1,10 @@
1
+ <script type="text/javascript">
2
+ var _gaq = _gaq || [];
3
+ _gaq.push(['_setAccount', 'UA-19321975-2']);
4
+ _gaq.push(['_trackPageview']);
5
+ (function() {
6
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
7
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
8
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
9
+ })();
10
+ </script>
@@ -0,0 +1,11 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ # The current version.
5
+ VERSION = '0.6.0.pre3'
6
+ end
7
+
8
+ require 'thinreports/core'
9
+ require 'thinreports/report'
10
+ require 'thinreports/layout'
11
+ require 'thinreports/generator'
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+
5
+ ROOTDIR = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
6
+
7
+ module Core
8
+ end
9
+
10
+ end
11
+
12
+ require 'thinreports/core/ext'
13
+ require 'thinreports/core/utils'
14
+ require 'thinreports/core/ordered_hash'
15
+
16
+ require 'thinreports/core/errors'
17
+ require 'thinreports/core/events'
18
+ require 'thinreports/core/format'
19
+ require 'thinreports/core/shape'
20
+ require 'thinreports/core/page'
@@ -0,0 +1,58 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+
5
+ module Errors
6
+ class Basic < ::StandardError
7
+ end
8
+
9
+ class UnknownShapeStyleName < Basic
10
+ end
11
+
12
+ class UnknownShapeType < Basic
13
+ end
14
+
15
+ class UnknownFormatterType < Basic
16
+ end
17
+
18
+ class LayoutFileNotFound < Basic
19
+ end
20
+
21
+ class NoRegisteredLayoutFound < Basic
22
+ end
23
+
24
+ class UnknownItemId < Basic
25
+ end
26
+
27
+ class DisabledListSection < Basic
28
+ end
29
+
30
+ class UnknownEventType < Basic
31
+ end
32
+
33
+ class UnknownLayoutId < Basic
34
+ end
35
+
36
+ class UnknownGeneratorType < Basic
37
+ end
38
+
39
+ class NoConfigurationFound < Basic
40
+ end
41
+
42
+ class UnsupportedColorName < Basic
43
+ end
44
+
45
+ class InvalidLayoutFormat < Basic
46
+ end
47
+
48
+ class IncompatibleLayoutFormat < Basic
49
+ def initialize(filename, fileversion, required_rules)
50
+ super("Generator #{ThinReports::VERSION} can not be built this file, " +
51
+ "'#{File.basename(filename)}'." +
52
+ "This file is created in the Editor of version '#{fileversion}', " +
53
+ "but Generator requires version #{required_rules}.")
54
+ end
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,71 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Core
5
+
6
+ class Events
7
+ Event = ::Struct.new(:type, :target)
8
+
9
+ # @return [Hash<Symbol, ThinReports::Core::Events::Event>]
10
+ # @private
11
+ attr_accessor :events
12
+
13
+ # @param [Symbol] types
14
+ def initialize(*types)
15
+ @events = {}
16
+ @types = types
17
+ end
18
+
19
+ # @param [Symbol] type
20
+ # @yield [e]
21
+ # @yieldparam [ThinReports::Core::Events::Event] e
22
+ def listen(type, &block)
23
+ verify_event_type(type)
24
+
25
+ if block_given?
26
+ events[type] = block
27
+ else
28
+ raise ArgumentError, '#listen requires a block'
29
+ end
30
+ end
31
+ alias_method :on, :listen
32
+
33
+ # @param [Symbol] type
34
+ def unlisten(type)
35
+ events.delete(type)
36
+ end
37
+ alias_method :un, :unlisten
38
+
39
+ # @private
40
+ def dispatch(e)
41
+ unless e.type
42
+ raise ArgumentError, 'Event#type attribute is required'
43
+ end
44
+ verify_event_type(e.type)
45
+
46
+ if event = events[e.type]
47
+ event.call(e)
48
+ end
49
+ end
50
+
51
+ # @private
52
+ def copy
53
+ new_events = self.dup
54
+ new_events.events = events.simple_deep_copy
55
+ new_events
56
+ end
57
+
58
+ private
59
+
60
+ # @param [Symbol] type
61
+ def verify_event_type(type)
62
+ return if @types.empty?
63
+
64
+ unless @types.include?(type)
65
+ raise ThinReports::Errors::UnknownEventType
66
+ end
67
+ end
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,5 @@
1
+ # coding: utf-8
2
+
3
+ require 'thinreports/core/ext/object'
4
+ require 'thinreports/core/ext/array'
5
+ require 'thinreports/core/ext/hash'
@@ -0,0 +1,19 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Core
5
+
6
+ # @private
7
+ module ArrayExtensions
8
+ def simple_deep_copy
9
+ map {|v| v.dup rescue v }
10
+ end
11
+ end
12
+
13
+ end
14
+ end
15
+
16
+ # @private
17
+ class Array
18
+ include ThinReports::Core::ArrayExtensions
19
+ end
@@ -0,0 +1,19 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Core
5
+
6
+ # @private
7
+ module HashExtensions
8
+ def simple_deep_copy
9
+ inject({}) {|h, (k, v)| h[k] = (v.dup rescue v); h}
10
+ end
11
+ end
12
+
13
+ end
14
+ end
15
+
16
+ # @private
17
+ class Hash
18
+ include ThinReports::Core::HashExtensions
19
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Core
5
+
6
+ # @private
7
+ module ObjectExtensions
8
+ unless ::Object.method_defined?(:blank?)
9
+ def blank?
10
+ case self
11
+ when String then self.nil? || self.empty?
12
+ when NilClass then true
13
+ else false
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ end
20
+ end
21
+
22
+ # @private
23
+ class Object
24
+ include ThinReports::Core::ObjectExtensions
25
+ end
@@ -0,0 +1,14 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Core
5
+
6
+ # @private
7
+ module Format
8
+ end
9
+
10
+ end
11
+ end
12
+
13
+ require 'thinreports/core/format/builder'
14
+ require 'thinreports/core/format/base'
@@ -0,0 +1,93 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Core::Format
5
+
6
+ # @abstract
7
+ # @private
8
+ class Base
9
+ # Work like a BlankSlate.
10
+ instance_methods.each do |m|
11
+ undef_method(m) unless m.to_s =~ /^(object|eq|__|instance_|=|!)/
12
+ end
13
+
14
+ class << self
15
+ include Core::Format::Builder
16
+
17
+ def config_reader(*configs, &block)
18
+ each_configs(*configs) do |m, location|
19
+ define_read_method(m, location, &block)
20
+ end
21
+ end
22
+
23
+ def config_checker(check, *configs)
24
+ checker = lambda {|val| val == check}
25
+ each_configs(*configs) do |m, location|
26
+ define_read_method(:"#{m}?", location, &checker)
27
+ end
28
+ end
29
+
30
+ def config_writer(*configs)
31
+ each_configs(*configs) do |m, location|
32
+ define_write_method(m, location)
33
+ end
34
+ end
35
+
36
+ def config_accessor(*configs, &block)
37
+ config_reader(*configs, &block)
38
+ config_writer(*configs)
39
+ end
40
+
41
+ private
42
+
43
+ def define_read_method(m, location = nil, &block)
44
+ define_method(m) do
45
+ read(*location, &block)
46
+ end
47
+ end
48
+
49
+ def define_write_method(m, location = nil)
50
+ define_method(:"#{m}=") do |value|
51
+ write(value, *location)
52
+ end
53
+ end
54
+
55
+ def each_configs(*configs, &block)
56
+ c = configs.first.is_a?(::Hash) ? configs.first : (configs || [])
57
+ c.each do |m, location|
58
+ block.call(m, location || [m.to_s])
59
+ end
60
+ end
61
+ end
62
+
63
+ def initialize(config, &block)
64
+ @config = config
65
+ block.call(self) if ::Kernel.block_given?
66
+ end
67
+
68
+ private
69
+
70
+ def find(*keys)
71
+ if keys.empty?
72
+ @config
73
+ else
74
+ keys.inject(@config) do |c, k|
75
+ c.is_a?(::Hash) ? c[k] : (break c)
76
+ end
77
+ end
78
+ end
79
+
80
+ def write(value, *keys)
81
+ key = keys.pop
82
+ owner = find(*keys)
83
+ owner[key] = value
84
+ end
85
+
86
+ def read(*keys, &block)
87
+ value = find(*keys)
88
+ ::Kernel.block_given? ? block.call(value) : value
89
+ end
90
+ end
91
+
92
+ end
93
+ end