marty 2.5.2 → 2.5.4

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 (181) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +4 -0
  3. data/.rubocop.yml +7 -0
  4. data/.rubocop_todo.yml +11 -589
  5. data/Gemfile +9 -9
  6. data/Gemfile.lock +1 -1
  7. data/Rakefile +1 -3
  8. data/app/components/marty/api_auth_view.rb +3 -3
  9. data/app/components/marty/api_config_view.rb +8 -8
  10. data/app/components/marty/api_log_view.rb +16 -20
  11. data/app/components/marty/auth_app.rb +6 -6
  12. data/app/components/marty/base_rule_view.rb +27 -19
  13. data/app/components/marty/config_view.rb +12 -9
  14. data/app/components/marty/data_grid_view.rb +26 -26
  15. data/app/components/marty/delorean_rule_view.rb +0 -1
  16. data/app/components/marty/event_view.rb +27 -27
  17. data/app/components/marty/extras/layout.rb +26 -26
  18. data/app/components/marty/extras/misc.rb +2 -2
  19. data/app/components/marty/grid.rb +13 -13
  20. data/app/components/marty/grid_append_only.rb +0 -1
  21. data/app/components/marty/import_type_view.rb +13 -13
  22. data/app/components/marty/import_view.rb +17 -16
  23. data/app/components/marty/log_view.rb +16 -14
  24. data/app/components/marty/main_auth_app.rb +59 -59
  25. data/app/components/marty/main_auth_app/client/main_auth_app.js +3 -3
  26. data/app/components/marty/mcfly_grid_panel.rb +10 -10
  27. data/app/components/marty/new_posting_form.rb +11 -11
  28. data/app/components/marty/new_posting_window.rb +0 -1
  29. data/app/components/marty/posting_grid.rb +12 -13
  30. data/app/components/marty/promise_view.rb +6 -6
  31. data/app/components/marty/report_form.rb +50 -53
  32. data/app/components/marty/report_select.rb +27 -27
  33. data/app/components/marty/reporting.rb +4 -4
  34. data/app/components/marty/script_form.rb +40 -42
  35. data/app/components/marty/script_grid.rb +24 -24
  36. data/app/components/marty/script_tester.rb +40 -42
  37. data/app/components/marty/scripting.rb +25 -27
  38. data/app/components/marty/simple_app.rb +24 -9
  39. data/app/components/marty/tag_grid.rb +12 -13
  40. data/app/components/marty/user_view.rb +35 -35
  41. data/app/controllers/marty/application_controller.rb +3 -4
  42. data/app/controllers/marty/components_controller.rb +1 -1
  43. data/app/controllers/marty/delayed_job_controller.rb +1 -0
  44. data/app/controllers/marty/diagnostic/controller.rb +4 -6
  45. data/app/controllers/marty/job_controller.rb +6 -6
  46. data/app/controllers/marty/report_controller.rb +11 -11
  47. data/app/controllers/marty/rpc_controller.rb +15 -16
  48. data/app/helpers/marty/script_set.rb +4 -4
  49. data/app/models/marty/api_auth.rb +4 -5
  50. data/app/models/marty/api_config.rb +1 -1
  51. data/app/models/marty/base.rb +9 -8
  52. data/app/models/marty/base_rule.rb +18 -13
  53. data/app/models/marty/config.rb +4 -5
  54. data/app/models/marty/data_grid.rb +157 -181
  55. data/app/models/marty/delorean_rule.rb +63 -62
  56. data/app/models/marty/enum.rb +1 -1
  57. data/app/models/marty/event.rb +56 -59
  58. data/app/models/marty/helper.rb +38 -6
  59. data/app/models/marty/import_type.rb +6 -6
  60. data/app/models/marty/log.rb +3 -2
  61. data/app/models/marty/name_validator.rb +3 -2
  62. data/app/models/marty/pg_enum.rb +3 -4
  63. data/app/models/marty/posting.rb +20 -24
  64. data/app/models/marty/promise.rb +28 -30
  65. data/app/models/marty/script.rb +30 -28
  66. data/app/models/marty/tag.rb +8 -8
  67. data/app/models/marty/token.rb +2 -2
  68. data/app/models/marty/user.rb +24 -23
  69. data/app/models/marty/vw_promise.rb +10 -11
  70. data/config/routes.rb +2 -2
  71. data/delorean/blame_report.dl +268 -0
  72. data/{spec/dummy/delorean/fields.dl → delorean/marty_fields.dl} +8 -0
  73. data/delorean/table_report.dl +34 -0
  74. data/docker-compose.dummy.yml +2 -3
  75. data/lib/marty/aws/base.rb +8 -8
  76. data/lib/marty/aws/request.rb +4 -4
  77. data/lib/marty/cache_adapters/mcfly_ruby_cache.rb +1 -0
  78. data/lib/marty/content_handler.rb +25 -25
  79. data/lib/marty/data_change.rb +49 -71
  80. data/lib/marty/data_conversion.rb +20 -28
  81. data/lib/marty/data_exporter.rb +25 -28
  82. data/lib/marty/data_importer.rb +25 -27
  83. data/lib/marty/engine.rb +1 -2
  84. data/lib/marty/json_schema.rb +22 -24
  85. data/lib/marty/logger.rb +6 -9
  86. data/lib/marty/mcfly_model.rb +20 -24
  87. data/lib/marty/migrations.rb +37 -35
  88. data/lib/marty/monkey.rb +33 -33
  89. data/lib/marty/permissions.rb +18 -18
  90. data/lib/marty/promise_job.rb +17 -17
  91. data/lib/marty/promise_proxy.rb +6 -6
  92. data/lib/marty/relation.rb +6 -7
  93. data/lib/marty/rpc_call.rb +13 -12
  94. data/lib/marty/rule_script_set.rb +32 -28
  95. data/lib/marty/schema_helper.rb +37 -51
  96. data/lib/marty/util.rb +25 -24
  97. data/lib/marty/version.rb +1 -1
  98. data/lib/marty/xl.rb +121 -115
  99. data/make-dummy.mk +3 -0
  100. data/marty.gemspec +21 -21
  101. data/other/marty/api/base.rb +34 -35
  102. data/other/marty/diagnostic/aws/ec2_instance.rb +8 -8
  103. data/other/marty/diagnostic/base.rb +13 -14
  104. data/other/marty/diagnostic/collection.rb +2 -1
  105. data/other/marty/diagnostic/connections.rb +8 -6
  106. data/other/marty/diagnostic/database.rb +1 -0
  107. data/other/marty/diagnostic/delayed_job_version.rb +7 -9
  108. data/other/marty/diagnostic/delayed_job_worker_total_count.rb +1 -1
  109. data/other/marty/diagnostic/delayed_job_workers.rb +1 -1
  110. data/other/marty/diagnostic/environment_variables.rb +17 -15
  111. data/other/marty/diagnostic/fatal.rb +1 -1
  112. data/other/marty/diagnostic/node.rb +5 -9
  113. data/other/marty/diagnostic/nodes.rb +7 -5
  114. data/other/marty/diagnostic/packer.rb +7 -7
  115. data/other/marty/diagnostic/reporter.rb +24 -27
  116. data/other/marty/diagnostic/version.rb +3 -5
  117. data/script/rails +2 -1
  118. data/spec/controllers/application_controller_spec.rb +6 -6
  119. data/spec/controllers/delayed_job_controller_spec.rb +4 -4
  120. data/spec/controllers/diagnostic/controller_spec.rb +59 -60
  121. data/spec/controllers/job_controller_spec.rb +68 -69
  122. data/spec/controllers/rpc_controller_spec.rb +353 -359
  123. data/spec/controllers/rpc_import_spec.rb +15 -16
  124. data/spec/dummy/delorean/blame_report.dl +110 -15
  125. data/spec/dummy/delorean/data_report.dl +4 -4
  126. data/spec/dummy/delorean/marty_fields.dl +63 -0
  127. data/spec/dummy/delorean/table_report.dl +34 -0
  128. data/spec/features/auth_app_spec.rb +1 -2
  129. data/spec/features/data_import_spec.rb +2 -3
  130. data/spec/features/enum_spec.rb +42 -46
  131. data/spec/features/jobs_dashboard_spec.rb +14 -8
  132. data/spec/features/log_view_spec.rb +40 -43
  133. data/spec/features/reporting_spec.rb +15 -15
  134. data/spec/features/rule_spec.rb +195 -190
  135. data/spec/features/scripting_spec.rb +17 -20
  136. data/spec/features/scripting_test_spec.rb +32 -33
  137. data/spec/features/user_view_spec.rb +15 -17
  138. data/spec/job_helper.rb +11 -11
  139. data/spec/lib/data_blame_spec.rb +82 -0
  140. data/spec/lib/data_exporter_spec.rb +31 -32
  141. data/spec/lib/data_importer_spec.rb +382 -395
  142. data/spec/lib/delorean_query_spec.rb +117 -119
  143. data/spec/lib/json_schema_spec.rb +382 -392
  144. data/spec/lib/logger_spec.rb +23 -24
  145. data/spec/lib/mcfly_model_spec.rb +112 -109
  146. data/spec/lib/migrations_spec.rb +10 -10
  147. data/spec/lib/struct_compare_spec.rb +6 -6
  148. data/spec/lib/table_report_spec.rb +90 -0
  149. data/spec/lib/xl_spec.rb +63 -65
  150. data/spec/lib/xl_styles_spec.rb +16 -19
  151. data/spec/models/api_auth_spec.rb +30 -30
  152. data/spec/models/config_spec.rb +32 -32
  153. data/spec/models/data_grid_spec.rb +642 -655
  154. data/spec/models/event_spec.rb +96 -88
  155. data/spec/models/import_type_spec.rb +20 -20
  156. data/spec/models/posting_spec.rb +35 -35
  157. data/spec/models/promise_spec.rb +5 -5
  158. data/spec/models/rule_spec.rb +280 -269
  159. data/spec/models/script_spec.rb +27 -18
  160. data/spec/models/user_spec.rb +9 -9
  161. data/spec/other/diagnostic/base_spec.rb +20 -19
  162. data/spec/other/diagnostic/collection_spec.rb +6 -5
  163. data/spec/other/diagnostic/delayed_job_version_spec.rb +1 -1
  164. data/spec/other/diagnostic/delayed_job_workers_spec.rb +8 -8
  165. data/spec/other/diagnostic/reporter_spec.rb +31 -33
  166. data/spec/spec_helper.rb +5 -5
  167. data/spec/support/chromedriver.rb +3 -5
  168. data/spec/support/components/netzke_combobox.rb +1 -1
  169. data/spec/support/components/netzke_grid.rb +17 -17
  170. data/spec/support/custom_matchers.rb +2 -2
  171. data/spec/support/download_helper.rb +1 -1
  172. data/spec/support/helper.rb +1 -2
  173. data/spec/support/netzke.rb +31 -31
  174. data/spec/support/performance_helper.rb +8 -8
  175. data/spec/support/post_run_logger.rb +1 -2
  176. data/spec/support/setup.rb +1 -4
  177. data/spec/support/shared_connection.rb +2 -2
  178. data/spec/support/structure_compare.rb +21 -22
  179. data/spec/support/suite.rb +1 -2
  180. data/spec/support/users.rb +5 -6
  181. metadata +32 -26
