masamune 0.14.0 → 0.15.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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -1
  3. data/Rakefile +37 -0
  4. data/bin/masamune-dump +22 -0
  5. data/bin/masamune-elastic-mapreduce +22 -0
  6. data/bin/masamune-hive +22 -0
  7. data/bin/masamune-psql +22 -0
  8. data/bin/masamune-shell +22 -0
  9. data/lib/masamune/cached_filesystem.rb +1 -1
  10. data/lib/masamune/commands/shell.rb +1 -1
  11. data/lib/masamune/configuration.rb +5 -7
  12. data/lib/masamune/data_plan/elem.rb +15 -7
  13. data/lib/masamune/data_plan/engine.rb +2 -0
  14. data/lib/masamune/data_plan/rule.rb +16 -5
  15. data/lib/masamune/data_plan/set.rb +8 -8
  16. data/lib/masamune/filesystem.rb +12 -6
  17. data/lib/masamune/schema/catalog.rb +6 -6
  18. data/lib/masamune/schema/column.rb +1 -1
  19. data/lib/masamune/schema/map.rb +6 -2
  20. data/lib/masamune/schema/store.rb +31 -3
  21. data/lib/masamune/tasks/shell_thor.rb +1 -1
  22. data/lib/masamune/thor.rb +12 -4
  23. data/lib/masamune/version.rb +1 -1
  24. data/lib/masamune.rb +0 -1
  25. data/spec/masamune/actions/elastic_mapreduce_spec.rb +0 -2
  26. data/spec/masamune/actions/execute_spec.rb +0 -2
  27. data/spec/masamune/actions/hadoop_filesystem_spec.rb +0 -2
  28. data/spec/masamune/actions/hadoop_streaming_spec.rb +0 -2
  29. data/spec/masamune/actions/hive_spec.rb +0 -2
  30. data/spec/masamune/actions/invoke_parallel_spec.rb +0 -2
  31. data/spec/masamune/actions/postgres_admin_spec.rb +0 -2
  32. data/spec/masamune/actions/postgres_spec.rb +0 -2
  33. data/spec/masamune/actions/s3cmd_spec.rb +0 -2
  34. data/spec/masamune/actions/transform_spec.rb +0 -2
  35. data/spec/masamune/after_initialization_callbacks_spec.rb +0 -2
  36. data/spec/masamune/cached_filesystem_spec.rb +0 -2
  37. data/spec/masamune/commands/hadoop_filesystem_spec.rb +0 -2
  38. data/spec/masamune/commands/hadoop_streaming_spec.rb +0 -2
  39. data/spec/masamune/commands/hive_spec.rb +0 -2
  40. data/spec/masamune/commands/postgres_admin_spec.rb +0 -2
  41. data/spec/masamune/commands/postgres_spec.rb +0 -2
  42. data/spec/masamune/commands/retry_with_backoff_spec.rb +0 -2
  43. data/spec/masamune/commands/s3cmd_spec.rb +0 -2
  44. data/spec/masamune/commands/shell_spec.rb +0 -2
  45. data/spec/masamune/configuration_spec.rb +12 -2
  46. data/spec/masamune/data_plan/builder_spec.rb +0 -2
  47. data/spec/masamune/data_plan/elem_spec.rb +73 -5
  48. data/spec/masamune/data_plan/engine_spec.rb +0 -2
  49. data/spec/masamune/data_plan/rule_spec.rb +51 -6
  50. data/spec/masamune/data_plan/set_spec.rb +2 -5
  51. data/spec/masamune/environment_spec.rb +0 -2
  52. data/spec/masamune/filesystem_spec.rb +33 -4
  53. data/spec/masamune/helpers/postgres_spec.rb +0 -2
  54. data/spec/masamune/rspec/job_fixture_spec.rb +365 -0
  55. data/spec/masamune/rspec/shared_example_group_spec.rb +73 -0
  56. data/spec/masamune/schema/catalog_spec.rb +14 -2
  57. data/spec/masamune/schema/column_spec.rb +0 -2
  58. data/spec/masamune/schema/dimension_spec.rb +0 -2
  59. data/spec/masamune/schema/fact_spec.rb +0 -2
  60. data/spec/masamune/schema/map_spec.rb +51 -2
  61. data/spec/masamune/schema/row_spec.rb +0 -2
  62. data/spec/masamune/schema/store_spec.rb +23 -2
  63. data/spec/masamune/schema/table_spec.rb +0 -2
  64. data/spec/masamune/string_format_spec.rb +0 -2
  65. data/spec/masamune/tasks/dump_thor_spec.rb +0 -3
  66. data/spec/masamune/tasks/elastic_mapreduce_thor_spec.rb +0 -3
  67. data/spec/masamune/tasks/hive_thor_spec.rb +0 -3
  68. data/spec/masamune/tasks/postgres_thor_spec.rb +0 -3
  69. data/spec/masamune/tasks/shell_thor_spec.rb +0 -3
  70. data/spec/masamune/template_spec.rb +0 -2
  71. data/spec/masamune/thor_spec.rb +53 -8
  72. data/spec/masamune/transform/bulk_upsert.dimension_spec.rb +0 -2
  73. data/spec/masamune/transform/consolidate_dimension_spec.rb +0 -2
  74. data/spec/masamune/transform/deduplicate_dimension_spec.rb +0 -2
  75. data/spec/masamune/transform/define_schema_spec.rb +0 -2
  76. data/spec/masamune/transform/define_table.dimension_spec.rb +0 -2
  77. data/spec/masamune/transform/define_table.fact_spec.rb +0 -2
  78. data/spec/masamune/transform/define_table.table_spec.rb +0 -2
  79. data/spec/masamune/transform/denormalize_table_spec.rb +0 -2
  80. data/spec/masamune/transform/insert_reference_values.dimension_spec.rb +0 -2
  81. data/spec/masamune/transform/insert_reference_values.fact_spec.rb +0 -2
  82. data/spec/masamune/transform/load_dimension_spec.rb +0 -2
  83. data/spec/masamune/transform/load_fact_spec.rb +0 -2
  84. data/spec/masamune/transform/relabel_dimension_spec.rb +0 -2
  85. data/spec/masamune/transform/rollup_fact_spec.rb +0 -2
  86. data/spec/masamune/transform/snapshot_dimension_spec.rb +0 -2
  87. data/spec/masamune/transform/stage_dimension_spec.rb +0 -2
  88. data/spec/masamune/transform/stage_fact_spec.rb +0 -2
  89. data/spec/masamune_spec.rb +0 -2
  90. data/spec/spec_helper.rb +2 -0
  91. data/spec/support/masamune/job_example_group.rb +62 -0
  92. data/spec/support/masamune/job_fixture.rb +137 -0
  93. data/spec/support/masamune/shared_example_group.rb +203 -0
  94. data/spec/support/masamune/step_example_group.rb +68 -0
  95. data/spec/support/masamune/step_fixture.rb +91 -0
  96. data/{lib/masamune/thor_loader.rb → spec/support/masamune/task_example_group.rb} +33 -10
  97. data/spec/support/rspec/example/action_example_group.rb +1 -1
  98. metadata +32 -3
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Template do
26
24
  describe '.render_to_file' do
