eco-helpers 0.6.17 → 0.7.1

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +19 -0
  3. data/.yardopts +2 -2
  4. data/Gemfile +6 -0
  5. data/Rakefile +27 -0
  6. data/eco-helpers.gemspec +9 -6
  7. data/lib/eco/api.rb +2 -1
  8. data/lib/eco/api/common/people.rb +1 -1
  9. data/lib/eco/api/common/people/base_parser.rb +31 -1
  10. data/lib/eco/api/common/people/default_parsers.rb +5 -1
  11. data/lib/eco/api/common/people/default_parsers/csv_parser.rb +37 -0
  12. data/lib/eco/api/common/people/default_parsers/numeric_parser.rb +0 -1
  13. data/lib/eco/api/common/people/entries.rb +14 -18
  14. data/lib/eco/api/common/people/entry_factory.rb +97 -9
  15. data/lib/eco/api/common/people/person_entry.rb +147 -206
  16. data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +212 -0
  17. data/lib/eco/api/common/people/person_factory.rb +10 -12
  18. data/lib/eco/api/common/people/person_parser.rb +97 -37
  19. data/lib/eco/api/common/session/base_session.rb +1 -2
  20. data/lib/eco/api/common/session/file_manager.rb +1 -1
  21. data/lib/eco/api/organization.rb +2 -1
  22. data/lib/eco/api/organization/people.rb +54 -22
  23. data/lib/eco/api/organization/person_schemas.rb +54 -0
  24. data/lib/eco/api/organization/policy_groups.rb +5 -9
  25. data/lib/eco/api/organization/{presets.rb → presets_factory.rb} +1 -1
  26. data/lib/eco/api/policies.rb +10 -0
  27. data/lib/eco/api/policies/base_policy.rb +14 -0
  28. data/lib/eco/api/policies/policy.rb +20 -0
  29. data/lib/eco/api/policies/used_policies.rb +37 -0
  30. data/lib/eco/api/session.rb +36 -34
  31. data/lib/eco/api/session/batch.rb +94 -44
  32. data/lib/eco/api/session/batch_job.rb +108 -48
  33. data/lib/eco/api/session/batch_jobs.rb +4 -5
  34. data/lib/eco/api/session/batch_status.rb +70 -11
  35. data/lib/eco/api/session/config.rb +22 -5
  36. data/lib/eco/api/session/config/files.rb +10 -1
  37. data/lib/eco/api/session/config/people.rb +18 -5
  38. data/lib/eco/api/session/config/policies.rb +29 -0
  39. data/lib/eco/api/session/config/use_cases.rb +3 -7
  40. data/lib/eco/api/session/job_groups.rb +9 -10
  41. data/lib/eco/api/usecases.rb +2 -1
  42. data/lib/eco/api/usecases/base_case.rb +7 -2
  43. data/lib/eco/api/usecases/default_cases/change_email_case.rb +4 -2
  44. data/lib/eco/api/usecases/default_cases/create_case.rb +2 -1
  45. data/lib/eco/api/usecases/default_cases/create_details_case.rb +3 -1
  46. data/lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb +4 -2
  47. data/lib/eco/api/usecases/default_cases/hris_case.rb +20 -13
  48. data/lib/eco/api/usecases/default_cases/new_email_case.rb +3 -1
  49. data/lib/eco/api/usecases/default_cases/new_id_case.rb +4 -2
  50. data/lib/eco/api/usecases/default_cases/recover_db_case.rb +9 -5
  51. data/lib/eco/api/usecases/default_cases/remove_account_case.rb +4 -2
  52. data/lib/eco/api/usecases/default_cases/set_supervisor_case.rb +4 -2
  53. data/lib/eco/api/usecases/default_cases/to_csv_case.rb +2 -2
  54. data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +2 -2
  55. data/lib/eco/api/usecases/default_cases/update_case.rb +16 -2
  56. data/lib/eco/api/usecases/default_cases/update_details_case.rb +3 -1
  57. data/lib/eco/api/usecases/default_cases/upsert_case.rb +25 -3
  58. data/lib/eco/api/usecases/use_case.rb +23 -140
  59. data/lib/eco/api/usecases/use_case_chain.rb +95 -0
  60. data/lib/eco/api/usecases/use_case_io.rb +117 -0
  61. data/lib/eco/api/usecases/use_group.rb +25 -5
  62. data/lib/eco/common/base_cli_backup.rb +1 -0
  63. data/lib/eco/language/models.rb +1 -1
  64. data/lib/eco/language/models/collection.rb +42 -31
  65. data/lib/eco/language/models/parser_serializer.rb +68 -0
  66. data/lib/eco/version.rb +1 -1
  67. metadata +93 -38
  68. data/lib/eco/api/common/people/types.rb +0 -47
  69. data/lib/eco/api/usecases/case_data.rb +0 -13
  70. data/lib/eco/language/models/attribute_parser.rb +0 -38
  71. data/lib/eco/lexic/dictionary.rb +0 -33
  72. data/lib/eco/lexic/dictionary/dictionary.txt +0 -355484
  73. data/lib/eco/lexic/dictionary/tags.json +0 -38