@@ -1,53 +1,43 @@
1
1
  class Marty::SchemaHelper
2
2
  include Delorean::Model
3
3
 
4
- delorean_fn :enum_is, sig: 2 do
5
- |var, value|
6
- {"properties"=> {var => { "enum"=> value}}}
4
+ delorean_fn :enum_is, sig: 2 do |var, value|
5
+ { 'properties' => { var => { 'enum' => value } } }
7
6
  end
8
7
 
9
- delorean_fn :bool_is, sig: 2 do
10
- |var, value|
11
- {"allOf"=>[{"required"=>[var]},
12
- {"properties"=> {var => { "type"=> "boolean", "enum"=> [value]}}}]}
8
+ delorean_fn :bool_is, sig: 2 do |var, value|
9
+ { 'allOf' => [{ 'required' => [var] },
10
+ { 'properties' => { var => { 'type' => 'boolean', 'enum' => [value] } } }] }
13
11
  end
14
12
 
15
- delorean_fn :or, sig: [1, 20] do
16
- |*args|
17
- {"anyOf"=>args}
13
+ delorean_fn :or, sig: [1, 20] do |*args|
14
+ { 'anyOf' => args }
18
15
  end
19
16
 
20
- delorean_fn :and, sig: [1, 20] do
21
- |*args|
22
- {"allOf"=>args}
17
+ delorean_fn :and, sig: [1, 20] do |*args|
18
+ { 'allOf' => args }
23
19
  end