27
25
  let(:parameters) { {} }
@@ -20,26 +20,37 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
- require 'thor'
25
-
26
23
  describe Masamune::Thor do
27
24
  let(:thor_class) do
28
25
  Class.new(Thor) do
29
26
  include Masamune::Thor
30
27
  include Masamune::Actions::DataFlow
31
28
 
29
+ namespace :example
30
+
32
31
  desc 'command', 'command'
33
- target path: "target/%Y-%m-%d"
34
- source path: "source/%Y%m%d*.log"
35
- method_option :zombo, desc: 'Anything is possible'
36
- def command
32
+ target path: fs.path(:tmp_dir, "target/%Y-%m-%d")
33
+ source path: fs.path(:tmp_dir, "source/%Y%m%d*.log")
34
+ def command_task
37
35
  # NOP
38
36
  end
39
37
 
40
38
  desc 'other', 'other'
41
39
  skip
42
- def other
40
+ def other_task
41
+ # NOP
42
+ end
43
+
44
+ desc 'current_dir', 'current_dir'
45
+ skip
46
+ def current_dir_task
47
+ console(fs.path(:current_dir))
48
+ end
49
+
50
+ desc 'unknown', 'unknown'
51
+ target path: fs.path(:unknown_dir, "target/%Y-%m-%d")
52
+ source path: fs.path(:unknown_dir, "source/%Y%m%d*.log")
53
+ def unknown_task
43
54
  # NOP
44
55
  end
45
56
  end
@@ -188,6 +199,40 @@ describe Masamune::Thor do
188
199
  end
189
200
  it { expect { cli_invocation }.to raise_error /random exception/ }
190
201
  end