@@ -8,8 +8,10 @@ module Eco
8
8
  @cases.define("new-email", type: :sync) do |entries, people, session, options|
9
9
  job = session.job_group("main").new("update", type: :update, sets: :core)
10
10
 
11
+ strict_search = session.config.people.strict_search? || options.dig(:search, :strict)
12
+
11
13
  entries.each.with_index do |entry, i|
12
- if person = people.find(entry)
14
+ if person = people.find(entry, strict: strict_search)
13
15
  person.email = entry.email
14
16
  job.add(person)
15
17
  else
@@ -5,11 +5,13 @@ module Eco
5
5
  class NewIdCase < BaseCase
6
6
 
7
7
  def process
8
- @cases.define("new-id", type: :sync) do |entries, people, session|
8
+ @cases.define("new-id", type: :sync) do |entries, people, session, options|
9
9
  job = session.job_group("main").new("update", type: :update, sets: :core)
10
10
 
11
+ strict_search = session.config.people.strict_search? || options.dig(:search, :strict)
12
+
11
13
  entries.each.with_index do |entry, i|
12
- if person = people.find(entry)
14
+ if person = people.find(entry, strict: strict_search)
13
15
  person.external_id = entry.external_id
14
16
  job.add(person)
15
17
  else
@@ -14,15 +14,15 @@ module Eco
14
14
  update = session.job_group("main").new("update", type: :update, sets: [:core, :details, :account])
15
15
  remove = session.job_group("main").new("remove", type: :delete, sets: [:core, :details, :account])
16
16
 
17
+ strict_search = session.config.people.strict_search? || options.dig(:search, :strict)
17
18
  pgs = session.policy_groups
18
19
 
19
20
  if options.dig(:include, :delete)
20
21
  people.exclude(entries).map {|person| remove.add(person)}
21
22
  end
22
23
 
23
-
24
24
  entries.each.with_index do |entry, i|
25
- create = ! (person = people.find(entry))
25
+ create = ! (person = people.find(entry, strict: strict_search))
26
26
 
27
27
  if create && !options.dig(:include, :create)
28
28
  session.logger.error("Entry(#{i}) - this person does not exist: #{entry.email}")
@@ -32,11 +32,15 @@ module Eco
32
32
  unless options.dig(:exclude, :core)
33
33
  person.external_id = entry.external_id
34
34
  person.name = entry.name
35
- person.email = entry.email unless (options.dig(:exclude, :email))
36
- person.supervisor_id = entry.supervisor_id
35
+ person.email = entry.email unless options.dig(:exclude, :email)
36
+ person.supervisor_id = entry.supervisor_id unless options.dig(:exclude, :supervisor)
37
+ end
38
+
39
+ unless options.dig(:exclude, :account)
40
+ person.account = entry.account
41
+ person.account&.send_invites = options[:send_invites] if options.key?(:send_invites)
37
42
  end
38
43
 
39
- person.account = entry.account unless options.dig(:exclude, :account)
40
44
  person.details = entry.details unless options.dig(:exclude, :details)
41
45
 
42
46
  creation.add(person) if create
@@ -14,11 +14,13 @@ module Eco
14
14
  end
15
15
  end
16
16
 
17
- @cases.define("remove-account", type: :sync) do |entries, people, session|
17
+ @cases.define("remove-account", type: :sync) do |entries, people, session, options|
18
18
  update = session.job_group("main").new("update", type: :update, sets: [:core, :account])
19
19
 
20
+ strict_search = session.config.people.strict_search? || options.dig(:search, :strict)
21
+
20
22
  entries.each.with_index do |entry, i|
21
- if person = people.find(entry)
23
+ if person = people.find(entry, strict: strict_search)
22
24
  person.account = nil
23
25
  update.add(person)
24
26
  else
@@ -5,11 +5,13 @@ module Eco
5
5
  class SetSupervisorCase < BaseCase