24
20
 
25
- delorean_fn :not, sig: 1 do
26
- |arg|
27
- {"not"=>{"allOf"=>[arg]}}
21
+ delorean_fn :not, sig: 1 do |arg|
22
+ { 'not' => { 'allOf' => [arg] } }
28
23
  end
29
24
 
30
25
  # if conds is true, var_array columns we be required
31
- delorean_fn :disallow_if_conds, sig: [2, 20] do
32
- |var_array, *conds_array|
33
- {"anyOf"=>[{"not"=>{"allOf"=> conds_array}},
34
- {"properties"=> var_array.each_with_object({}) do
35
- |v,h|
36
- h[v] = { "not" => {} }
37
- end
38
- }]}
26
+ delorean_fn :disallow_if_conds, sig: [2, 20] do |var_array, *conds_array|
27
+ { 'anyOf' => [{ 'not' => { 'allOf' => conds_array } },
28
+ { 'properties' => var_array.each_with_object({}) do |v, h|
29
+ h[v] = { 'not' => {} }
30
+ end
31
+ }] }
39
32
  end
40
33
 
41
-
42
34
  # if param is present, disallow cols
43
- delorean_fn :disallow_if_present, sig: [2, 20] do
44
- |dep_column, *var_array|
35
+ delorean_fn :disallow_if_present, sig: [2, 20] do |dep_column, *var_array|
45
36
  dep_check(dep_column,
46
- {"properties"=> var_array.each_with_object({}) do
47
- |v,h|
48
- h[v] = { "not" => {} }
49
- end
50
- })
37
+ 'properties' => var_array.each_with_object({}) do |v, h|
38
+ h[v] = { 'not' => {} }
39
+ end
40
+ )
51
41
  end
52
42
 
53
43
  # if param is not present, disallow cols
@@ -57,30 +47,26 @@ class Marty::SchemaHelper
57
47
  # it will report both the required clause and the not clauses
58
48
  # as failed. so the caller will see a message that a
59
49
  # required field is missing (which is not really a required field)
60
- delorean_fn :disallow_if_not_present, sig: [2, 20] do
61
- |dep_column, *var_array|
62
- { "anyOf" => [
63
- {"required" => [dep_column] },
64
- {"properties"=> var_array.each_with_object({}) do
65
- |v,h|
66
- h[v] = { "not" => {} }
67
- end
68
- }]}
50
+ delorean_fn :disallow_if_not_present, sig: [2, 20] do |dep_column, *var_array|
51
+ { 'anyOf' => [
52
+ { 'required' => [dep_column] },
53
+ { 'properties' => var_array.each_with_object({}) do |v, h|
54
+ h[v] = { 'not' => {} }
55
+ end
56
+ }
57
+ ] }
69
58
  end
70
59
 
71
60
  # if conds is true, var_array columns are not allowed
72
- delorean_fn :required_if, sig: [2, 20] do
73
- |var_array, *conds_array|
74
- {"anyOf"=>[{"not"=>{"allOf"=> conds_array}},
75
- {"required"=>var_array}]}
61
+ delorean_fn :required_if, sig: [2, 20] do |var_array, *conds_array|
62
+ { 'anyOf' => [{ 'not' => { 'allOf' => conds_array } },
63
+ { 'required' => var_array }] }
76
64
  end
77
65
 
78
66
  # if dep_column is present, checks must pass
79
- delorean_fn :dep_check, sig: [2, 20] do
80
- |dep_column, *checks|
81
- {"dependencies"=> {dep_column =>
82
- {"type"=>"object",
83
- "allOf"=> checks}}}
67
+ delorean_fn :dep_check, sig: [2, 20] do |dep_column, *checks|
68
+ { 'dependencies' => { dep_column =>
69
+ { 'type' => 'object',
70
+ 'allOf' => checks } } }
84
71
  end
85
-
86
72
  end
@@ -8,16 +8,17 @@ module Marty::Util
8
8
  def self.get_posting
9
9
  sid = Netzke::Base.session && Netzke::Base.session[:posting]
10
10
  return unless sid.is_a? Integer
11
+
11
12
  sid && Marty::Posting.find_by_id(sid)
12
13
  end
13
14
 
14
15
  def self.get_posting_time
15
- snap = self.get_posting
16
+ snap = get_posting
16
17
  snap ? snap.created_dt : Float::INFINITY
17
18
  end
18
19
 
19
20
  def self.warped?
20
- self.get_posting_time != Float::INFINITY
21
+ get_posting_time != Float::INFINITY
21
22
  end
22
23
 
23
24
  def self.logger
@@ -34,21 +35,21 @@ module Marty::Util
34
35
  end
35
36
 
