checkoff 0.58.1 → 0.59.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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/checkoff/internal/project_selector_evaluator.rb +40 -0
- data/lib/checkoff/internal/selector_classes/common/function_evaluator.rb +158 -0
- data/lib/checkoff/internal/selector_classes/common.rb +226 -0
- data/lib/checkoff/internal/selector_classes/function_evaluator.rb +36 -0
- data/lib/checkoff/internal/selector_classes/project/function_evaluator.rb +161 -0
- data/lib/checkoff/internal/selector_classes/project.rb +10 -0
- data/lib/checkoff/internal/selector_classes/task/function_evaluator.rb +161 -0
- data/lib/checkoff/internal/selector_classes/task.rb +310 -0
- data/lib/checkoff/internal/selector_evaluator.rb +66 -0
- data/lib/checkoff/internal/task_selector_evaluator.rb +38 -729
- data/lib/checkoff/project_selectors.rb +9 -15
- data/lib/checkoff/tasks.rb +3 -0
- data/lib/checkoff/version.rb +1 -1
- metadata +11 -2
@@ -0,0 +1,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../function_evaluator'
|
4
|
+
|
5
|
+
module Checkoff
|
6
|
+
module SelectorClasses
|
7
|
+
module Task
|
8
|
+
# Base class to evaluate a task selector function given fully evaluated arguments
|
9
|
+
class FunctionEvaluator < ::Checkoff::SelectorClasses::FunctionEvaluator
|
10
|
+
# @param selector [Array<(Symbol, Array)>,String]
|
11
|
+
# @param tasks [Checkoff::Tasks]
|
12
|
+
def initialize(selector:,
|
13
|
+
tasks:)
|
14
|
+
@selector = selector
|
15
|
+
@tasks = tasks
|
16
|
+
super()
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# @param task [Asana::Resources::Task]
|
22
|
+
# @param field_name [Symbol]
|
23
|
+
#
|
24
|
+
# @sg-ignore
|
25
|
+
# @return [Date, nil]
|
26
|
+
def pull_date_field_by_name(task, field_name)
|
27
|
+
if field_name == :modified
|
28
|
+
return Time.parse(task.modified_at).to_date unless task.modified_at.nil?
|
29
|
+
|
30
|
+
return nil
|
31
|
+
end
|
32
|
+
|
33
|
+
if field_name == :due
|
34
|
+
return Time.parse(task.due_at).to_date unless task.due_at.nil?
|
35
|
+
|
36
|
+
return Date.parse(task.due_on) unless task.due_on.nil?
|
37
|
+
|
38
|
+
return nil
|
39
|
+
end
|
40
|
+
|
41
|
+
raise "Teach me how to handle field #{field_name}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param task [Asana::Resources::Task]
|
45
|
+
# @param field_name [Symbol]
|
46
|
+
#
|
47
|
+
# @sg-ignore
|
48
|
+
# @return [Date, Time, nil]
|
49
|
+
def pull_date_or_time_field_by_name(task, field_name)
|
50
|
+
if field_name == :due
|
51
|
+
return Time.parse(task.due_at) unless task.due_at.nil?
|
52
|
+
|
53
|
+
return Date.parse(task.due_on) unless task.due_on.nil?
|
54
|
+
|
55
|
+
return nil
|
56
|
+
end
|
57
|
+
|
58
|
+
if field_name == :start
|
59
|
+
return Time.parse(task.start_at) unless task.start_at.nil?
|
60
|
+
|
61
|
+
return Date.parse(task.start_on) unless task.start_on.nil?
|
62
|
+
|
63
|
+
return nil
|
64
|
+
end
|
65
|
+
|
66
|
+
raise "Teach me how to handle field #{field_name}"
|
67
|
+
end
|
68
|
+
|
69
|
+
# @sg-ignore
|
70
|
+
# @param task [Asana::Resources::Task]
|
71
|
+
# @param custom_field_gid [String]
|
72
|
+
# @return [Hash]
|
73
|
+
def pull_custom_field_or_raise(task, custom_field_gid)
|
74
|
+
# @type [Array<Hash>]
|
75
|
+
custom_fields = task.custom_fields
|
76
|
+
if custom_fields.nil?
|
77
|
+
raise "Could not find custom_fields under task (was 'custom_fields' included in 'extra_fields'?)"
|
78
|
+
end
|
79
|
+
|
80
|
+
# @sg-ignore
|
81
|
+
# @type [Hash, nil]
|
82
|
+
matched_custom_field = custom_fields.find { |data| data.fetch('gid') == custom_field_gid }
|
83
|
+
if matched_custom_field.nil?
|
84
|
+
raise "Could not find custom field with gid #{custom_field_gid} " \
|
85
|
+
"in task #{task.gid} with custom fields #{custom_fields}"
|
86
|
+
end
|
87
|
+
|
88
|
+
matched_custom_field
|
89
|
+
end
|
90
|
+
|
91
|
+
# @return [Array<(Symbol, Array)>]
|
92
|
+
attr_reader :selector
|
93
|
+
|
94
|
+
# @sg-ignore
|
95
|
+
# @param custom_field [Hash]
|
96
|
+
# @return [Array<String>]
|
97
|
+
def pull_enum_values(custom_field)
|
98
|
+
resource_subtype = custom_field.fetch('resource_subtype')
|
99
|
+
case resource_subtype
|
100
|
+
when 'enum'
|
101
|
+
[custom_field.fetch('enum_value')]
|
102
|
+
when 'multi_enum'
|
103
|
+
custom_field.fetch('multi_enum_values')
|
104
|
+
else
|
105
|
+
raise "Teach me how to handle resource_subtype #{resource_subtype}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# @param custom_field [Hash]
|
110
|
+
# @param enum_value [Object, nil]
|
111
|
+
# @return [Array<String>]
|
112
|
+
def find_gids(custom_field, enum_value)
|
113
|
+
if enum_value.nil?
|
114
|
+
[]
|
115
|
+
else
|
116
|
+
raise "Unexpected enabled value on custom field: #{custom_field}" if enum_value.fetch('enabled') == false
|
117
|
+
|
118
|
+
[enum_value.fetch('gid')]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# @param task [Asana::Resources::Task]
|
123
|
+
# @param custom_field_gid [String]
|
124
|
+
# @return [Array<String>]
|
125
|
+
def pull_custom_field_values_gids(task, custom_field_gid)
|
126
|
+
custom_field = pull_custom_field_or_raise(task, custom_field_gid)
|
127
|
+
pull_enum_values(custom_field).flat_map do |enum_value|
|
128
|
+
find_gids(custom_field, enum_value)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# @sg-ignore
|
133
|
+
# @param task [Asana::Resources::Task]
|
134
|
+
# @param custom_field_name [String]
|
135
|
+
# @return [Hash, nil]
|
136
|
+
def pull_custom_field_by_name(task, custom_field_name)
|
137
|
+
custom_fields = task.custom_fields
|
138
|
+
if custom_fields.nil?
|
139
|
+
raise "custom fields not found on task - did you add 'custom_fields' in your extra_fields argument?"
|
140
|
+
end
|
141
|
+
|
142
|
+
# @sg-ignore
|
143
|
+
# @type [Hash, nil]
|
144
|
+
custom_fields.find { |field| field.fetch('name') == custom_field_name }
|
145
|
+
end
|
146
|
+
|
147
|
+
# @param task [Asana::Resources::Task]
|
148
|
+
# @param custom_field_name [String]
|
149
|
+
# @return [Hash]
|
150
|
+
def pull_custom_field_by_name_or_raise(task, custom_field_name)
|
151
|
+
custom_field = pull_custom_field_by_name(task, custom_field_name)
|
152
|
+
if custom_field.nil?
|
153
|
+
raise "Could not find custom field with name #{custom_field_name} " \
|
154
|
+
"in task #{task.gid} with custom fields #{task.custom_fields}"
|
155
|
+
end
|
156
|
+
custom_field
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,310 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'task/function_evaluator'
|
4
|
+
|
5
|
+
module Checkoff
|
6
|
+
module SelectorClasses
|
7
|
+
module Task
|
8
|
+
# :tag function
|
9
|
+
class TagPFunctionEvaluator < FunctionEvaluator
|
10
|
+
def matches?
|
11
|
+
fn?(selector, :tag)
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param _index [Integer]
|
15
|
+
def evaluate_arg?(_index)
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
# @sg-ignore
|
20
|
+
# @param task [Asana::Resources::Task]
|
21
|
+
# @param tag_name [String]
|
22
|
+
# @return [Boolean]
|
23
|
+
def evaluate(task, tag_name)
|
24
|
+
task.tags.map(&:name).include? tag_name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# :due function
|
29
|
+
class DuePFunctionEvaluator < FunctionEvaluator
|
30
|
+
def matches?
|
31
|
+
fn?(selector, :due)
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param task [Asana::Resources::Task]
|
35
|
+
# @param ignore_dependencies [Boolean]
|
36
|
+
# @return [Boolean]
|
37
|
+
def evaluate(task, ignore_dependencies: false)
|
38
|
+
@tasks.task_ready?(task, ignore_dependencies: ignore_dependencies)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# :unassigned function
|
43
|
+
class UnassignedPFunctionEvaluator < FunctionEvaluator
|
44
|
+
def matches?
|
45
|
+
fn?(selector, :unassigned)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @param task [Asana::Resources::Task]
|
49
|
+
# @return [Boolean]
|
50
|
+
def evaluate(task)
|
51
|
+
task.assignee.nil?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# :due_date_set function
|
56
|
+
class DueDateSetPFunctionEvaluator < FunctionEvaluator
|
57
|
+
FUNCTION_NAME = :due_date_set
|
58
|
+
|
59
|
+
def matches?
|
60
|
+
fn?(selector, FUNCTION_NAME)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @sg-ignore
|
64
|
+
# @param task [Asana::Resources::Task]
|
65
|
+
# @return [Boolean]
|
66
|
+
def evaluate(task)
|
67
|
+
!task.due_at.nil? || !task.due_on.nil?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# :due_between_n_days function
|
72
|
+
class DueBetweenRelativePFunctionEvaluator < FunctionEvaluator
|
73
|
+
FUNCTION_NAME = :due_between_relative
|
74
|
+
|
75
|
+
def matches?
|
76
|
+
fn?(selector, FUNCTION_NAME)
|
77
|
+
end
|
78
|
+
|
79
|
+
# @param _index [Integer]
|
80
|
+
def evaluate_arg?(_index)
|
81
|
+
false
|
82
|
+
end
|
83
|
+
|
84
|
+
# @param task [Asana::Resources::Task]
|
85
|
+
# @param beginning_num_days_from_now [Integer]
|
86
|
+
# @param end_num_days_from_now [Integer]
|
87
|
+
# @param ignore_dependencies [Boolean]
|
88
|
+
#
|
89
|
+
# @return [Boolean]
|
90
|
+
def evaluate(task, beginning_num_days_from_now, end_num_days_from_now, ignore_dependencies: false)
|
91
|
+
beginning_n_days_from_now_time = (Time.now + (beginning_num_days_from_now * 24 * 60 * 60))
|
92
|
+
end_n_days_from_now_time = (Time.now + (end_num_days_from_now * 24 * 60 * 60))
|
93
|
+
|
94
|
+
# @type [Date, Time, nil]
|
95
|
+
task_date_or_time = pull_date_or_time_field_by_name(task, :start) ||
|
96
|
+
pull_date_or_time_field_by_name(task, :due)
|
97
|
+
|
98
|
+
return false if task_date_or_time.nil?
|
99
|
+
|
100
|
+
# if time
|
101
|
+
in_range = if task_date_or_time.is_a?(Time)
|
102
|
+
task_date_or_time > beginning_n_days_from_now_time &&
|
103
|
+
task_date_or_time <= end_n_days_from_now_time
|
104
|
+
else
|
105
|
+
# if date
|
106
|
+
task_date_or_time > beginning_n_days_from_now_time.to_date &&
|
107
|
+
task_date_or_time <= end_n_days_from_now_time.to_date
|
108
|
+
end
|
109
|
+
|
110
|
+
return false unless in_range
|
111
|
+
|
112
|
+
return false if !ignore_dependencies && @tasks.incomplete_dependencies?(task)
|
113
|
+
|
114
|
+
true
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# :field_less_than_n_days_ago
|
119
|
+
class FieldLessThanNDaysAgoPFunctionEvaluator < FunctionEvaluator
|
120
|
+
FUNCTION_NAME = :field_less_than_n_days_ago
|
121
|
+
|
122
|
+
def matches?
|
123
|
+
fn?(selector, FUNCTION_NAME)
|
124
|
+
end
|
125
|
+
|
126
|
+
def evaluate_arg?(_index)
|
127
|
+
false
|
128
|
+
end
|
129
|
+
|
130
|
+
# @param task [Asana::Resources::Task]
|
131
|
+
# @param field_name [Symbol]
|
132
|
+
# @param num_days [Integer]
|
133
|
+
#
|
134
|
+
# @return [Boolean]
|
135
|
+
def evaluate(task, field_name, num_days)
|
136
|
+
date = pull_date_field_by_name(task, field_name)
|
137
|
+
|
138
|
+
return false if date.nil?
|
139
|
+
|
140
|
+
# @sg-ignore
|
141
|
+
n_days_ago = Date.today - num_days
|
142
|
+
# @sg-ignore
|
143
|
+
date < n_days_ago
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# :field_greater_than_or_equal_to_n_days_from_today
|
148
|
+
class FieldGreaterThanOrEqualToNDaysFromTodayPFunctionEvaluator < FunctionEvaluator
|
149
|
+
FUNCTION_NAME = :field_greater_than_or_equal_to_n_days_from_today
|
150
|
+
|
151
|
+
def matches?
|
152
|
+
fn?(selector, FUNCTION_NAME)
|
153
|
+
end
|
154
|
+
|
155
|
+
def evaluate_arg?(_index)
|
156
|
+
false
|
157
|
+
end
|
158
|
+
|
159
|
+
# @param task [Asana::Resources::Task]
|
160
|
+
# @param field_name [Symbol]
|
161
|
+
# @param num_days [Integer]
|
162
|
+
#
|
163
|
+
# @return [Boolean]
|
164
|
+
def evaluate(task, field_name, num_days)
|
165
|
+
date = pull_date_field_by_name(task, field_name)
|
166
|
+
|
167
|
+
return false if date.nil?
|
168
|
+
|
169
|
+
# @sg-ignore
|
170
|
+
n_days_from_today = Date.today + num_days
|
171
|
+
# @sg-ignore
|
172
|
+
date >= n_days_from_today
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# :custom_field_less_than_n_days_from_now function
|
177
|
+
class CustomFieldLessThanNDaysFromNowFunctionEvaluator < FunctionEvaluator
|
178
|
+
FUNCTION_NAME = :custom_field_less_than_n_days_from_now
|
179
|
+
|
180
|
+
def matches?
|
181
|
+
fn?(selector, FUNCTION_NAME)
|
182
|
+
end
|
183
|
+
|
184
|
+
def evaluate_arg?(_index)
|
185
|
+
false
|
186
|
+
end
|
187
|
+
|
188
|
+
# @param task [Asana::Resources::Task]
|
189
|
+
# @param custom_field_name [String]
|
190
|
+
# @param num_days [Integer]
|
191
|
+
# @return [Boolean]
|
192
|
+
def evaluate(task, custom_field_name, num_days)
|
193
|
+
custom_field = pull_custom_field_by_name_or_raise(task, custom_field_name)
|
194
|
+
|
195
|
+
# @sg-ignore
|
196
|
+
# @type [String, nil]
|
197
|
+
time_str = custom_field.fetch('display_value')
|
198
|
+
return false if time_str.nil?
|
199
|
+
|
200
|
+
time = Time.parse(time_str)
|
201
|
+
n_days_from_now = (Time.now + (num_days * 24 * 60 * 60))
|
202
|
+
time < n_days_from_now
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# :custom_field_greater_than_or_equal_to_n_days_from_now function
|
207
|
+
class CustomFieldGreaterThanOrEqualToNDaysFromNowFunctionEvaluator < FunctionEvaluator
|
208
|
+
FUNCTION_NAME = :custom_field_greater_than_or_equal_to_n_days_from_now
|
209
|
+
|
210
|
+
def matches?
|
211
|
+
fn?(selector, FUNCTION_NAME)
|
212
|
+
end
|
213
|
+
|
214
|
+
def evaluate_arg?(_index)
|
215
|
+
false
|
216
|
+
end
|
217
|
+
|
218
|
+
# @param task [Asana::Resources::Task]
|
219
|
+
# @param custom_field_name [String]
|
220
|
+
# @param num_days [Integer]
|
221
|
+
# @return [Boolean]
|
222
|
+
def evaluate(task, custom_field_name, num_days)
|
223
|
+
custom_field = pull_custom_field_by_name_or_raise(task, custom_field_name)
|
224
|
+
|
225
|
+
# @sg-ignore
|
226
|
+
# @type [String, nil]
|
227
|
+
time_str = custom_field.fetch('display_value')
|
228
|
+
return false if time_str.nil?
|
229
|
+
|
230
|
+
time = Time.parse(time_str)
|
231
|
+
n_days_from_now = (Time.now + (num_days * 24 * 60 * 60))
|
232
|
+
time >= n_days_from_now
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
# :last_story_created_less_than_n_days_ago function
|
237
|
+
class LastStoryCreatedLessThanNDaysAgoFunctionEvaluator < FunctionEvaluator
|
238
|
+
FUNCTION_NAME = :last_story_created_less_than_n_days_ago
|
239
|
+
|
240
|
+
def matches?
|
241
|
+
fn?(selector, FUNCTION_NAME)
|
242
|
+
end
|
243
|
+
|
244
|
+
def evaluate_arg?(_index)
|
245
|
+
false
|
246
|
+
end
|
247
|
+
|
248
|
+
# @param task [Asana::Resources::Task]
|
249
|
+
# @param num_days [Integer]
|
250
|
+
# @param excluding_resource_subtypes [Array<String>]
|
251
|
+
# @return [Boolean]
|
252
|
+
def evaluate(task, num_days, excluding_resource_subtypes)
|
253
|
+
# for whatever reason, .last on the enumerable does not impose ordering; .to_a does!
|
254
|
+
|
255
|
+
# @type [Array<Asana::Resources::Story>]
|
256
|
+
stories = task.stories(per_page: 100).to_a.reject do |story|
|
257
|
+
excluding_resource_subtypes.include? story.resource_subtype
|
258
|
+
end
|
259
|
+
return true if stories.empty? # no stories == infinitely old!
|
260
|
+
|
261
|
+
last_story = stories.last
|
262
|
+
last_story_created_at = Time.parse(last_story.created_at)
|
263
|
+
n_days_ago = Time.now - (num_days * 24 * 60 * 60)
|
264
|
+
last_story_created_at < n_days_ago
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# :estimate_exceeds_duration
|
269
|
+
class EstimateExceedsDurationFunctionEvaluator < FunctionEvaluator
|
270
|
+
FUNCTION_NAME = :estimate_exceeds_duration
|
271
|
+
|
272
|
+
def matches?
|
273
|
+
fn?(selector, FUNCTION_NAME)
|
274
|
+
end
|
275
|
+
|
276
|
+
# @param task [Asana::Resources::Task]
|
277
|
+
# @return [Float]
|
278
|
+
def calculate_allocated_hours(task)
|
279
|
+
due_on = nil
|
280
|
+
start_on = nil
|
281
|
+
start_on = Date.parse(task.start_on) unless task.start_on.nil?
|
282
|
+
due_on = Date.parse(task.due_on) unless task.due_on.nil?
|
283
|
+
allocated_hours = 8.0
|
284
|
+
# @sg-ignore
|
285
|
+
allocated_hours = (due_on - start_on + 1).to_i * 8.0 if start_on && due_on
|
286
|
+
allocated_hours
|
287
|
+
end
|
288
|
+
|
289
|
+
# @param task [Asana::Resources::Task]
|
290
|
+
# @return [Boolean]
|
291
|
+
def evaluate(task)
|
292
|
+
custom_field = pull_custom_field_by_name_or_raise(task, 'Estimated time')
|
293
|
+
|
294
|
+
# @sg-ignore
|
295
|
+
# @type [Integer, nil]
|
296
|
+
estimate_minutes = custom_field.fetch('number_value')
|
297
|
+
|
298
|
+
# no estimate set
|
299
|
+
return false if estimate_minutes.nil?
|
300
|
+
|
301
|
+
estimate_hours = estimate_minutes / 60.0
|
302
|
+
|
303
|
+
allocated_hours = calculate_allocated_hours(task)
|
304
|
+
|
305
|
+
estimate_hours > allocated_hours
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Checkoff
|
4
|
+
# Base class to evaluate Asana resource selectors against an Asana resource
|
5
|
+
class SelectorEvaluator
|
6
|
+
# @param selector [Array]
|
7
|
+
# @return [Boolean, Object, nil]
|
8
|
+
def evaluate(selector)
|
9
|
+
return true if selector.empty?
|
10
|
+
|
11
|
+
function_evaluators.each do |evaluator_class|
|
12
|
+
# @type [SelectorClasses::FunctionEvaluator]
|
13
|
+
# @sg-ignore
|
14
|
+
evaluator = evaluator_class.new(selector: selector,
|
15
|
+
**initializer_kwargs)
|
16
|
+
|
17
|
+
next unless evaluator.matches?
|
18
|
+
|
19
|
+
return try_this_evaluator(selector, evaluator)
|
20
|
+
end
|
21
|
+
|
22
|
+
raise "Syntax issue trying to handle #{selector.inspect}"
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# @return [Hash]
|
28
|
+
def initializer_kwargs
|
29
|
+
{}
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Array<Class<FunctionEvaluator>>]
|
33
|
+
# @sg-ignore
|
34
|
+
def function_evaluators
|
35
|
+
raise 'Implement me!'
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param selector [Array]
|
39
|
+
# @param evaluator [SelectorClasses::FunctionEvaluator]
|
40
|
+
# @return [Array]
|
41
|
+
def evaluate_args(selector, evaluator)
|
42
|
+
return [] unless selector.is_a?(Array)
|
43
|
+
|
44
|
+
selector[1..].map.with_index do |item, index|
|
45
|
+
if evaluator.evaluate_arg?(index)
|
46
|
+
evaluate(item)
|
47
|
+
else
|
48
|
+
item
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param selector [Array]
|
54
|
+
# @param evaluator [SelectorClasses::FunctionEvaluator]
|
55
|
+
# @return [Boolean, Object, nil]
|
56
|
+
def try_this_evaluator(selector, evaluator)
|
57
|
+
# if selector is an array
|
58
|
+
evaluated_args = evaluate_args(selector, evaluator)
|
59
|
+
|
60
|
+
evaluator.evaluate(item, *evaluated_args)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Asana::Resources::Resource]
|
64
|
+
attr_reader :item
|
65
|
+
end
|
66
|
+
end
|