6
6
 
7
7
  def process
8
- @cases.define("set-supervisor", type: :sync) do |entries, people, session|
8
+ @cases.define("set-supervisor", type: :sync) do |entries, people, session, options|
9
9
  job = session.job_group("main").new("update", type: :update, sets: :core)
10
10
 
11
+ strict_search = session.config.people.strict_search? || options.dig(:search, :strict)
12
+
11
13
  entries.each.with_index do |entry, i|
12
- person = people.find(entry)
14
+ person = people.find(entry, strict: strict_search)
13
15
 
14
16
  if !person
15
17
  session.logger.error("Entry(#{i}) - this person does not exist: #{entry.to_s(:identify)}")
@@ -18,8 +18,8 @@ module Eco
18
18
 
19
19
  session.logger.info("going to create file: #{file}")
20
20
  CSV.open(file, "w") do |csv|
21
- deps = {"supervisor_id" => {people: people}}
22
- entry = session.new_entry(people.first, dependencies: deps)
21
+ deps = {"supervisor_id" => {people: people}}
22
+ entry = session.new_entry(people.first, dependencies: deps)
23
23
  header = entry.to_hash.keys
24
24
 
25
25
  if options.dig(:nice_header)
@@ -20,8 +20,8 @@ module Eco
20
20
 
21
21
  session.logger.info("going to create file: #{file}")
22
22
  CSV.open(file, "w") do |csv|
23
- deps = {"supervisor_id" => {people: people}}
24
- header = session.new_entry(people.first, dependencies: deps).to_hash.keys
23
+ deps = {"supervisor_id" => {people: people}}
24
+ header = session.new_entry(people.first, dependencies: deps).to_hash.keys
25
25
  header += abilities
26
26
 
27
27
  csv << header
@@ -5,13 +5,24 @@ module Eco
5
5
  class UpdateCase < BaseCase
6
6
 
7
7
  def process
8
+ #opts = CLI::Options.new do |p|
9
+ # p.option :exclude, "Allows to exclude certain options"
10
+ # p.suboption :exclude, :core, "Excludes core details from the update.", optional: true
11
+ # p.suboption :exclude, :details, "Excludes schema details from the update.", optional: true
12
+ # p.suboption :exclude, :account, "Excludes account details from the update.", optional: true
13
+ # p.suboption :exclude, :email, "Excludes core email from the update.", optional: true
14
+ # p.suboption :exclude, :supervisor, "Excludes supervisor_id from the update.", optional: true
15
+ # p.suboption :exclude, :abilities, "Excludes the abilities from the update.", optional: true
16
+ #end
17
+
8
18
  @cases.define("update", type: :sync) do |entries, people, session, options|
9
19
  update = session.job_group("main").new("update", type: :update, sets: [:core, :details, :account])
10
20
 
21
+ strict_search = session.config.people.strict_search? || options.dig(:search, :strict)
11
22
  pgs = session.policy_groups
12
23
 
13
24
  entries.each.with_index do |entry, i|
14
- if person = people.find(entry)
25
+ if person = people.find(entry, strict: strict_search)
15
26
  core_excluded = ["supervisor_id"]
16
27
  core_excluded.push("email") if options.dig(:exclude, :email)
17
28
  entry.set_core(person, exclude: core_excluded) unless options.dig(:exclude, :core)
@@ -27,7 +38,7 @@ module Eco
27
38
  final: person.account.policy_group_ids
28
39
  )
29
40
 
30
- person.account.permissions_custom = session.new_preset(person) unless options.dig(:exclude, :abilities)
41
+ person.account.permissions_custom = session.new_preset(person) unless !create && options.dig(:exclude, :abilities)
31
42
 
32
43
  if session.tagtree