36
37
  def self.pg_range_to_human(r)
37
- return r if r == "empty" || r.nil?
38
+ return r if r == 'empty' || r.nil?
38
39
 
39
40
  m = pg_range_match(r)
40
41
 
41
42
  raise "bad PG range #{r}" unless m
42
43
 
43
- if m[:start] == ""
44
- res = ""
44
+ if m[:start] == ''
45
+ res = ''
45
46
  else
46
- op = m[:open] == "(" ? ">" : ">="
47
+ op = m[:open] == '(' ? '>' : '>='
47
48
  res = "#{op}#{m[:start]}"
48
49
  end
49
50
 
50
- if m[:end] != ""
51
- op = m[:close] == ")" ? "<" : "<="
51
+ if m[:end] != ''
52
+ op = m[:close] == ')' ? '<' : '<='
52
53
  res += "#{op}#{m[:end]}"
53
54
  end
54
55
 
@@ -56,7 +57,7 @@ module Marty::Util
56
57
  end
57
58
 
58
59
  def self.human_to_pg_range(r)
59
- return r if r == "empty"
60
+ return r if r == 'empty'
60
61
 
61
62
  m = /\A
62
63
  ((?<op0>\>|\>=)(?<start>[^\<\>\=]*?))?
@@ -66,17 +67,17 @@ module Marty::Util
66
67
  raise "bad range #{r}" unless m
67
68
 
68
69
  if m[:op0]
69
- open = m[:op0] == ">" ? "(" : "["
70
+ open = m[:op0] == '>' ? '(' : '['
70
71
  start = "#{open}#{m[:start]}"
71
72
  else
72
- start = "["
73
+ start = '['
73
74
  end
74
75
 
75
76
  if m[:op1]
76
- close = m[:op1] == "<" ? ")" : "]"
77
+ close = m[:op1] == '<' ? ')' : ']'
77
78
  ends = "#{m[:end]}#{close}"
78
79
  else
79
- ends = "]"
80
+ ends = ']'
80
81
  end
81
82
 
82
83
  "#{start},#{ends}"
@@ -88,7 +89,7 @@ module Marty::Util
88
89
  sql = 'select pg_is_in_recovery();'
89
90
  result = ActiveRecord::Base.connection.execute(sql)
90
91
  status = result[0]['pg_is_in_recovery'] == 't' if result && result[0]
91
- rescue => e
92
+ rescue StandardError => e
92
93
  Marty::Util.logger.error 'unable to determine recovery status'
93
94
  end
94
95
  status
@@ -97,14 +98,14 @@ module Marty::Util
97
98
  def self.deep_round(obj, digits)
98
99
  case obj
99
100
  when Array
100
- obj.map {|o| deep_round(o, digits)}
101
+ obj.map { |o| deep_round(o, digits) }
101
102
  when Hash
102
- obj.inject({}) { |result, (key, value)|
103
+ obj.inject({}) do |result, (key, value)|
103
104
  result[key] = deep_round(value, digits)
104
105
  result
105
- }
106
+ end
106
107
  else
107
- obj.is_a?(Float)? obj.round(digits) : obj
108
+ obj.is_a?(Float) ? obj.round(digits) : obj
108
109
  end
109
110
  end
110
111
 
@@ -113,7 +114,7 @@ module Marty::Util
113
114
  engine = Marty::ScriptSet.new.get_engine(script_name)
114
115
  res = engine.background_eval(node_name,
115
116
  params,
116
- ["result", "title", "format"],
117
+ ['result', 'title', 'format'],
117
118
  )
118
119
 
119
120
  promise_id = res.__promise__.id
@@ -127,18 +128,18 @@ module Marty::Util
127
128
  engine = Marty::ScriptSet.new.get_engine(script)
128
129
  format = engine.evaluate(node, 'format')
129
130
  title = params.delete(:title) || engine.evaluate(node, 'title')
130
- data = ({selected_script_name: script,
131
- selected_node: node} + params).to_json
131
+ data = ({ selected_script_name: script,
132
+ selected_node: node } + params).to_json
132
133
  URI.encode("#{Marty::Util.marty_path}/report?data=#{data}"\
133
134
  "&reptitle=#{title}&format=#{format}")
134
135
  end
135
136
 
136
137
  def self.scrub_obj(obj)