202
+
203
+ context 'with command that raises exception during execution' do
204
+ let(:command) { 'unknown' }
205
+ let(:options) { ['--start', '2013-01-01'] }
206
+ it 'exits with status code 1 and prints error to stderr' do
207
+ expect { cli_invocation }.to raise_error { |e|
208
+ expect(e).to be_a(SystemExit)
209
+ expect(e.status).to eq(1)
210
+ }
211
+ expect(stdout.string).to be_blank
212
+ expect(stderr.string).to match(/Path :unknown_dir not defined/)
213
+ end
214
+ end
215
+
216
+ end
217
+
218
+ context 'with command that prints :current_dir' do
219
+ let(:thor_class) do
220
+ Class.new(Thor) do
221
+ include Masamune::Thor
222
+
223
+ desc 'current_dir', 'current_dir'
224
+ def current_dir
225
+ console(fs.path(:current_dir))
226
+ end
227
+ end
228
+ end
229
+
230
+ let(:command) { 'current_dir' }
231
+ it 'prints :current_dir' do
232
+ cli_invocation
233
+ expect(stdout.string).to eq(File.dirname(__FILE__) + "\n")
234
+ expect(stderr.string).to be_blank
235
+ end
191
236
  end
192
237
 
193
238
  context '.parse_extra' do
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::BulkUpsert do
26
24
  before do
27
25
  allow_any_instance_of(Masamune::Schema::Table).to receive(:lock_id).and_return(42)
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::ConsolidateDimension do
26
24
  before do
27
25
  catalog.schema :postgres do
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::DeduplicateDimension do
26
24
  before do
27
25
  catalog.schema :postgres do
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::DefineSchema do
26
24
  context 'for postgres schema' do
27
25
  before do
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::DefineTable do
26
24
  subject { transform.define_table(table).to_s }
27
25
 
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::DefineTable do
26
24
  before do
27
25
  catalog.schema :postgres do
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::DefineTable do
26
24
  let(:files) { [] }
27
25
  let(:section) { :all }
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::DenormalizeTable do
26
24
  before do
27
25
  catalog.schema :postgres do
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::InsertReferenceValues do
26
24
  before do
27
25
  allow_any_instance_of(Masamune::Schema::Table).to receive(:lock_id).and_return(42)
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::InsertReferenceValues do
26
24
  before do
27
25
  allow_any_instance_of(Masamune::Schema::Table).to receive(:lock_id).and_return(42)
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::LoadDimension do
26
24
  before do
27
25
  catalog.schema :postgres do
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::LoadFact do
26
24
  before do
27
25
  catalog.schema :postgres do
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::RelabelDimension do
26
24
  before do
27
25
  allow_any_instance_of(Masamune::Schema::Table).to receive(:lock_id).and_return(42)
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::RollupFact do
26
24
  before do
27
25
  allow_any_instance_of(Masamune::Schema::Table).to receive(:lock_id).and_return(42)
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::SnapshotDimension do
26
24
  before do
27
25
  catalog.schema :postgres do
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::StageDimension do
26
24
  before do
27
25
  catalog.schema :postgres do
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune::Transform::StageFact do
26
24
  before do
27
25
  allow_any_instance_of(Masamune::Schema::Table).to receive(:lock_id).and_return(42)
@@ -20,8 +20,6 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'spec_helper'
24
-
25
23
  describe Masamune do
26
24
  it { is_expected.to be_a(Module) }
27
25
 
data/spec/spec_helper.rb CHANGED
@@ -30,6 +30,8 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
30
30
 
31
31
  require 'active_support/core_ext/string/strip'
32
32
 
33
+ ENV['MASAMUNE_ENV'] = 'test'
34
+
33
35
  Masamune::ExampleGroup.configure do |config|
34
36
  config.quiet = ENV['MASAMUNE_DEBUG'] ? false : true
35
37
  config.debug = ENV['MASAMUNE_DEBUG'] ? true : false