33
44
  person.account.filter_tags = session.tagtree.user_tags(
@@ -41,6 +52,9 @@ module Eco
41
52
  tags = person.account.filter_tags
42
53
  person.account.default_tag = tags.first unless tags.length > 1
43
54
  end
55
+
56
+ person.account&.send_invites = options[:send_invites] if options.key?(:send_invites)
57
+
44
58
  end
45
59
  update.add(person)
46
60
  else
@@ -8,8 +8,10 @@ module Eco
8
8
  @cases.define("update-details", type: :sync) do |entries, people, session, options|
9
9
  job = session.job_group("main").new("update", type: :update, sets: [:core, :details])
10
10
 
11
+ strict_search = session.config.people.strict_search? || options.dig(:search, :strict)
12
+
11
13
  entries.each.with_index do |entry, i|
12
- if person = people.find(entry)
14
+ if person = people.find(entry, strict: strict_search)
13
15
  core_excluded = ["supervisor_id"]
14
16
  core_excluded.push("email") if options.dig(:exclude, :email)
15
17
  entry.set_core(person, exclude: core_excluded) unless options.dig(:exclude, :core)
@@ -8,11 +8,13 @@ module Eco
8
8
  @cases.define("upsert", type: :sync) do |entries, people, session, options|
9
9
  creation = session.job_group("main").new("create", type: :create, sets: [:core, :details, :account])
10
10
  update = session.job_group("main").new("update", type: :update, sets: [:core, :details, :account])
11
+ supers = session.job_group("post").new("supers", type: :update, sets: :core)
11
12
 
13
+ strict_search = session.config.people.strict_search? || options.dig(:search, :strict)
12
14
  pgs = session.policy_groups
13
15
 
14
16
  entries.each.with_index do |entry, i|
15
- create = ! (person = people.find(entry))
17
+ create = ! (person = people.find(entry, strict: strict_search))
16
18
  person = session.new_person if create
17
19
 
18
20
  core_excluded = ["supervisor_id"]
@@ -25,14 +27,14 @@ module Eco
25
27
  ini_tags = person.account&.filter_tags || []
26
28
  entry.set_account(person)
27
29
 
28
- person.account.send_invites = false if options.key?(:send_invites) && !options(:send_invites)
30
+ person.account.send_invites = options[:send_invites] if options.key?(:send_invites)
29
31
 
30
32
  person.account.policy_group_ids = pgs.user_pg_ids(
31
33
  initial: ini_pg_ids,
32
34
  final: person.account.policy_group_ids
33
35
  )
34
36
 
35
- person.account.permissions_custom = session.new_preset(person) unless options.dig(:exclude, :abilities)
37
+ person.account.permissions_custom = session.new_preset(person) unless !create && options.dig(:exclude, :abilities)
36
38
 
37
39
  if session.tagtree
38
40
  person.account.filter_tags = session.tagtree.user_tags(
@@ -46,10 +48,30 @@ module Eco
46
48
  tags = person.account.filter_tags
47
49
  person.account.default_tag = tags.first unless tags.length > 1
48
50
  end
51
+
49
52
  end
50
53
 
51
54
  creation.add(person) if create
52
55
  update.add(person) unless create
56
+
57
+ # set supervisor
58
+ unless options.dig(:exclude, :core) || options.dig(:exclude, :supervisor)
59
+ if !(sup_id = entry.supervisor_id)
60
+ person.supervisor_id = nil
61
+ else
62
+ if supervisor = people.person(id: sup_id, external_id: sup_id, email: sup_id)
63
+ person.supervisor_id = supervisor.id
64
+ else
65
+ # delay setting supervisor if does not exit
66
+ supers.add(person) do |person|
67
+ person.consolidate!
68
+ person.supervisor_id = sup_id
69
+ person
70
+ end
71
+ end
72
+ end
73
+ end
74
+
53
75
  end
54
76
  end
55
77
  end
@@ -10,164 +10,47 @@ module Eco
10
10
  transform: [:people, :session],
11
11
  export: [:people, :session, :options]
12
12
  }
13
- MAX_CHAINS = 70
14
- @@num_chains = 0
15
13
 
16
- attr_reader :name, :type, :times_used
14
+ attr_reader :name, :type, :times_launched
15
+
16
+ class << self
17
+ def valid_type?(type)
18
+ TYPES.include?(type)
19
+ end
20
+
21
+ def type_params(type)
22
+ raise "Invalid type '#{type.to_s}'" if !valid_type?(type)
23
+ TYPE_PARAMS[type]
24
+ end
25
+ end
17
26
 
18
27
  def initialize(name, type:, root:, options: {}, &block)
28
+ raise "Undefine usecase type #{type}. Please, use any of #{TYPES}" unless self.class.valid_type?(type)
19
29
 
20
30
  self.root = root
21
- @case = block
22
- @name = name
23
- @type = type
24
- @options = options
25
-
26
- @chains = []
27
- @resolved_chains = nil
28
- @times_used = 0
31
+ @case = block
32
+ @name = name
33
+ @type = type
34
+ @options = options
35
+ @times_launched = 0
29
36
  end
30
37
 
31
38
  def root=(value)
32
- raise "You cannot change root UseGroup once the chains have been resolved" if @resolved_chains
33
39
  raise "Root should be a UseGroup. Given: #{value}" if !value.is_a?(UseGroup)
34
40
  @root = value
35
41
  end
36
42
 
37
- def use(preserve_chains: false, recursive: false)
38
- newcase = UseCase.new(@name, type: @type, root: @root, options: @options, &@case)
39
- if preserve_chains
40
- chain_use = {preserve_chains: recursive, recursive: recursive}
41
- @chains = @chains.map do |usecase|
42
- if usecase.respond_to? :call
43
- Proc.new do |usegroup|
44
- usecase = usecase.call(usegroup)
45
- usecase.use(chain_use).chain_to(newcase)
46
- usecase
47
- end
48
- else
49
- usecase.use(chain_use).chain_to(newcase)
50
- usecase
51
- end
52
- end
53
- end
54
- newcase
55
- end
56
-
57
- def process(input: nil, people: nil, session:, options: {})
58
- raise "This case has been already used. To create multiple instances of same use case, use 'use' method" if @done
59
- validate_args(input: input, people: people, session: session, options: options)
60
-
61
- opts = options&.dup
62
- opts = @options.merge(opts || {})
43
+ def launch(input: nil, people: nil, session:, options: {})
44
+ data = UseCaseIO.new(usecase: self, input: input, people: people, session: session, options: options)
63
45
 
64
- case @type
65
- when :import
66
- out = input = @case.call(input, session, opts)
67
- when :filter
68
- out = people = @case.call(people, session, opts)
69
- when :transform
70
- out = jobs = into_a(@case.call(people, session, opts))
71
- when :sync
72
- out = jobs = into_a(@case.call(input, people, session, opts))
73
- when :export
74
- out = stat = @case.call(people, session, opts)
75
- end
76
- @times_used += 1
46
+ data.output = @case.call(data.params)
47
+ @times_launched += 1
77
48
 
78
49
  data_model = {
79
50
  self => {
80
- data: { input: input, people: people, session: session, options: opts, output: out }
51
+ io: data
81
52
  }
82
53
  }
83
- post_usecase(data_model)
84
- end
85
-
86
- def chain(usecase = nil)
87
- @@num_chains += 1
88
- raise "Reached maximum number of chained use cases (#{MAX_CHAINS}). Looks like a recursive cyclic chain 'use'" if @@num_chains >= MAX_CHAINS
89
- raise "A UseCase can only be chained with another UseCase" if usecase && !usecase.is_a?(UseCase)
90
- raise "Missuse. Please use either parameter or block but not both" if block_given? && usecase
91
- usecase = block_given?? Proc.new : usecase
92
- @chains.push(usecase)
93
- self
94
- end
95
-
96
- def self.valid_type(type)
97
- TYPES.include?(type)
98
- end
99
-
100
- def self.type_params(type)
101
- raise "Invalid type '#{type.to_s}'" if !valid_type?(type)
102
- TYPE_PARAMS[type]
103
- end
104
-
105
- protected
106
-
107
- def chain_to(usecase)
108
- raise "A UseCase can only be chained with another UseCase" if usecase && !usecase.is_a?(UseCase)
109
- usecase.chain(self)
110
- end
111
-
112
- def resolved_chains(use_group = nil)
113
- return @resolved_chains if @resolved_chains
114
- raise "Only UseGroup object can resolve chains. Given: #{use_group} " if use_group && !use_group.is_a?(UseGroup)
115
-
116
- use_group = use_group || @root
117
- @resolved_chains = @chains.map do |usecase|
118
- usecase = usecase.call(use_group) if usecase.respond_to? :call
119
- raise "A UseCase can only be chained with another UseCase" if usecase && !usecase.is_a?(UseCase)
120
- usecase.resolved_chains(use_group)
121
- usecase
122
- end
123
- @resolved_chains
124
- end
125
-
126
- private
127
-
128
- def post_usecase(data_model)
129
- return data_model if resolved_chains.empty?
130
- data_model[self][:chains] = {} unless data_model[self][:chains]
131
-
132
- resolved_chains.each do |usecase|
133
- # chained cases use same params as parent case (out of simplicity)
134
- params = data_model[self][:data].slice(*ALL_PARAMS) #TYPE_PARAMS[usecase.type])
135
- data_model[self][:chains].merge(usecase.process(params))
136
- end
137
- data_model
138
- end
139
-
140
- def validate_args(input:, people:, session:, options:)
141
- case
142
- when !session.is_a?(Eco::API::Session)
143
- raise "A UseCase needs a Session object. Given: #{session}"
144
- when input_required? && !input
145
- raise "UseCase of type '#{@type.to_s}' requires a valid input. None given"
146
- when people_required? && !people.is_a?(Eco::API::Organization::People)
147
- raise "UseCase of type '#{@type.to_s}' requires a People object. Given: #{people}"
148
- when !options || (options && !options.is_a?(Hash))
149
- raise "To inject dependencies via ':options' it should be a Hash object. Given: #{options}"
150
- when options_required? && !options
151
- raise "UseCase of type '#{@type.to_s}' requires a Hash ':options' object."
152
- end
153
- true
154
- end
155
-
156
- def input_required?
157
- [:import, :sync].include?(@type)
158
- end
159
-
160
- def people_required?
161
- [:filter, :transform, :sync, :export].include?(@type)
162
- end
163
-
164
- def options_required?
165
- [:filter].include?(@type)
166
- end
167
-
168
- def into_a(value)
169
- value = [].push(value) unless value.is_a?(Array)
170
- value
171
54
  end
172
55
 
173
56
  end
@@ -0,0 +1,95 @@
1
+ module Eco
2
+ module API
3
+ module UseCases
4
+ class UseCaseChain < UseCase
5
+ MAX_CHAINS = 70
6
+ @@num_chains = 0
7
+
8
+ def initialize(name, type:, root:, options: {}, &block)
9
+ super(name, type: type, root: root, options: options, &block)
10
+ @chains = []
11
+ @resolved_chains = nil
12
+ end
13
+
14
+ def root=(value)
15
+ raise "You cannot change root UseGroup once the chains have been resolved" if @resolved_chains
16
+ super(value)
17
+ end
18
+
19
+ def use(preserve_chains: false, recursive: false)
20
+ UseCase.new(@name, type: @type, root: @root, options: @options, &@case).tap do |newcase|
21
+ if preserve_chains
22
+ chain_use = {preserve_chains: recursive, recursive: recursive}
23
+ @chains = @chains.map do |usecase|
24
+ if usecase.respond_to? :call
25
+ Proc.new do |usegroup|
26
+ usecase = usecase.call(usegroup)
27
+ usecase.use(chain_use).chain_to(newcase)
28
+ usecase
29
+ end
30
+ elsif usecase.is_a?(UseCase)
31
+ usecase.use(chain_use).chain_to(newcase)
32
+ usecase
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def launch(input: nil, people: nil, session:, options: {})
40
+ data_model = super(input: input, people: people, session: session, options: options)
41
+ launch_chain(data_model)
42
+ end
43
+
44
+ def chain(usecase = nil)
45
+ @@num_chains += 1
46
+ raise "Reached maximum number of chained use cases (#{MAX_CHAINS}). Looks like a recursive cyclic chain 'use'" if @@num_chains >= MAX_CHAINS
47
+ raise "A UseCase can only be chained with another UseCase" if usecase && !usecase.is_a?(UseCase)
48
+ raise "Missuse. Please use either parameter or block but not both" if block_given? && usecase
49
+ usecase = block_given?? Proc.new : usecase
50
+ @chains.push(usecase)
51
+ self
52
+ end
53
+
54
+ protected
55
+
56
+ def chain_to(usecase)
57
+ raise "A UseCase can only be chained with another UseCase" if usecase && !usecase.is_a?(UseCase)
58
+ usecase.chain(self)
59
+ end
60
+
61
+ def resolved_chains(use_group = nil)
62
+ return @resolved_chains if @resolved_chains
63
+ raise "Only UseGroup object can resolve chains. Given: #{use_group} " if use_group && !use_group.is_a?(UseGroup)
64
+
65
+ use_group = use_group || @root
66
+ @resolved_chains = @chains.map do |usecase|
67
+ usecase = usecase.call(use_group) if usecase.respond_to? :call
68
+ raise "A UseCase can only be chained with another UseCase" if usecase && !usecase.is_a?(UseCase)
69
+ usecase.resolved_chains(use_group)
70
+ usecase
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ def launch_chain(data_model)
77
+ return data_model if resolved_chains.empty?
78
+
79
+ data_model.tap do |dm|
80
+ dm[self][:chains] ||= {}
81
+
82
+ resolved_chains.each do |usecase|
83
+ # chained cases use same params as parent case (out of simplicity)
84
+ data_chain = dm[self][:io].chain(usecase: usecase)
85
+ keyed_data = data_chain.params(keyed: true)
86
+ dm[self][:chains].merge(usecase.launch(keyed_data))
87
+ end
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+ end
95
+ end