137
- trav = lambda {|o|
138
+ trav = lambda { |o|
138
139
  if o.is_a?(Hash)
139
- return o.each_with_object({}) {|(k, v), h| h[k] = trav.call(v)}
140
+ return o.each_with_object({}) { |(k, v), h| h[k] = trav.call(v) }
140
141
  elsif o.is_a?(Array)
141
- return o.map {|v| trav.call(v)}
142
+ return o.map { |v| trav.call(v) }
142
143
  elsif o.to_s.length > 10000
143
144
  o.class.to_s
144
145
  else
@@ -1,3 +1,3 @@
1
1
  module Marty
2
- VERSION = "2.5.2"
2
+ VERSION = '2.5.4'
3
3
  end
@@ -12,10 +12,10 @@ class Marty::Xl
12
12
  end
13
13
 
14
14
  def deep_copy(value)
15
- return value.each_with_object({}){|(k, v), h| h[k] = deep_copy(v)} if
15
+ return value.each_with_object({}) { |(k, v), h| h[k] = deep_copy(v) } if
16
16
  value.is_a?(Hash)
17
17
 
18
- value.is_a?(Array) ? value.map{|v| deep_copy(v)} : value
18
+ value.is_a?(Array) ? value.map { |v| deep_copy(v) } : value
19
19
  end
20
20
 
21
21
  def merge_cell_edges(a, b)
@@ -25,10 +25,9 @@ class Marty::Xl
25
25
 
26
26
  return b unless a_border.is_a?(Hash) && a_border[:edges].is_a?(Array)
27
27
 
28
- non_match = a_border.detect {
29
- |key, value|
28
+ non_match = a_border.detect do |key, value|
30
29
  key != :edges && b_border[key] != value
31
- }
30
+ end
32
31
 
33
32
  a_border[:edges].each do |edge|
34
33
  unless b_border[:edges].include? edge
@@ -37,10 +36,9 @@ class Marty::Xl
37
36
 
38
37
  # add new style/color for the new edge if there is no style
39
38
  # match with the old edges:
40
- b["border_#{edge}".to_sym] = a_border.each_with_object({}) {
41
- |(key, value), h|
39
+ b["border_#{edge}".to_sym] = a_border.each_with_object({}) do |(key, value), h|
42
40
  h[key] = value unless key == :edges
43
- } if non_match
41
+ end if non_match
44
42
  end
45
43
  end
46
44
  b
@@ -48,6 +46,7 @@ class Marty::Xl
48
46
 
49
47
  def merge_row_edges(a, b)
50
48
  return b unless a.count > 0
49
+
51
50
  a.each_index do |ind|
52
51
  b[ind] = merge_cell_edges(a[ind], deep_copy(b[ind]))
53
52
  end
@@ -70,32 +69,33 @@ class Marty::Xl
70
69
  new_row, new_style = rows[r_number], styles[r_number]
71
70
 
72
71
  (0...column_offset).each do |t|
73
- new_row[t] ||= ""
72
+ new_row[t] ||= ''
74
73
  new_style[t] ||= {}
75
74
  end
76
75
 
77
76
  d[1].each_index do |c_index|
78
- new_row[c_index+column_offset] = d[1][c_index]
77
+ new_row[c_index + column_offset] = d[1][c_index]
79
78
  end if d[1].kind_of?(Array)
80
79
 
81
- if (d.length > 2) && d[2].kind_of?(Hash) && d[2]["style"].kind_of?(Array)
82
- d[2]["style"].each_index do |c_index|
83
- new_style[c_index+column_offset] = d[2]["style"][c_index]
80
+ if (d.length > 2) && d[2].kind_of?(Hash) && d[2]['style'].kind_of?(Array)
81
+ d[2]['style'].each_index do |c_index|
82
+ new_style[c_index + column_offset] = d[2]['style'][c_index]
84
83
  end
85
84
  end
86
85
 
87
86
  # apply style for the row as a whole:
88
87
  if (d.length > 2) && d[2].kind_of?(Hash)
89
88
  d[2].each do |key, value|
90
- unless key == :style.to_s
91
- row_styles[r_number][key] = value
92
- else
89
+ if key == :style.to_s
93
90
  # skip if the style is an array: /style as an array is
94
91
  # handled by the 'apply a style to each cell' section/
95
92
  next unless value.kind_of?(Hash)
93
+
96
94
  d[1].length.times do |t|
97
- new_style[t+column_offset] = value
95
+ new_style[t + column_offset] = value
98
96
  end
97
+ else
98
+ row_styles[r_number][key] = value
99
99
  end
100
100
  end
101
101
  end
@@ -107,43 +107,44 @@ class Marty::Xl
107
107
  x1, y1, x2, y2, w, h = d[1]
108
108
  column_offset, row_offset = offset
109
109
 
110
- y_coords = y2.is_a?(Integer) || d[0] != "image" ? [y1, y2] : [y1]
111
- x_coords = x2.is_a?(Integer) || d[0] != "image" ? [x1, x2] : [x1]
110
+ y_coords = y2.is_a?(Integer) || d[0] != 'image' ? [y1, y2] : [y1]
111
+ x_coords = x2.is_a?(Integer) || d[0] != 'image' ? [x1, x2] : [x1]
112
112
 
113
113
  # add the row offset:
114
- y1, y2 = y_coords.map { |y|
114
+ y1, y2 = y_coords.map do |y|
115
115
  if y.is_a?(Integer)
116
116
  row_offset + y
117
- elsif y.is_a?(Hash) && y["off"].is_a?(Integer)
118
- last_row + y["off"]
117
+ elsif y.is_a?(Hash) && y['off'].is_a?(Integer)
118
+ last_row + y['off']
119
119
  else
120
120
  raise "bad offset #{y}"
121
121
  end
122
- }
122
+ end
123
123
 
124
124
  # add the column offset:
125
- x1, x2 = x_coords.map { |x|
125
+ x1, x2 = x_coords.map do |x|
126
126
  raise "bad range point #{x}" unless x.is_a? Integer
127
+
127
128
  column_offset + x
128
- }
129
+ end
129
130
 
130
131
  el[last_row] = [] unless
131
- el[last_row] || ["border", "image"].member?(d[0])
132
+ el[last_row] || ['border', 'image'].member?(d[0])
132
133
 
133
134
  case d[0]
134
- when "conditional_formatting"
135
+ when 'conditional_formatting'
135
136
  el[last_row] << [d[0], [x1, y1, x2, y2], d[2]]
136
- when "merge"
137
+ when 'merge'
137
138
  el[last_row] << [d[0], [x1, y1, x2, y2]]
138
- when "border"
139
+ when 'border'
139
140
  el << [d[0], [x1, y1, x2, y2], d[2]]
140
- when "image"
141
+ when 'image'
141
142
  el << [d[0], [x1, y1, x2, y2, w, h], d[2]]
142
143
  end
143
144
  end
144
145
 
145
146
  def position_borders(borders)
146
- b_styles = []
147
+ b_styles = []
147
148
  borders.each do |b|
148
149
  top_row, middle_row, bottom_row, edge_h = [], [], [], {}
149
150
  br, range, defaults = b
@@ -156,7 +157,7 @@ class Marty::Xl
156
157
 
157
158
  boxborders = Hash.new do |hash, key|
158
159
  hash[key] = {
159
- border: defaults.merge( {edges: key.to_s.split('_').map(&:to_sym)} )
160
+ border: defaults.merge(edges: key.to_s.split('_').map(&:to_sym))
160
161
  }
161
162
  end
162
163
 
@@ -168,16 +169,16 @@ class Marty::Xl
168
169
  if col0 == colw
169
170
  # vertical line
170
171
  edge_h[tro], edge_h[mro], edge_h[bro] =
171
- ["left"], ["left"], ["left"]
172
+ ['left'], ['left'], ['left']
172
173
  elsif row0 == rowh
173
174
  # horizontal line
174
175
  edge_h[tro], edge_h[mro], edge_h[bro] =
175
- ["top"]*3, ["top"]*3, ["top"]*3
176
+ ['top'] * 3, ['top'] * 3, ['top'] * 3
176
177
  else
177
178
  # box
178
- edge_h[tro] = ["top_left", "top_right", "top"]
179
- edge_h[mro] = ["left", "right", "nil"]
180
- edge_h[bro] = ["bottom_left", "bottom_right", "bottom"]
179
+ edge_h[tro] = ['top_left', 'top_right', 'top']
180
+ edge_h[mro] = ['left', 'right', 'nil']
181
+ edge_h[bro] = ['bottom_left', 'bottom_right', 'bottom']
181
182
  end
182
183
 
183
184
  [top_row, middle_row, bottom_row].each do |r|
@@ -189,7 +190,7 @@ class Marty::Xl
189
190
 
190
191
  # counter == col0 == (colw - 1) => merge the edges:
191
192
  a = boxborders[edge_h[r.object_id][1].to_sym] =
192
- merge_cell_edges(a, deep_copy(boxborders[edge_h[r.object_id][1].to_sym])) if
193
+ merge_cell_edges(a, deep_copy(boxborders[edge_h[r.object_id][1].to_sym])) if
193
194
  counter == (colw - 1)
194
195
 
195
196
  a = boxborders[edge_h[r.object_id][2].to_sym] unless
@@ -209,7 +210,7 @@ class Marty::Xl
209
210
 
210
211
  a = i == 0 ? top_row : []
211
212
 
212
- a = merge_row_edges(a,bottom_row) if
213
+ a = merge_row_edges(a, bottom_row) if
213
214
  i == (rowh - row0 - 1)
214
215
 
215
216
  a = middle_row unless
@@ -234,43 +235,42 @@ class Marty::Xl
234
235
 
235
236
  if rlen < rlenmax
236
237
  rows[index] ||= []
237
- rows[index] += [""] * (rlenmax-rlen)
238
+ rows[index] += [''] * (rlenmax - rlen)
238
239
  end
239
240
 
240
241
  row_styles[index] ||= {}
241
242
 
242
243
  rsi = row_styles[index]
243
244
 
244
- rsi["style"] = styles[index].kind_of?(Array) ? styles[index] : []
245
+ rsi['style'] = styles[index].kind_of?(Array) ? styles[index] : []
245
246
 
246
247
  if b_styles[index].kind_of?(Array) && b_styles[index].count > 0
247
- len = [rsi["style"].count, b_styles[index].count].max
248
+ len = [rsi['style'].count, b_styles[index].count].max
248
249
 
249
250
  len.times do |ind|
250
251
  b_styles[index][ind] ||= {}
251
- rsi["style"][ind] ||= {}
252
+ rsi['style'][ind] ||= {}
252
253
 
253
- rsi["style"][ind] =
254
- rsi["style"][ind].merge(b_styles[index][ind])
254
+ rsi['style'][ind] =
255
+ rsi['style'][ind].merge(b_styles[index][ind])
255
256
  end
256
257
 
257
- rsi["style"] = rsi["style"].map{ |x| x || {} }
258
+ rsi['style'] = rsi['style'].map { |x| x || {} }
258
259
  end
259
260
 
260
- wsrows << ["row", rows[index], rsi]
261
+ wsrows << ['row', rows[index], rsi]
261
262
 
262
263
  if format[index] && format[index].kind_of?(Array)
263
264
  format[index].each do |f|
264
265
  raise "wrong number of arguments for #{f[0]}" unless
265
266
  [
266
- ["conditional_formatting", 3],
267
- ["merge", 2]
267
+ ['conditional_formatting', 3],
268
+ ['merge', 2]
268
269
  ].member?([f[0], f.length])
269
270
 
270
271
  wsrows << f
271
272
  end
272
273
  end
273
-
274
274
  end
275
275
 
276
276
  apply_relative_worksheet_ops(ws, wsrows + images)
@@ -285,18 +285,18 @@ class Marty::Xl
285
285
 
286
286
  # We got some sort of error if the worksheets is an array
287
287
  if worksheets.is_a? Hash
288
- ws = wb.add_worksheet(name: "EXCEPTION")
289
- ws.add_row ["error", worksheets["error"]]
290
- ws.add_row ["backtrace", worksheets["backtrace"]]
288
+ ws = wb.add_worksheet(name: 'EXCEPTION')
289
+ ws.add_row ['error', worksheets['error']]
290
+ ws.add_row ['backtrace', worksheets['backtrace']]
291
291
  return
292
292
  end
293
293
 
294
294
  raise "expected worksheets array, got: #{worksheets}" unless
295
295
  worksheets.is_a?(Array)
296
296
 
297
- worksheets << ["No data", []] if worksheets.count == 0
297
+ worksheets << ['No data', []] if worksheets.count == 0
298
298
 
299
- worksheets.each { |opl|
299
+ worksheets.each do |opl|
300
300
  name, ops, opts = opl
301
301
 
302
302
  raise "bad worksheet name: #{name}" unless name.is_a?(String)
@@ -318,17 +318,17 @@ class Marty::Xl
318
318
  ws.sheet_view.show_grid_lines = gridlines
319
319
 
320
320
  apply_relative_worksheet_ops(ws, ops)
321
- }
321
+ end
322
322
  @package.use_shared_strings = true
323
323
  end
324
324
 
325
325
  def add_style(style)
326
- raise "bad style" unless style.is_a?(Hash) || style.is_a?(Array)
326
+ raise 'bad style' unless style.is_a?(Hash) || style.is_a?(Array)
327
327
 
328
328
  if style.is_a?(Array)
329
- style.map { |s|
329
+ style.map do |s|
330
330
  styles[s] ||= package.workbook.styles.add_style(s)
331
- }
331
+ end
332
332
  else
333
333
  styles[style] ||= package.workbook.styles.add_style(style)
334
334
  end
@@ -336,71 +336,74 @@ class Marty::Xl
336
336
 
337
337
  def intern_range(ws, range)
338
338
  return range if range.is_a? String
339
- raise "bad range #{range}" unless range.is_a?(Array) && range.length==4
339
+ raise "bad range #{range}" unless range.is_a?(Array) && range.length == 4
340
+
340
341
  x1, y1, x2, y2 = range
341
342
 
342
- y1, y2 = [y1, y2].map { |y|
343
+ y1, y2 = [y1, y2].map do |y|
343
344
  next y unless y.is_a?(Hash)
344
- raise "bad offset #{y}" unless y["off"].is_a?(Integer)
345
- ws.rows.last.row_index + y["off"]
346
- }
345
+ raise "bad offset #{y}" unless y['off'].is_a?(Integer)
346
+
347
+ ws.rows.last.row_index + y['off']
348
+ end
347
349
 
348
- [x1, y1, x2, y2].each { |x|
350
+ [x1, y1, x2, y2].each do |x|
349
351
  raise "bad range point #{x}" unless x.is_a? Integer
350
- }
351
- Axlsx.cell_r(x1, y1) + ":" + Axlsx.cell_r(x2, y2)
352
+ end
353
+ Axlsx.cell_r(x1, y1) + ':' + Axlsx.cell_r(x2, y2)
352
354
  end
353
355
 
354
356
  def recalc_offsets(ops_pos)
355
357
  new_ops1, new_ops2, new_ops = [], [], []
356
358
  # precalculate the offsets of pos options embedded in another pos opt:
357
- ops_pos.each { |d|
358
- new_ops1 += d[2].select { |inner_ops|
359
- inner_ops if inner_ops[0] == "pos"
360
- }.map { |inner|
361
- [inner[0], d[1].zip(inner[1]).map { |x,y| x+y }, inner[2] ]
362
- }
363
- }
359
+ ops_pos.each do |d|
360
+ new_ops1 += d[2].select do |inner_ops|
361
+ inner_ops if inner_ops[0] == 'pos'
362
+ end.map do |inner|
363
+ [inner[0], d[1].zip(inner[1]).map { |x, y| x + y }, inner[2]]
364
+ end
365
+ end
364
366
  # keep the offsets of non-pos options embedded in pos opt:
365
- new_ops2 = ops_pos.map { |d|
366
- [ d[0], d[1], d[2].select{|inner| inner if inner[0] != "pos" } ]
367
- }
367
+ new_ops2 = ops_pos.map do |d|
368
+ [d[0], d[1], d[2].select { |inner| inner if inner[0] != 'pos' }]
369
+ end
368
370
  new_ops = new_ops1 + new_ops2
369
- count = new_ops.select { |d|
370
- d[2].select { |inner_ops|
371
- inner_ops if inner_ops[0] == "pos"
372
- }.count > 0
373
- }.count
371
+ count = new_ops.select do |d|
372
+ d[2].select do |inner_ops|
373
+ inner_ops if inner_ops[0] == 'pos'
374
+ end.count > 0
375
+ end.count
374
376
 
375
377
  count == 0 ? new_ops.sort : recalc_offsets(new_ops)
376
378
  end
377
379
 
378
380
  def apply_relative_worksheet_ops(ws, ops)
379
-
380
- non_pos = ops.select {|opl| opl[0] != "pos" }
381
- ops_pos = ops.select {|opl| opl[0] == "pos" }
382
- ops_brd = ops.select {|opl| opl[0] == "border" }
381
+ non_pos = ops.select { |opl| opl[0] != 'pos' }
382
+ ops_pos = ops.select { |opl| opl[0] == 'pos' }
383
+ ops_brd = ops.select { |opl| opl[0] == 'border' }
383
384
 
384
385
  if (ops_pos.count > 0)
385
386
  # Wrap all non-pos options in a pos option with offset 0, 0:
386
- pos_00_ops = non_pos.count > 0 ? [ ["pos", [0, 0], non_pos] ] : []
387
+ pos_00_ops = non_pos.count > 0 ? [['pos', [0, 0], non_pos]] : []
387
388
  # Recalculate the offsets of embedded pos opts:
388
- ops = pos_00_ops + recalc_offsets(ops_pos)
389
+ ops = pos_00_ops + recalc_offsets(ops_pos)
389
390
  elsif (ops_brd.count > 0)
390
391
  # Wrap the non-pos options in a pos opt with offset 0, 0:
391
- pos_00_ops = [ ["pos", [0, 0], non_pos] ]
392
+ pos_00_ops = [['pos', [0, 0], non_pos]]
392
393
  ops = pos_00_ops
393
394
  end
394
395
 
395
396
  rows, styles, row_styles, format, borders, images = [], [], [], [], [], []
396
- ops.each { |opl|
397
+ ops.each do |opl|
397
398
  raise "bad op #{opl}" unless opl.length > 1
399
+
398
400
  case opl[0]
399
- when "pos"
401
+ when 'pos'
400
402
  op, offset, data = opl
401
403
  raise "bad offset #{offset}" unless
402
404
  offset.is_a?(Array) && offset.length == 2 &&
403
- offset.all? {|x| x.is_a? Integer}
405
+ offset.all? { |x| x.is_a? Integer }
406
+
404
407
  # column offset, row offset:
405
408
  column_offset, row_offset = offset
406
409
  r_number, last_row = row_offset, row_offset
@@ -409,23 +412,24 @@ class Marty::Xl
409
412
  raise "non array data #{d[1]}" unless d[1].is_a?(Array)
410
413
  raise "non hash data options #{d[2]}" unless
411
414
  [NilClass, Hash, String, Array].member? d[2].class
415
+
412
416
  case d[0]
413
- when "row"
417
+ when 'row'
414
418
  position_row(d, column_offset, r_number, rows, styles, row_styles)
415
419
  last_row = r_number
416
420
  r_number += 1
417
- when "conditional_formatting", "merge"
421
+ when 'conditional_formatting', 'merge'
418
422
  position_elem(d, offset, last_row, format)
419
- when "border"
423
+ when 'border'
420
424
  position_elem(d, offset, last_row, borders)
421
- when "image"
425
+ when 'image'
422
426
  position_elem(d, offset, last_row, images)
423
427
  else
424
428
  raise "unknown op #{d[0]} embedded in 'position' option"
425
429
  end
426
430
  end
427
431
 
428
- when "row"
432
+ when 'row'
429
433
  op, data, options = opl
430
434
 
431
435
  raise "bad row op #{opl}" unless data.is_a?(Array) || opl.length > 3
@@ -438,11 +442,11 @@ class Marty::Xl
438
442
 
439
443
  ws.add_row data, options
440
444
 
441
- when "row_style"
445
+ when 'row_style'
442
446
  op, row_num, style = opl
443
447
 
444
448
  # FIXME: need to handle Array?
445
- raise "non hash arg for row_style" unless style.is_a?(Hash)
449
+ raise 'non hash arg for row_style' unless style.is_a?(Hash)
446
450
  raise "bad row num #{opl}" unless row_num.is_a?(Integer)
447
451
 
448
452
  style = self.class.symbolize_keys(style, ':')
@@ -452,17 +456,18 @@ class Marty::Xl
452
456
 
453
457
  row.style = style_id
454
458
 
455
- when "merge"
459
+ when 'merge'
456
460
  op, range = opl
457
461
 
458
462
  raise "bad merge op #{opl}" unless opl.length == 2
463
+
459
464
  range = intern_range(ws, range)
460
465
 
461
466
  ws.merge_cells range
462
- when "conditional_formatting"
467
+ when 'conditional_formatting'
463
468
  op, range, format = opl
464
469
 
465
- raise "non hash arg for format" unless format.is_a?(Hash)
470
+ raise 'non hash arg for format' unless format.is_a?(Hash)
466
471
 
467
472
  range = intern_range(ws, range)
468
473
 
@@ -471,11 +476,11 @@ class Marty::Xl
471
476
  color_scale_a = format[:color_scale]
472
477
 
473
478
  if color_scale_a
474
- raise "color_scale must be an array" unless
479
+ raise 'color_scale must be an array' unless
475
480
  color_scale_a.is_a?(Array)
476
481
 
477
- raise "non-hash color_scale element" unless
478
- color_scale_a.all? {|x| x.is_a?(Hash)}
482
+ raise 'non-hash color_scale element' unless
483
+ color_scale_a.all? { |x| x.is_a?(Hash) }
479
484
 
480
485
  format[:color_scale] = Axlsx::ColorScale.new(*color_scale_a)
481
486
  end
@@ -484,13 +489,15 @@ class Marty::Xl
484
489
  format[:dxfId] = add_style(dxfid) if dxfid.is_a?(Hash)
485
490
 
486
491
  ws.add_conditional_formatting(range, format)
487
- when "image"
492
+ when 'image'
488
493
  op, range, img = opl
489
494
  raise "bad image params #{range}" unless
490
495
  range.is_a?(Array) && range.length == 6
496
+
491
497
  x1, y1, x2, y2, w, h = range
492
498
  raise "bad image range, width or height #{range}" unless
493
- [ x1, y1, w, h ].all? {|x| x.is_a? Integer}
499
+ [x1, y1, w, h].all? { |x| x.is_a? Integer }
500
+
494
501
  ws.add_image(image_src: "#{Rails.public_path}/images/#{img}",
495
502
  noSelect: true,
496
503
  noMove: true) do |image|
@@ -502,28 +509,27 @@ class Marty::Xl
502
509
  else
503
510
  raise "unknown op #{opl[0]}"
504
511
  end
505
- }
506
- worksheet_rows(ws,rows,styles,row_styles,format,borders,images) unless
507
- [ops_pos.count, ops_brd.count].all?{ |a| a == 0 }
512
+ end
513
+ worksheet_rows(ws, rows, styles, row_styles, format, borders, images) unless
514
+ [ops_pos.count, ops_brd.count].all? { |a| a == 0 }
508
515
  end
509
516
 
510
517
  # recursive symbolize_keys. FIXME: this belongs in a generic
511
518
  # library somewhere.
512
- def self.symbolize_keys(obj, sym_str=nil)
519
+ def self.symbolize_keys(obj, sym_str = nil)
513
520
  case obj
514
521
  when Array
515
- obj.map {|x| symbolize_keys(x, sym_str)}
522
+ obj.map { |x| symbolize_keys(x, sym_str) }
516
523
  when Hash
517
- obj.inject({}) { |result, (key, value)|
524
+ obj.inject({}) do |result, (key, value)|
518
525
  key = key.to_sym if key.is_a?(String)
519
526
  result[key] = symbolize_keys(value, sym_str)
520
527
  result
521
- }
528
+ end
522
529
  when String
523
530
  (sym_str && obj.starts_with?(sym_str)) ? obj[sym_str.length..-1].to_sym : obj
524
531
  else
525
532
  obj
526
533
  end
527
534
  end
528
-
529
535
  end