ecoportal-api-v2 1.1.8 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,4 @@
1
-
2
- lib = File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require "ecoportal/api/v2_version"
5
4
 
@@ -9,25 +8,27 @@ Gem::Specification.new do |spec|
9
8
  spec.authors = ["Oscar Segura"]
10
9
  spec.email = ["rien@ecoportal.co.nz", "oscar@ecoportal.co.nz", "bozydar@ecoportal.co.nz"]
11
10
 
12
- spec.summary = %q{A collection of helpers for interacting with the ecoPortal MS's V2 API}
11
+ spec.summary = "A collection of helpers for interacting with the ecoPortal MS's V2 API"
13
12
  spec.homepage = "https://www.ecoportal.com"
14
13
  spec.licenses = %w[MIT]
15
14
 
16
- spec.required_ruby_version = '>= 2.7.2'
15
+ spec.metadata['rubygems_mfa_required'] = 'true'
16
+
17
+ spec.required_ruby_version = '>= 3.2.2'
17
18
 
18
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
20
  f.match(%r{^(test|spec|features)/})
20
21
  end
21
22
  spec.bindir = "exe"
22
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
24
  spec.require_paths = ["lib"]
24
25
 
25
- spec.add_development_dependency "bundler", ">= 2.4.12", "< 3"
26
- spec.add_development_dependency "rspec", ">= 3.12.0", "< 4"
27
- spec.add_development_dependency "rake", ">= 13.0.3", "< 14"
28
- spec.add_development_dependency "yard", ">= 0.9.34", "< 1"
29
- spec.add_development_dependency "redcarpet", ">= 3.6.0", "< 4"
30
- spec.add_development_dependency "pry" , ">= 0.14"
26
+ spec.add_development_dependency "pry" , '>= 0.14'
27
+ spec.add_development_dependency "rake", '>= 13.0.3', "< 14"
28
+ spec.add_development_dependency "redcarpet", '>= 3.6.0', "< 4"
29
+ spec.add_development_dependency "rspec", '>= 3.12.0', "< 4"
30
+ spec.add_development_dependency "yard", '~> 0.9.34'
31
31
 
32
- spec.add_dependency 'ecoportal-api', '>= 0.9.6', '< 0.10'
32
+ spec.add_dependency 'ecoportal-api', '~> 0.10'
33
+ spec.add_dependency 'mime-types', '~> 3.5', '>= 3.5.2'
33
34
  end
@@ -14,59 +14,63 @@ module Ecoportal
14
14
  @benchmark_enabled
15
15
  end
16
16
 
17
- def benchmarking(ref = nil, print: false)
17
+ def benchmarking(ref = nil, units: 1, print: false, &block)
18
18
  return yield unless benchmark_enabled?
19
- benchmark_mem(ref, print: false) do
20
- benchmark_time(ref, print: false) do
21
- yield
22
- end
19
+ benchmark_mem(ref, units: units, print: false) do
20
+ benchmark_time(ref, units: units, print: false, &block)
23
21
  end.tap do
24
22
  puts "\n#{bench_summary_ref(ref)}" if print
25
23
  end
26
24
  end
27
25
 
28
- def benchmark_mem(ref = nil, print: false)
26
+ def benchmark_mem(ref = nil, units: 1, print: false)
29
27
  return yield unless benchmark_enabled?
28
+
30
29
  memory_before = memory_usage
31
30
  yield.tap do
32
31
  memory_after = memory_usage
33
32
  mb_footprint = ((memory_after - memory_before) / 1024.0).round(2)
34
- bench_add_mem(ref, mb_footprint)
33
+ bench_add_mem(ref, mb_footprint, units: units)
35
34
  puts bench_str_mem(mb, ref: ref, reffix: true) if print
36
35
  end
37
36
  end
38
37
 
39
- def benchmark_time(ref = nil, print: false)
38
+ def benchmark_time(ref = nil, units: 1, print: false)
40
39
  return yield unless benchmark_enabled?
40
+
41
41
  result = nil
42
42
  time = benchmark.realtime do
43
43
  result = yield
44
44
  end.round(2)
45
+
45
46
  result.tap do
46
- bench_add_time(ref, time)
47
+ bench_add_time(ref, time, units: units)
47
48
  puts bench_str_time(time, ref: ref, reffix: true) if print
48
49
  end
49
50
  end
50
51
 
51
52
  def benchmark_summary(ref = nil)
52
- return '' unless benchmark_enabled?
53
+ return '' unless benchmark_enabled?
53
54
  return bench_summary_ref(ref) unless ref == :all
54
55
 
55
- bench.keys.each_with_object([]) do |ref, out|
56
- out << bench_summary_ref(ref)
56
+ bench.keys.each_with_object([]) do |rf, out|
57
+ out << bench_summary_ref(rf)
57
58
  end.join("\n")
58
59
  end
59
60
 
60
61
  def bench_summary_ref(ref = nil)
61
62
  ref_lines = bench_summary_ref_lines(ref)
62
- "- #{ref}\n" + " • " + ref_lines.join("\n • ")
63
+ msg = "- #{ref}\n"
64
+ msg << " • "
65
+ msg << ref_lines.join("\n • ")
66
+ msg
63
67
  end
64
68
 
65
69
  def bench_summary_ref_lines(ref = nil)
66
70
  ref_bench = bench_get(ref)
67
71
  [
68
- bench_str_time(*ref_bench[:time].values_at(:avg, :cnt), ref: ref),
69
- bench_str_mem(*ref_bench[:mem].values_at(:avg, :cnt), ref: ref)
72
+ bench_str_time(*ref_bench[:time].values_at(:avg, :cnt, :last), ref: ref),
73
+ bench_str_mem(*ref_bench[:mem].values_at(:avg, :cnt, :last), ref: ref)
70
74
  ]
71
75
  end
72
76
 
@@ -79,12 +83,12 @@ module Ecoportal
79
83
  @bench ||= {}
80
84
  end
81
85
 
82
- def bench_add_mem(ref, mem)
83
- bench_data_push(bench_get(ref)[:mem], mem)
86
+ def bench_add_mem(ref, mem, units: 1)
87
+ bench_data_push(bench_get(ref)[:mem], mem, units: units)
84
88
  end
85
89
 
86
- def bench_add_time(ref, time)
87
- bench_data_push(bench_get(ref)[:time], time)
90
+ def bench_add_time(ref, time, units: 1)
91
+ bench_data_push(bench_get(ref)[:time], time, units: units)
88
92
  end
89
93
 
90
94
  def bench_get(ref)
@@ -96,50 +100,58 @@ module Ecoportal
96
100
 
97
101
  def bench_data
98
102
  {
99
- avg: nil,
100
- cnt: 0
103
+ avg: nil,
104
+ cnt: 0,
105
+ last: nil
101
106
  }
102
107
  end
103
108
 
104
- def bench_data_push(data, value)
105
- total = value + ( (data[:avg] || 0) * data[:cnt])
106
- data[:cnt] += 1
109
+ def bench_data_push(data, value, units: 1)
110
+ total = value + ((data[:avg] || 0) * data[:cnt])
111
+ data[:last] = value.round(3)
112
+ data[:cnt] += units
107
113
  data[:avg] = (total / data[:cnt]).round(3)
108
114
  data
109
115
  end
110
116
 
111
- def bench_str_mem(mem, count = nil, ref: nil, reffix: false)
112
- ref = reffix ? ref : nil
117
+ def bench_str_mem(mem, count = nil, last = nil, ref: nil, reffix: false)
118
+ ref = nil unless reffix
113
119
  msg = [ref, 'Memory'].compact.join(' -- ')
114
- cnt = count ? " (cnt: #{count})" : ''
120
+ cnt = count ? " (cnt: #{count}; lst: #{last} MB)" : ''
115
121
  "#{msg}: #{mem} MB#{cnt}"
116
122
  end
117
123
 
118
124
  def active_support_duration?
119
125
  return false unless Kernel.const_defined?(:ActiveSupport)
126
+
120
127
  ActiveSupport.const_defined?(:Duration, false)
121
128
  end
122
129
 
123
- def bench_str_time(time, count = nil, ref: nil, reffix: false)
124
- ref = reffix ? ref : nil
130
+ def bench_str_time(time, count = nil, last = nil, ref: nil, reffix: false)
131
+ ref = nil unless reffix
125
132
  msg = [ref, 'Time'].compact.join(' -- ')
126
133
  total = (time * count).round(2)
127
134
  str_desc = ''
135
+
128
136
  if active_support_duration? && total >= 60
129
137
  duration = ActiveSupport::Duration.build(total.round)
130
- str_desc = ": #{duration_to_s(duration)}"
138
+ str_desc = " > #{duration_to_s(duration)}"
131
139
  end
132
- cnt = count ? " (cnt: #{count}; sum: #{total} s#{str_desc})" : ''
140
+
141
+ cnt = count ? " (cnt: #{count}; lst: #{last} s ; sum: #{total} s#{str_desc})" : ''
133
142
  "#{msg}: #{time} s#{cnt}"
134
143
  end
135
144
 
136
145
  def duration_to_s(value)
137
- return "" unless active_support_duration?
138
- return "" if value.nil?
146
+ return '' unless active_support_duration?
147
+ return '' if value.nil?
148
+
149
+ msg = "Expecint ActiveSupport::Duration. Given: #{value.class}"
150
+ raise ArgumentError, msg unless value.is_a?(ActiveSupport::Duration)
139
151
 
140
- raise ArgumentError, "Expecint ActiveSupport::Duration. Given: #{value.class}" unless value.is_a?(ActiveSupport::Duration)
141
152
  parts = value.parts.map {|pair| pair.reverse.join(" ")}
142
153
  return parts.first if parts.length == 1
154
+
143
155
  [parts[..-2].join(", "), parts.last].join(" and ")
144
156
  end
145
157
 
@@ -148,6 +160,7 @@ module Ecoportal
148
160
  if Gem.win_platform?
149
161
  wmem = `wmic process where processid=#{Process.pid} get WorkingSetSize | findstr "[0-9]"`
150
162
  return 0 unless wmem
163
+
151
164
  wmem.lines.first.chop.strip.to_i / 1024.0
152
165
  else
153
166
  `ps -o rss= -p #{Process.pid}`.to_i
@@ -0,0 +1,41 @@
1
+ module Ecoportal
2
+ module API
3
+ module Common
4
+ module Concerns
5
+ module Threadable
6
+ private
7
+
8
+ def new_thread(threads, max: 20, &block)
9
+ if max == 1
10
+ yield
11
+ return []
12
+ end
13
+
14
+ threads.shift.join if threads.count >= max
15
+ threads << Thread.new(&block)
16
+ end
17
+
18
+ def mutex(key = :general)
19
+ require 'thread'
20
+ key = key.to_sym
21
+ @mutex ||= {}
22
+ @mutex[key] ||= Mutex.new
23
+ end
24
+
25
+ def with_preserved_thread_globals(abort: false, report: true)
26
+ mutex(:thread_globals).synchronize do
27
+ aux_thr_aoe = Thread.abort_on_exception
28
+ aux_thr_roe = Thread.report_on_exception
29
+ Thread.abort_on_exception = abort
30
+ Thread.report_on_exception = report
31
+ yield
32
+ ensure
33
+ Thread.abort_on_exception = aux_thr_aoe
34
+ Thread.report_on_exception = aux_thr_roe
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -7,4 +7,5 @@ module Ecoportal
7
7
  end
8
8
  end
9
9
 
10
+ require 'ecoportal/api/common/concerns/threadable'
10
11
  require 'ecoportal/api/common/concerns/benchmarkable'
@@ -8,8 +8,8 @@ module Ecoportal
8
8
  class ArrayModel < Content::DoubleModel
9
9
  class TypeMismatchedComparison < StandardError
10
10
  def initialize(this: nil, that: msg = "Trying to compare objects with different behavior.")
11
- msg += " From object with 'order_matters: #{this.order_matters?}' and 'uniq: #{this.uniq?}'." if this
12
- msg += " To object where 'order_matters: #{that.order_matters?}' and 'uniq: #{that.uniq?}'." if that
11
+ msg << " From object with 'order_matters: #{this.order_matters?}' and 'uniq: #{this.uniq?}'." if this
12
+ msg << " To object where 'order_matters: #{that.order_matters?}' and 'uniq: #{that.uniq?}'." if that
13
13
  super(msg)
14
14
  end
15
15
  end
@@ -22,7 +22,7 @@ module Ecoportal
22
22
  # @param a [ArrayModel]
23
23
  # @param b [ArrayModel]
24
24
  # @return [Boolean] `true` if both elements have same behaviour
25
- def same_type?(a, b)
25
+ def same_type?(a, b) # rubocop:disable Naming/MethodParameterName
26
26
  msg = "To use this comparison both objects should be `ArrayModel`"
27
27
  raise msg unless a.is_a?(ArrayModel) && b.is_a?(ArrayModel)
28
28
  (a.order_matters? == b.order_matters?) && (a.uniq? == b.uniq?)
@@ -57,6 +57,7 @@ module Ecoportal
57
57
 
58
58
  def each(&block)
59
59
  return to_enum(:each) unless block
60
+
60
61
  _items.each(&block)
61
62
  end
62
63
 
@@ -273,12 +274,14 @@ module Ecoportal
273
274
  def into_a(value)
274
275
  raise "Can't convert to 'Array' a 'Hash', as is a key_value pair Enumerable" if value.is_a?(Hash)
275
276
  return value.to_a.slice(0..-1) if value.is_a?(Enumerable)
277
+
276
278
  [].push(value).compact
277
279
  end
278
280
 
279
281
  def deletion!(value)
280
282
  return _items.delete(value) if uniq?
281
283
  return unless (idx = _items.index(value))
284
+
282
285
  _items.slice!(idx)
283
286
  end
284
287
  end
@@ -41,7 +41,7 @@ module Ecoportal
41
41
  # @param key [String, Symbol] to be normalized
42
42
  # @return [String] a correct constant name
43
43
  def to_constant(key)
44
- key.to_s.strip.split(/::/).compact.map do |str|
44
+ key.to_s.strip.split('::').compact.map do |str|
45
45
  str.slice(0).upcase + str.slice(1..-1)
46
46
  end.join.split(/[\-\_ :]+/i).compact.map do |str|
47
47
  str.slice(0).upcase + str.slice(1..-1)
@@ -67,15 +67,17 @@ module Ecoportal
67
67
  # If the class for `name` exists, it returns it. Otherwise it generates it.
68
68
  # @param name [String, Symbol] the name of the new class
69
69
  # @param inherits [Class] the parent class to _inherit_ from
70
- # @param namespace [Class, String] an existing `constant` (class or module) the new class will be namespaced on
70
+ # @param namespace [Class, String] an existing `constant` (class or module)
71
+ # the new class will be namespaced on
71
72
  # @yield [child_class] configure the new class
72
73
  # @yieldparam child_class [Class] the new class
73
74
  # @return [Class] the new generated class
74
75
  def new_class(name = "Child#{uid}", inherits: self, namespace: inherits)
75
- name = name.to_s.to_sym.freeze
76
- class_name = to_constant(name)
76
+ name = name.to_s.to_sym.freeze
77
+ class_name = to_constant(name)
78
+ target_class = resolve_class("#{namespace}::#{class_name}", exception: false)
77
79
 
78
- unless target_class = resolve_class("#{namespace}::#{class_name}", exception: false)
80
+ unless target_class
79
81
  target_class = Class.new(inherits)
80
82
  Kernel.const_get(namespace.to_s).const_set class_name, target_class
81
83
  end
@@ -131,9 +133,11 @@ module Ecoportal
131
133
  # Builds the attr_reader and attr_writer of `attrs` and registers the associated instance variable as inheritable.
132
134
  def inheritable_attrs(*attrs)
133
135
  attrs.each do |attr|
134
- class_eval %(
135
- class << self; attr_accessor :#{attr} end
136
- )
136
+ class_eval <<-DEF_CLSS_ATTR, __FILE__, __LINE__ + 1
137
+ class << self # class << self
138
+ attr_accessor :#{attr} # attr_accessor :coolio
139
+ end # end
140
+ DEF_CLSS_ATTR
137
141
  end
138
142
  inheritable_class_vars(*attrs)
139
143
  end
@@ -142,7 +142,7 @@ module Ecoportal
142
142
  #print "{{#{p}}}"
143
143
  end
144
144
  else
145
- show_str = \
145
+ show_str =
146
146
  case value
147
147
  when Hash
148
148
  value.pretty_inspect
@@ -329,20 +329,20 @@ module Ecoportal
329
329
  end
330
330
 
331
331
  def _doc_upsert(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
332
- current_pos =
333
- if (elem = self[value])
334
- _doc_key(elem)
335
- end
332
+ elem = self[value]
333
+ current_pos = nil
334
+ current_pos = _doc_key(elem) if elem
336
335
 
337
336
  pos = scope_position(pos: pos, before: before, after: after)
338
337
  pos ||= current_pos
339
338
 
340
339
  if current_pos && pos
341
340
  _doc_items.delete_at(current_pos)
342
- pos = pos <= current_pos ? pos : pos - 1
341
+ pos -= 1 unless pos <= current_pos
343
342
  end
344
343
 
345
- pos = (pos && pos < _doc_items.length)? pos : _doc_items.length # rubocop:disable Style/TernaryParentheses
344
+ pos = _doc_items.length unless pos && pos < _doc_items.length
345
+
346
346
  pos.tap do |_i|
347
347
  _doc_items.insert(pos, value)
348
348
  end
@@ -7,25 +7,26 @@ module Ecoportal
7
7
 
8
8
  attr_reader :response, :result
9
9
 
10
- def initialize(response, klass, key: nil)
10
+ def initialize(response, klass, key: nil) # rubocop:disable Lint/MissingSuper
11
11
  @response = response
12
12
  @klass = klass
13
13
  @key = key
14
14
 
15
- if @response.success?
16
- @result =
17
- if data.is_a?(Array)
18
- data.map do |doc|
19
- @klass.new(doc)
20
- end
21
- else
22
- @klass.new(data)
15
+ return unless @response.success?
16
+
17
+ @result =
18
+ if data.is_a?(Array)
19
+ data.map do |doc|
20
+ @klass.new(doc)
23
21
  end
24
- end
22
+ else
23
+ @klass.new(data)
24
+ end
25
25
  end
26
26
 
27
27
  def data
28
28
  return @data if instance_variable_defined?(:@data)
29
+
29
30
  @data = (response.body || {})["data"]
30
31
  @data = @data[@key] if @key && @data
31
32
  @data
@@ -34,7 +35,6 @@ module Ecoportal
34
35
  def body
35
36
  data.to_s
36
37
  end
37
-
38
38
  end
39
39
  end
40
40
  end
@@ -25,8 +25,8 @@ module Ecoportal
25
25
  ref_ids.each do |ref_id|
26
26
  next if reference_ids.include?(ref_id)
27
27
  refs.push({
28
- "id" => ref_id,
29
- "weight" => 0,
28
+ "id" => ref_id,
29
+ "weight" => 0,
30
30
  "patch_ver" => 0
31
31
  })
32
32
  end
@@ -39,9 +39,13 @@ module Ecoportal
39
39
 
40
40
  def delete(*ref_ids)
41
41
  ref_ids.each do |ref_id|
42
- if doc_ref = doc["references"].find {|doc_ref| doc_ref["id"] == ref_id}
43
- doc["references"].delete(doc_ref)
42
+ doc_ref = doc["references"].find do |df|
43
+ df["id"] == ref_id
44
44
  end
45
+
46
+ next unless doc_ref
47
+
48
+ doc["references"].delete(doc_ref)
45
49
  end
46
50
  end
47
51
 
@@ -62,21 +66,21 @@ module Ecoportal
62
66
  self.display_fields = true
63
67
  self.display_fields_in_lookup = true
64
68
  when Hash
65
- supported = [:create, :attach, :metadata]
66
- unless (rest = hash_except(cnf.dup, *supported)).empty?
67
- unused.push(rest)
68
- end
69
- if cnf.key?(:create) then self.hide_create = !cnf[:create] end
70
- if cnf.key?(:attach) then self.hide_attach = !cnf[:attach] end
71
- if cnf.key?(:metadata) then self.hide_metadata = !cnf[:metadata] end
69
+ supported = %i[create attach metadata]
70
+ rest = hash_except(cnf.dup, *supported)
71
+
72
+ unused.push(rest) unless rest.empty?
73
+
74
+ self.hide_create = !cnf[:create] if cnf.key?(:create)
75
+ self.hide_attach = !cnf[:attach] if cnf.key?(:attach)
76
+ self.hide_metadata = !cnf[:metadata] if cnf.key?(:metadata)
72
77
  else
73
78
  unused.push(cnf)
74
79
  end
75
- end.yield_self do |unused|
80
+ end.then do |unused|
76
81
  super(*unused)
77
82
  end
78
83
  end
79
-
80
84
  end
81
85
  end
82
86
  end
@@ -14,7 +14,7 @@ module Ecoportal
14
14
  class_resolver :plain_text_field_class, "Ecoportal::API::V2::Page::Component::PlainTextField"
15
15
  class_resolver :rich_text_field_class, "Ecoportal::API::V2::Page::Component::RichTextField"
16
16
  class_resolver :people_field_class, "Ecoportal::API::V2::Page::Component::PeopleField"
17
- class_resolver :contractor_entities_field_class, "Ecoportal::API::V2::Page::Component::ContractorEntitiesField"
17
+ class_resolver :contractor_entities_field_class, "Ecoportal::API::V2::Page::Component::ContractorEntitiesField" # rubocop:disable Layout/LineLength
18
18
  class_resolver :checklist_field_class, "Ecoportal::API::V2::Page::Component::ChecklistField"
19
19
  class_resolver :action_field_class, "Ecoportal::API::V2::Page::Component::ActionField"
20
20
  class_resolver :actions_field_class, "Ecoportal::API::V2::Page::Component::ActionsField"
@@ -112,6 +112,7 @@ module Ecoportal
112
112
  def ref(any_length: false)
113
113
  digest = self.class.hash_label(label, any_length: any_length)
114
114
  return unless digest
115
+
115
116
  [type, digest].join(".")
116
117
  end
117
118
 
@@ -165,7 +166,7 @@ module Ecoportal
165
166
  # @note careful with this, depending what's done in the force, this may brake the force.
166
167
  def replace(fld)
167
168
  if fld.section
168
- fld.move(section: self.section, before: self)
169
+ fld.move(section: section, before: self)
169
170
  else
170
171
  section.add(fld, before: self)
171
172
  end
@@ -178,7 +179,7 @@ module Ecoportal
178
179
  end
179
180
 
180
181
  def delete!
181
- bindings.each {|b| b.delete!}
182
+ bindings.each(&:delete!)
182
183
  unattach!
183
184
  _parent.delete!(self)
184
185
  end
@@ -216,7 +217,9 @@ module Ecoportal
216
217
  unused.push(cnf)
217
218
  end
218
219
  end.tap do |unused|
219
- raise "Unsupported configuration options '#{unused}' for #{self.class}" unless unused.empty?
220
+ next if unused.empty?
221
+
222
+ raise "Unsupported configuration options '#{unused}' for #{self.class}"
220
223
  end
221
224
  end
222
225
  end
@@ -43,7 +43,7 @@ module Ecoportal
43
43
 
44
44
  # It sets the `script` value by using `custom_script` and `helpers[N..1].script`
45
45
  def update_script
46
- doc["script"] = helpers.to_a.reverse.map(&:script).push(self.custom_script).join("\n")
46
+ doc["script"] = helpers.to_a.reverse.map(&:script).push(custom_script).join("\n")
47
47
  end
48
48
  end
49
49
  end
@@ -5,27 +5,26 @@ module Ecoportal
5
5
  class Stages < Common::Content::CollectionModel
6
6
  class_resolver :stage_class, "Ecoportal::API::V2::Page::Stage"
7
7
 
8
- self.klass = :stage_class
8
+ self.klass = :stage_class
9
9
  self.order_key = :ordering
10
-
10
+
11
11
  def ooze
12
- self._parent.ooze
12
+ _parent.ooze
13
13
  end
14
14
 
15
15
  # @param name [String, Regexp] the `name` of the stage to find.
16
16
  # @return [Ecoportal::API::V2::Page::Stage, nil]
17
17
  def get_by_name(name)
18
- self.find do |stage|
18
+ find do |stage|
19
19
  same_string?(stage.name, name)
20
20
  end
21
21
  end
22
22
 
23
23
  def ordered
24
- self.sort_by.with_index do |stage, index|
24
+ sort_by.with_index do |stage, index|
25
25
  [stage.ordering, index]
26
26
  end
27
27
  end
28
-
29
28
  end
30
29
  end
31
30
  end