@@ -0,0 +1,62 @@
1
+ # The MIT License (MIT)
2
+ #
3
+ # Copyright (c) 2014-2015, VMware, Inc. All Rights Reserved.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module Masamune::JobExampleGroup
24
+ module JobFixtureContext
25
+ shared_context 'job_fixture' do |context_options = {}|
26
+ fixture_file = example_fixture_file(context_options.slice(:fixture, :file, :path))
27
+ let(:fixture) { example_fixture(file: fixture_file) }
28
+
29
+ before :all do
30
+ load_example_config!
31
+ clean_example_run!
32
+ end
33
+
34
+ before do
35
+ setup_example_input!(fixture)
36
+ end
37
+
38
+ it "should match #{fixture_file}" do
39
+ aggregate_failures 'generates expected output' do
40
+ gather_example_output(fixture) do |actual_data, expect_file, expect_data|
41
+ expect(File.exists?(expect_file)).to eq(true)
42
+ expect(actual_data).to eq(expect_data)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ def self.included(base)
50
+ base.send(:include, Masamune::ExampleGroup)
51
+ base.send(:include, Masamune::SharedExampleGroup)
52
+ base.send(:include, Masamune::Actions::Filesystem)
53
+ base.send(:include, Masamune::Actions::Hive)
54
+ base.send(:include, Masamune::Actions::Postgres)
55
+ base.send(:include, JobFixtureContext)
56
+ end
57
+ end
58
+
59
+ RSpec.configure do |config|
60
+ config.include Masamune::JobExampleGroup, :type => :job, :file_path => %r{.*/spec/.*job_spec\.rb}
61
+ config.include Masamune::JobExampleGroup, :type => :task, :file_path => %r{.*/spec/.*task_spec\.rb}
62
+ end
@@ -0,0 +1,137 @@
1
+ # The MIT License (MIT)
2
+ #
3
+ # Copyright (c) 2014-2015, VMware, Inc. All Rights Reserved.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require 'active_support/core_ext/string/indent'
24
+
25
+ module Masamune
26
+ class JobFixture
27
+ INDENT = 2
28
+
29
+ attr_accessor :name
30
+
31
+ def initialize(options = {})
32
+ @path = options[:path]
33
+ @name = options[:name] || options[:fixture]
34
+ @file = options[:file]
35
+ @data = options[:data]
36
+ @type = options[:type]
37
+ @context = options[:context]
38
+
39
+ @data['inputs'] ||= []
40
+ @data['outputs'] ||= []
41
+ end
42
+
43
+ class << self
44
+ def load(options = {}, context = binding)
45
+ file = file_name(options)
46
+ raise ArgumentError, "Fixture '#{file}' does not exist" unless File.exists?(file)
47
+ YAML.load(ERB.new(File.read(file)).result(context)).tap do |data|
48
+ return new(options.merge(data: data, context: context))
49
+ end
50
+ end
51
+
52
+ def file_name(options = {})
53
+ return options[:file] if options[:file]
54
+ File.join(options[:path], [options[:name] || options[:fixture], suffix(options)].compact.join('.'))
55
+ end
56
+
57
+ protected
58
+
59
+ def suffix(options = {})
60
+ "#{options[:type] || 'job'}_fixture.yml"
61
+ end
62
+ end
63
+
64
+ def file_name
65
+ self.class.file_name(file: @file, path: @path, name: @name, type: @type)
66
+ end
67
+
68
+ def path
69
+ @path || File.dirname(@file)
70
+ end
71
+
72
+ def save
73
+ FileUtils.mkdir_p(path)
74
+ File.open(file_name, 'w') do |file|
75
+ file.puts '---'
76
+ file.puts 'inputs:'
77
+ @data['inputs'].each do |input|
78
+ file.puts '-'.indent(INDENT)
79
+ serialize(input) do |elem|
80
+ file.puts elem.indent(INDENT*2)
81
+ end
82
+ end
83
+ file.puts
84
+ file.puts 'outputs:'
85
+ @data['outputs'].each do |output|
86
+ file.puts '-'.indent(INDENT)
87
+ serialize(output) do |elem|
88
+ file.puts elem.indent(INDENT*2)
89
+ end
90
+ end
91
+ end
92
+ file_name
93
+ end
94
+
95
+ def inputs
96
+ @inputs ||= begin
97
+ @data['inputs'].map do |input|
98
+ if input['reference']
99
+ raise ArgumentError, "reference in #{file_name} requires fixture" unless input['reference']['fixture'] || input['reference']['file']
100
+ reference = self.class.load({path: input['reference']['path'] || path, name: input['reference']['fixture'], file: input['reference']['file'], type: @type}, @context)
101
+ section = input['reference']['section'] || 'outputs'
102
+ reference.send(section) if reference.respond_to?(section)
103
+ else
104
+ input
105
+ end
106
+ end.flatten.compact
107
+ end
108
+ end
109
+
110
+ def outputs
111
+ @data['outputs']
112
+ end
113
+
114
+ private
115
+
116
+ def serialize(hash, level = 0)
117
+ hash.each do |key, value|
118
+ case value
119
+ when String
120
+ if value.split("\n").count > 1
121
+ yield "#{key}: |".indent(level * INDENT)
122
+ value.split("\n").each do |line|
123
+ yield line.strip.indent((level + 1) * INDENT)
124
+ end
125
+ else
126
+ yield "#{key}: #{value}".indent(level * INDENT)
127
+ end
128
+ when Hash
129
+ yield "#{key}:".indent(level * INDENT)
130
+ serialize(value, level + 1) do |next_hash|
131
+ yield next_hash
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end