turbogenerator 0.3.0 → 0.5.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.
- checksums.yaml +15 -0
- data/bin/turbo +19 -2
- data/lib/commander.rb +93 -0
- data/lib/hash_recursive.rb +18 -0
- data/lib/templates/command.erb +18 -0
- data/lib/templates/output.erb +8 -0
- data/lib/templates/resource-get.json +19 -5
- data/lib/turbo.rb +22 -68
- data/lib/value_object.rb +52 -0
- metadata +68 -16
- data/bin/before.sh, +0 -0
- data/lib/hash_recursive_merge.rb +0 -74
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YjRmMzhkMTA0NGI3NTc1M2E5YTBmMGY0NzVmZjQ3MTFlY2MxNTUzYQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YzZiMDk1ODFiZWJlZTBiNTI0ZmYyYzQwMmYxYmQyYWUzOThmNjQ1Yg==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NTlmZGVmNTNmMWM3Yjg4ZjU0NDU2ODFlMDQ4MjI5NTA5MDE5NTBiNWE1NGU0
|
10
|
+
NDk2MmZkNTRhNzFmZGQ1MTZiZDM5NDNjZjE0MjM1ODE0MTdmYWQ3MmEwMDk0
|
11
|
+
ZjA2OGNmYWE4YjBkMWY1NzI2ZjhkNjk3M2M1NzI5MjMwNzA1NWE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZDM4OTMxZDM2NzUwNmVlZjUyODQ4OTc4OTc1Y2I5ZWE0ZWJjZTA5ZjIzNWM3
|
14
|
+
ZjQwYmNlYzBhZTZlYTcwZWExZTY2ODM0ZTRkNDUwOTFhNjczZmE0MjVjMDM1
|
15
|
+
NjUxZWI1ZWRmNjI2NTJjMjhkMmU5OTM4NWFiZDJjZGRlNzYzOTM=
|
data/bin/turbo
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "thor"
|
4
|
+
require 'term/ansicolor'
|
4
5
|
require "turbo"
|
5
6
|
|
6
7
|
def get_real_path(path)
|
@@ -13,7 +14,7 @@ class TurboApp < Thor
|
|
13
14
|
def generate(name)
|
14
15
|
|
15
16
|
if File.exist? "workflows/#{name}"
|
16
|
-
puts "workflow #{name} has already exist under workflows/#{name}"
|
17
|
+
puts "workflow #{name.green} has already exist under workflows/#{name}"
|
17
18
|
return
|
18
19
|
end
|
19
20
|
|
@@ -32,7 +33,8 @@ class TurboApp < Thor
|
|
32
33
|
|
33
34
|
FileUtils.copy File.join(File.dirname(File.expand_path(__FILE__)), "../lib/templates/workflow.json"), "workflows/#{name}/workflow.json"
|
34
35
|
|
35
|
-
puts "
|
36
|
+
puts "Workflow `#{name.green}` is generated under workflows/#{name}"
|
37
|
+
puts "Run `turbo start #{name.green}` to start the workflow"
|
36
38
|
end
|
37
39
|
|
38
40
|
desc "start", "specify the workflow name"
|
@@ -40,9 +42,24 @@ class TurboApp < Thor
|
|
40
42
|
def start(workflow)
|
41
43
|
config = options[:config]
|
42
44
|
turbo = Turbo.new(config)
|
45
|
+
|
46
|
+
if(!File.exist?("workflows/#{workflow}/workflow.json"))
|
47
|
+
puts "Workflow `#{workflow.green}` does not exist"
|
48
|
+
puts "Run `turbo generate #{workflow.green}` to generate it first"
|
49
|
+
return
|
50
|
+
end
|
51
|
+
|
43
52
|
turbo.run_workflow(workflow)
|
44
53
|
end
|
45
54
|
|
55
|
+
desc "list", "list all workflows"
|
56
|
+
def list
|
57
|
+
if(File.exist?("workflows"))
|
58
|
+
system ('ls workflows/')
|
59
|
+
else
|
60
|
+
puts "No workflow found, you can generate one by using `turob generate my-workflow`"
|
61
|
+
end
|
62
|
+
end
|
46
63
|
end
|
47
64
|
|
48
65
|
TurboApp.start
|
data/lib/commander.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'json'
|
3
|
+
require 'hashugar'
|
4
|
+
require 'jsonpath'
|
5
|
+
|
6
|
+
require 'term/ansicolor'
|
7
|
+
|
8
|
+
require 'rexml/document'
|
9
|
+
include REXML
|
10
|
+
|
11
|
+
require 'value_object'
|
12
|
+
|
13
|
+
|
14
|
+
class String
|
15
|
+
include Term::ANSIColor
|
16
|
+
end
|
17
|
+
|
18
|
+
def verfiy_xpath(caze, result)
|
19
|
+
xmldoc = Document.new(result)
|
20
|
+
nodes = XPath.match(xmldoc, "#{caze.success.content}")
|
21
|
+
|
22
|
+
if nodes != nil
|
23
|
+
puts "Case: ['#{caze.name}'] passed".green
|
24
|
+
else
|
25
|
+
puts "Case: ['#{caze.name}'] failed\nExpected: #{caze.success.content}\nGot: #{result}".red
|
26
|
+
end
|
27
|
+
puts "#{caze.type} #{caze.url}\n".cyan
|
28
|
+
end
|
29
|
+
|
30
|
+
def verify_regexp(caze, result)
|
31
|
+
x = result.match(/#{caze.success.content}/)
|
32
|
+
|
33
|
+
if x != nil
|
34
|
+
puts "Case: ['#{caze.name}'] passed".green
|
35
|
+
else
|
36
|
+
puts "Case: ['#{caze.name}'] failed\nExpected: #{caze.success.content}\nGot: #{result}".red
|
37
|
+
end
|
38
|
+
puts "#{caze.type} #{caze.url}\n".cyan
|
39
|
+
end
|
40
|
+
|
41
|
+
def verify_jsonpath(caze, result)
|
42
|
+
nodes = JsonPath.on(result, "#{caze.success.content}")
|
43
|
+
|
44
|
+
if nodes.size != 0
|
45
|
+
puts "Case: ['#{caze.name}'] passed".green
|
46
|
+
else
|
47
|
+
puts "Case: ['#{caze.name}'] failed\nExpected: #{nodes}\nGot: #{result}".red
|
48
|
+
end
|
49
|
+
puts "#{caze.type} #{caze.url}\n".cyan
|
50
|
+
end
|
51
|
+
|
52
|
+
def verify(caze)
|
53
|
+
result = `#{caze.command}`
|
54
|
+
|
55
|
+
case caze.success.type
|
56
|
+
when 'xpath'
|
57
|
+
verfiy_xpath(caze, result)
|
58
|
+
when 'regexp'
|
59
|
+
verify_regexp(caze, result)
|
60
|
+
when 'jsonpath'
|
61
|
+
verify_jsonpath(caze, result)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def generate_command(config)
|
66
|
+
template = File.read(File.join(File.dirname(File.expand_path(__FILE__)), 'templates/command.erb'))
|
67
|
+
renderer = ERB.new(template)
|
68
|
+
|
69
|
+
puts "Scenario: #{config.name}, test cases: #{config.cases.size}\n".cyan
|
70
|
+
config.cases.each do |caze|
|
71
|
+
test_case = TestCase.new({
|
72
|
+
:name => caze.name,
|
73
|
+
:url => "#{config.baseurl}/#{caze.path}",
|
74
|
+
:headers => caze.headers,
|
75
|
+
:type => caze.type,
|
76
|
+
:data_path => caze.data,
|
77
|
+
:success => SuccessDefinition.new(caze.success),
|
78
|
+
:debug => caze.debug
|
79
|
+
})
|
80
|
+
|
81
|
+
command = renderer.result(test_case.get_binding).gsub("\n", " ").strip
|
82
|
+
|
83
|
+
test = ExecutableTest.new({
|
84
|
+
:name => caze.name,
|
85
|
+
:type => caze.type,
|
86
|
+
:url => "#{config.baseurl}/#{caze.path}",
|
87
|
+
:command => command,
|
88
|
+
:success => SuccessDefinition.new(caze.success)
|
89
|
+
})
|
90
|
+
|
91
|
+
verify(test)
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module HashRecursiveMerge
|
2
|
+
def rmerge!(other_hash)
|
3
|
+
merge!(other_hash) do |key, oldval, newval|
|
4
|
+
oldval.class == self.class ? oldval.rmerge!(newval) : newval
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
def rmerge(other_hash)
|
9
|
+
r = {}
|
10
|
+
merge(other_hash) do |key, oldval, newval|
|
11
|
+
r[key] = oldval.class == self.class ? oldval.rmerge(newval) : newval
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Hash
|
17
|
+
include HashRecursiveMerge
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
curl -s
|
2
|
+
<% if success.part == "header" %> -D - -o /dev/null<% end %>
|
3
|
+
|
4
|
+
-X <%= type %>
|
5
|
+
|
6
|
+
<% if ['POST', 'PUT'].include? type %>
|
7
|
+
--data @<%= data_path %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% headers.each_pair do |key, value| %>
|
11
|
+
--header <%= key %>=<%= value %>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<%= url %>
|
15
|
+
|
16
|
+
<% if debug %>
|
17
|
+
-D - -o debug.log
|
18
|
+
<% end %>
|
@@ -1,14 +1,28 @@
|
|
1
1
|
{
|
2
|
-
"
|
3
|
-
"
|
2
|
+
"name": "posts",
|
3
|
+
"baseurl": "http://localhost:8080",
|
4
4
|
"headers": {
|
5
5
|
"Accept": "application/json",
|
6
6
|
"Content-Type": "application/json"
|
7
7
|
},
|
8
8
|
"cases": [
|
9
|
-
{
|
10
|
-
"path": "/
|
11
|
-
"success":
|
9
|
+
{ "name": "list posts",
|
10
|
+
"path": "/api/feeds",
|
11
|
+
"success": {
|
12
|
+
"part": "body",
|
13
|
+
"type": "jsonpath",
|
14
|
+
"content": "$[0].url"
|
15
|
+
}
|
16
|
+
},
|
17
|
+
{ "name": "create posts",
|
18
|
+
"path": "/api/fav-feeds",
|
19
|
+
"type": "POST",
|
20
|
+
"data": "resource.json",
|
21
|
+
"success": {
|
22
|
+
"part": "header",
|
23
|
+
"type": "regexp",
|
24
|
+
"content": "200 OK"
|
25
|
+
}
|
12
26
|
}
|
13
27
|
]
|
14
28
|
}
|
data/lib/turbo.rb
CHANGED
@@ -2,31 +2,12 @@
|
|
2
2
|
|
3
3
|
require 'json'
|
4
4
|
require 'term/ansicolor'
|
5
|
+
require 'hashugar'
|
6
|
+
require 'rexml/document'
|
7
|
+
include REXML
|
5
8
|
|
6
|
-
|
7
|
-
|
8
|
-
# License:: MIT License
|
9
|
-
# Link:: http://www.simonecarletti.com/
|
10
|
-
# Source:: http://gist.github.com/gists/6391/
|
11
|
-
#
|
12
|
-
module HashRecursiveMerge
|
13
|
-
def rmerge!(other_hash)
|
14
|
-
merge!(other_hash) do |key, oldval, newval|
|
15
|
-
oldval.class == self.class ? oldval.rmerge!(newval) : newval
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def rmerge(other_hash)
|
20
|
-
r = {}
|
21
|
-
merge(other_hash) do |key, oldval, newval|
|
22
|
-
r[key] = oldval.class == self.class ? oldval.rmerge(newval) : newval
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
class Hash
|
28
|
-
include HashRecursiveMerge
|
29
|
-
end
|
9
|
+
require 'hash_recursive'
|
10
|
+
require 'commander'
|
30
11
|
|
31
12
|
class String
|
32
13
|
include Term::ANSIColor
|
@@ -46,23 +27,25 @@ class Turbo
|
|
46
27
|
@workflow_path = "workflows/#{workflow}"
|
47
28
|
@pre_command = "#{@workflow_path}/#{wf['before']}"
|
48
29
|
@post_command = "#{@workflow_path}/#{wf['after']}"
|
30
|
+
@debug_file = 'debug.log'
|
49
31
|
|
50
32
|
scenarios = wf['scenarios']
|
33
|
+
@run_success = 0
|
34
|
+
@run_failed = 0
|
51
35
|
|
52
|
-
|
36
|
+
execute_before_script
|
53
37
|
scenarios.each do |scenario|
|
54
38
|
run_scenario("#{@workflow_path}/scenarios/#{scenario}")
|
55
39
|
end
|
56
|
-
|
57
|
-
|
40
|
+
execute_after_script
|
58
41
|
end
|
59
42
|
|
60
43
|
private
|
61
|
-
def
|
44
|
+
def execute_before_script
|
62
45
|
system "#{@pre_command}"
|
63
46
|
end
|
64
47
|
|
65
|
-
def
|
48
|
+
def execute_after_script
|
66
49
|
system "#{@post_command}"
|
67
50
|
end
|
68
51
|
|
@@ -76,14 +59,6 @@ class Turbo
|
|
76
59
|
end
|
77
60
|
end
|
78
61
|
|
79
|
-
def generate_header(obj)
|
80
|
-
headers = []
|
81
|
-
obj.each_pair do |k, v|
|
82
|
-
headers << "-H \"#{k}: #{v}\""
|
83
|
-
end
|
84
|
-
headers.join(' ')
|
85
|
-
end
|
86
|
-
|
87
62
|
def load_common
|
88
63
|
JSON.parse(File.read(@conf['conf_path'] + '/' + @conf['common_conf']))
|
89
64
|
end
|
@@ -92,39 +67,18 @@ class Turbo
|
|
92
67
|
JSON.parse(File.read(scenario))
|
93
68
|
end
|
94
69
|
|
95
|
-
|
96
|
-
|
97
|
-
config = common.rmerge(load_scenario(scenario))
|
70
|
+
def bootstrap(scenario)
|
71
|
+
config = load_common.rmerge(load_scenario(scenario)).to_hashugar
|
98
72
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
|
-
# generate all headers
|
105
|
-
headers = generate_header(config['headers'])
|
106
|
-
|
107
|
-
# generate HTTP method
|
108
|
-
method = "-X #{config['method']}"
|
109
|
-
|
110
|
-
# run each case here
|
111
|
-
config['cases'].each do |caze|
|
112
|
-
path = config['baseurl'] + caze['path']
|
113
|
-
data = config['method'] == "POST" || config['method'] == "PUT" ? "-d @#{@workflow_path}/#{caze['data']}" : ""
|
114
|
-
|
115
|
-
debug = @conf['debug'] == 'true' || config['debug'] == 'true' ? "-D - -o debug.log" : ""
|
73
|
+
def config.get_binding
|
74
|
+
binding
|
75
|
+
end
|
116
76
|
|
117
|
-
|
118
|
-
|
119
|
-
command = "#{real_command} | grep --color=auto -E \"#{caze['success']}\""
|
77
|
+
config
|
78
|
+
end
|
120
79
|
|
121
|
-
|
80
|
+
def run_scenario(scenario)
|
81
|
+
generate_command(bootstrap(scenario))
|
82
|
+
end
|
122
83
|
|
123
|
-
if ret
|
124
|
-
puts "#{'Success'}: #{real_command}".green
|
125
|
-
else
|
126
|
-
puts "#{'Error'}: #{real_command}".red
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
84
|
end
|
data/lib/value_object.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
class TestCase
|
4
|
+
attr_accessor :name, :url, :headers, :type, :data_path, :debug, :success
|
5
|
+
|
6
|
+
def initialize(args)
|
7
|
+
obj = OpenStruct.new(args)
|
8
|
+
@name = obj.name
|
9
|
+
@url = obj.url
|
10
|
+
@headers = obj.headers || {}
|
11
|
+
@type = obj.type || "GET"
|
12
|
+
@data_path = obj.data_path
|
13
|
+
@success = obj.success
|
14
|
+
@debug = obj.debug
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_binding
|
18
|
+
binding
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class SuccessDefinition
|
23
|
+
attr_accessor :part, :type, :content
|
24
|
+
|
25
|
+
def initialize(args)
|
26
|
+
obj = OpenStruct.new(args)
|
27
|
+
@part = obj.part
|
28
|
+
@type = obj.type
|
29
|
+
@content = obj.content
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_binding
|
33
|
+
binding
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class ExecutableTest
|
38
|
+
attr_accessor :name, :type, :url, :command, :success
|
39
|
+
|
40
|
+
def initialize(args)
|
41
|
+
obj = OpenStruct.new(args)
|
42
|
+
@name = obj.name
|
43
|
+
@url = obj.url
|
44
|
+
@type = obj.type || "GET"
|
45
|
+
@command = obj.command
|
46
|
+
@success = obj.success
|
47
|
+
end
|
48
|
+
|
49
|
+
def get_binding
|
50
|
+
binding
|
51
|
+
end
|
52
|
+
end
|
metadata
CHANGED
@@ -1,91 +1,143 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: turbogenerator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.5.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Juntao Qiu
|
8
|
+
- Jia Wei
|
9
|
+
- Shen Tong
|
10
|
+
- Yan Yu
|
11
|
+
- Yang Mengmeng
|
9
12
|
autorequire:
|
10
13
|
bindir: bin
|
11
14
|
cert_chain: []
|
12
|
-
date:
|
15
|
+
date: 2015-03-12 00:00:00.000000000 Z
|
13
16
|
dependencies:
|
14
17
|
- !ruby/object:Gem::Dependency
|
15
18
|
name: thor
|
16
19
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
20
|
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '0.18'
|
19
24
|
- - ! '>='
|
20
25
|
- !ruby/object:Gem::Version
|
21
26
|
version: 0.18.1
|
22
27
|
type: :runtime
|
23
28
|
prerelease: false
|
24
29
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
30
|
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.18'
|
27
34
|
- - ! '>='
|
28
35
|
- !ruby/object:Gem::Version
|
29
36
|
version: 0.18.1
|
30
37
|
- !ruby/object:Gem::Dependency
|
31
38
|
name: term-ansicolor
|
32
39
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
40
|
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.3'
|
35
44
|
- - ! '>='
|
36
45
|
- !ruby/object:Gem::Version
|
37
46
|
version: 1.3.0
|
38
47
|
type: :runtime
|
39
48
|
prerelease: false
|
40
49
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
50
|
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.3'
|
43
54
|
- - ! '>='
|
44
55
|
- !ruby/object:Gem::Version
|
45
56
|
version: 1.3.0
|
46
|
-
|
47
|
-
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: hashugar
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ~>
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '1.0'
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 1.0.0
|
67
|
+
type: :runtime
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ~>
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '1.0'
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.0.0
|
77
|
+
- !ruby/object:Gem::Dependency
|
78
|
+
name: jsonpath
|
79
|
+
requirement: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ~>
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0.5'
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 0.5.7
|
87
|
+
type: :runtime
|
88
|
+
prerelease: false
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0.5'
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.5.7
|
97
|
+
description: Turbo is a HTTP API tester, it's a curl wrapper
|
48
98
|
email: juntao.qiu@gmail.com
|
49
99
|
executables:
|
50
100
|
- turbo
|
51
101
|
extensions: []
|
52
102
|
extra_rdoc_files: []
|
53
103
|
files:
|
54
|
-
- bin/before.sh,
|
55
104
|
- bin/turbo
|
105
|
+
- lib/commander.rb
|
56
106
|
- lib/config/browsers.json
|
57
107
|
- lib/config/common.json
|
58
108
|
- lib/config/turbo.conf
|
59
|
-
- lib/
|
109
|
+
- lib/hash_recursive.rb
|
60
110
|
- lib/templates/after.sh
|
61
111
|
- lib/templates/before.sh
|
112
|
+
- lib/templates/command.erb
|
113
|
+
- lib/templates/output.erb
|
62
114
|
- lib/templates/resource-get.json
|
63
115
|
- lib/templates/resource.json
|
64
116
|
- lib/templates/workflow.json
|
65
117
|
- lib/turbo.rb
|
118
|
+
- lib/value_object.rb
|
66
119
|
homepage: https://github.com/abruzzi/turbo
|
67
120
|
licenses:
|
68
121
|
- MIT
|
122
|
+
metadata: {}
|
69
123
|
post_install_message:
|
70
124
|
rdoc_options: []
|
71
125
|
require_paths:
|
72
126
|
- lib
|
73
127
|
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
128
|
requirements:
|
76
129
|
- - ! '>='
|
77
130
|
- !ruby/object:Gem::Version
|
78
131
|
version: '0'
|
79
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
-
none: false
|
81
133
|
requirements:
|
82
134
|
- - ! '>='
|
83
135
|
- !ruby/object:Gem::Version
|
84
136
|
version: '0'
|
85
137
|
requirements: []
|
86
138
|
rubyforge_project:
|
87
|
-
rubygems_version:
|
139
|
+
rubygems_version: 2.2.2
|
88
140
|
signing_key:
|
89
|
-
specification_version:
|
90
|
-
summary:
|
141
|
+
specification_version: 4
|
142
|
+
summary: Turbo is a HTTP API tester
|
91
143
|
test_files: []
|
data/bin/before.sh,
DELETED
File without changes
|
data/lib/hash_recursive_merge.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# = Hash Recursive Merge
|
3
|
-
#
|
4
|
-
# Merges a Ruby Hash recursively, Also known as deep merge.
|
5
|
-
# Recursive version of Hash#merge and Hash#merge!.
|
6
|
-
#
|
7
|
-
# Category:: Ruby
|
8
|
-
# Package:: Hash
|
9
|
-
# Author:: Simone Carletti <weppos@weppos.net>
|
10
|
-
# Copyright:: 2007-2008 The Authors
|
11
|
-
# License:: MIT License
|
12
|
-
# Link:: http://www.simonecarletti.com/
|
13
|
-
# Source:: http://gist.github.com/gists/6391/
|
14
|
-
#
|
15
|
-
module HashRecursiveMerge
|
16
|
-
|
17
|
-
#
|
18
|
-
# Recursive version of Hash#merge!
|
19
|
-
#
|
20
|
-
# Adds the contents of +other_hash+ to +hsh+,
|
21
|
-
# merging entries in +hsh+ with duplicate keys with those from +other_hash+.
|
22
|
-
#
|
23
|
-
# Compared with Hash#merge!, this method supports nested hashes.
|
24
|
-
# When both +hsh+ and +other_hash+ contains an entry with the same key,
|
25
|
-
# it merges and returns the values from both arrays.
|
26
|
-
#
|
27
|
-
# h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
|
28
|
-
# h2 = {"b" => 254, "c" => 300, "c" => {"c1" => 16, "c3" => 94}}
|
29
|
-
# h1.rmerge!(h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
|
30
|
-
#
|
31
|
-
# Simply using Hash#merge! would return
|
32
|
-
#
|
33
|
-
# h1.merge!(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
|
34
|
-
#
|
35
|
-
def rmerge!(other_hash)
|
36
|
-
merge!(other_hash) do |key, oldval, newval|
|
37
|
-
oldval.class == self.class ? oldval.rmerge!(newval) : newval
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
#
|
42
|
-
# Recursive version of Hash#merge
|
43
|
-
#
|
44
|
-
# Compared with Hash#merge!, this method supports nested hashes.
|
45
|
-
# When both +hsh+ and +other_hash+ contains an entry with the same key,
|
46
|
-
# it merges and returns the values from both arrays.
|
47
|
-
#
|
48
|
-
# Compared with Hash#merge, this method provides a different approch
|
49
|
-
# for merging nasted hashes.
|
50
|
-
# If the value of a given key is an Hash and both +other_hash+ abd +hsh
|
51
|
-
# includes the same key, the value is merged instead replaced with
|
52
|
-
# +other_hash+ value.
|
53
|
-
#
|
54
|
-
# h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
|
55
|
-
# h2 = {"b" => 254, "c" => 300, "c" => {"c1" => 16, "c3" => 94}}
|
56
|
-
# h1.rmerge(h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
|
57
|
-
#
|
58
|
-
# Simply using Hash#merge would return
|
59
|
-
#
|
60
|
-
# h1.merge(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
|
61
|
-
#
|
62
|
-
def rmerge(other_hash)
|
63
|
-
r = {}
|
64
|
-
merge(other_hash) do |key, oldval, newval|
|
65
|
-
r[key] = oldval.class == self.class ? oldval.rmerge(newval) : newval
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
|
72
|
-
class Hash
|
73
|
-
include HashRecursiveMerge
|
74
|
-
end
|