evva 0.1.4.3 → 0.4.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.
Files changed (48) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -2
  3. data/.rspec +0 -1
  4. data/.rubocop_todo.yml +10 -10
  5. data/.travis.yml +1 -0
  6. data/Gemfile +9 -8
  7. data/Gemfile.lock +7 -11
  8. data/README.md +12 -2
  9. data/Rakefile +9 -0
  10. data/changelog.md +18 -1
  11. data/evva.gemspec +0 -3
  12. data/lib/evva/{mixpanel_enum.rb → analytics_enum.rb} +2 -1
  13. data/lib/evva/analytics_event.rb +17 -0
  14. data/lib/evva/analytics_property.rb +17 -0
  15. data/lib/evva/android_generator.rb +141 -84
  16. data/lib/evva/config.rb +21 -4
  17. data/lib/evva/google_sheet.rb +69 -44
  18. data/lib/evva/swift_generator.rb +91 -81
  19. data/lib/evva/templates/kotlin/base.kt +7 -0
  20. data/lib/evva/templates/kotlin/destinations.kt +5 -0
  21. data/lib/evva/templates/kotlin/event_enum.kt +5 -0
  22. data/lib/evva/templates/kotlin/events.kt +34 -0
  23. data/lib/evva/templates/kotlin/people_properties.kt +24 -0
  24. data/lib/evva/templates/kotlin/people_properties_enum.kt +5 -0
  25. data/lib/evva/templates/kotlin/special_property_enums.kt +10 -0
  26. data/lib/evva/templates/swift/base.swift +7 -0
  27. data/lib/evva/templates/swift/destinations.swift +5 -0
  28. data/lib/evva/templates/swift/events.swift +65 -0
  29. data/lib/evva/templates/swift/people_properties.swift +49 -0
  30. data/lib/evva/templates/swift/special_property_enums.swift +10 -0
  31. data/lib/evva/version.rb +2 -2
  32. data/lib/evva.rb +16 -6
  33. data/spec/evva_spec.rb +3 -5
  34. data/spec/fixtures/sample_public_enums.csv +3 -0
  35. data/spec/fixtures/sample_public_events.csv +4 -0
  36. data/spec/fixtures/sample_public_people_properties.csv +4 -0
  37. data/spec/fixtures/test.yml +9 -4
  38. data/spec/lib/evva/android_generator_spec.rb +132 -58
  39. data/spec/lib/evva/config_spec.rb +13 -5
  40. data/spec/lib/evva/google_sheet_spec.rb +60 -72
  41. data/spec/lib/evva/swift_generator_spec.rb +153 -40
  42. metadata +23 -39
  43. data/evva_config.yml +0 -10
  44. data/lib/evva/mixpanel_event.rb +0 -13
  45. data/spec/fixtures/sample_public_enums.html +0 -1
  46. data/spec/fixtures/sample_public_info.html +0 -1
  47. data/spec/fixtures/sample_public_people_properties.html +0 -1
  48. data/spec/fixtures/sample_public_sheet.html +0 -1
@@ -1,79 +1,104 @@
1
1
  require 'net/https'
2
- require 'xmlsimple'
2
+ require 'csv'
3
3
 
4
4
  module Evva
5
5
  class GoogleSheet
6
- def initialize(sheet_id)
7
- @sheet_id = sheet_id
6
+ EVENT_NAME = 'Event Name'
7
+ EVENT_PROPERTIES = 'Event Properties'
8
+ EVENT_DESTINATION = 'Event Destination'
9
+
10
+ PROPERTY_NAME = 'Property Name'
11
+ PROPERTY_TYPE = 'Property Type'
12
+ PROPERTY_DESTINATION = 'Property Destination'
13
+
14
+ ENUM_NAME = 'Enum Name'
15
+ ENUM_VALUES = 'Possible Values'
16
+
17
+ def initialize(events_url, people_properties_url, enum_classes_url)
18
+ @events_url = events_url
19
+ @people_properties_url = people_properties_url
20
+ @enum_classes_url = enum_classes_url
8
21
  end
9
22
 
10
23
  def events
11
- event_list = []
12
- iterate_entries(raw_data(@sheet_id, 0)) do |entry|
13
- event_name = entry['eventname'].first
14
- properties = hash_parser(entry['eventproperties'].first)
15
- event_list << Evva::MixpanelEvent.new(event_name, properties)
24
+ @events_csv ||= begin
25
+ Logger.info("Downloading data from Google Sheet at #{@events_url}")
26
+ get_csv(@events_url)
27
+ end
28
+
29
+ @events ||= @events_csv.map do |row|
30
+ event_name = row[EVENT_NAME]
31
+ properties = hash_parser(row[EVENT_PROPERTIES])
32
+ destinations = row[EVENT_DESTINATION]&.split(',')
33
+ Evva::AnalyticsEvent.new(event_name, properties, destinations || [])
16
34
  end
17
- event_list
18
35
  end
19
36
 
20
37
  def people_properties
21
- people_list = []
22
- iterate_entries(raw_data(@sheet_id, 1)) do |entry|
23
- value = entry['propertyname'].first
24
- people_list << value
38
+ @people_properties_csv ||= begin
39
+ Logger.info("Downloading data from Google Sheet at #{@people_properties_url}")
40
+ get_csv(@people_properties_url)
41
+ end
42
+
43
+ @people_properties ||= @people_properties_csv.map do |row|
44
+ property_name = row[PROPERTY_NAME]
45
+ property_type = row[PROPERTY_TYPE]
46
+ destinations = row[PROPERTY_DESTINATION]&.split(',')
47
+ Evva::AnalyticsProperty.new(property_name, property_type, destinations || [])
25
48
  end
26
- people_list
27
49
  end
28
50
 
29
51
  def enum_classes
30
- enum_list = []
31
- iterate_entries(raw_data(@sheet_id, 2)) do |entry|
32
- enum_name = entry['enumname'].first
33
- values = entry['possiblevalues'].first.split(',')
34
- enum_list << Evva::MixpanelEnum.new(enum_name, values)
52
+ @enum_classes_csv ||= begin
53
+ Logger.info("Downloading data from Google Sheet at #{@enum_classes_url}")
54
+ get_csv(@enum_classes_url)
55
+ end
56
+
57
+ @enum_classes ||= @enum_classes_csv.map do |row|
58
+ enum_name = row[ENUM_NAME]
59
+ values = row[ENUM_VALUES].split(',')
60
+ Evva::AnalyticsEnum.new(enum_name, values)
35
61
  end
36
- enum_list
62
+ end
63
+
64
+ def destinations
65
+ @destinations ||= events.map(&:destinations).flatten.uniq
37
66
  end
38
67
 
39
68
  private
40
69
 
41
- def iterate_entries(data)
42
- Logger.info('Downloading dictionary from Google Sheet...')
43
- non_language_columns = %w[id updated category title content link]
44
- data['entry'].each do |entry|
45
- filtered_entry = entry.reject { |c| non_language_columns.include?(c) }
46
- yield(filtered_entry)
70
+ def get_csv(url)
71
+ data = get(url)
72
+
73
+ begin
74
+ CSV.parse(data, headers: true)
75
+ rescue StandardError => e
76
+ raise "Cannot parse. Expected CSV at #{url}: #{e}"
47
77
  end
48
78
  end
49
79
 
50
- def xml_data(uri, headers = nil)
51
- uri = URI.parse(uri)
80
+ def get(url, max_redirects = 1)
81
+ raise "Too may redirects" if max_redirects == -1
82
+
83
+ uri = URI(url)
84
+
52
85
  http = Net::HTTP.new(uri.host, uri.port)
53
86
  http.use_ssl = true
54
87
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
55
- data = http.get(uri.path, headers)
56
- unless data.code.to_i == 200
57
- raise "Cannot access sheet at #{uri} - HTTP #{data.code}"
58
- end
59
88
 
60
- begin
61
- XmlSimple.xml_in(data.body, 'KeyAttr' => 'name')
62
- rescue
63
- raise "Cannot parse. Expected XML at #{uri}"
64
- end
65
- end
89
+ request = Net::HTTP::Get.new(uri.request_uri)
90
+ response = http.request(request)
91
+
92
+ return get(response['location'], max_redirects - 1) if response.is_a? Net::HTTPRedirection
93
+
94
+ raise "Http Error #{response.body}" if response.code.to_i >= 400
66
95
 
67
- def raw_data(sheet_id, sheet_number)
68
- Logger.info('Downloading Google Sheet...')
69
- sheet = xml_data("https://spreadsheets.google.com/feeds/worksheets/#{sheet_id}/public/full")
70
- url = sheet['entry'][sheet_number]['link'][0]['href']
71
- xml_data(url)
96
+ response.body
72
97
  end
73
98
 
74
99
  def hash_parser(property_array)
75
100
  h = {}
76
- unless property_array.empty?
101
+ unless property_array.nil? || property_array.empty?
77
102
  property_array.split(',').each do |prop|
78
103
  split_prop = prop.split(':')
79
104
  prop_name = split_prop[0].to_sym
@@ -1,121 +1,132 @@
1
+ require 'erb'
2
+
1
3
  module Evva
2
4
  class SwiftGenerator
3
- EXTENSION_HEADER =
4
- "\nimport Foundation\n\n"\
5
- "extension Analytics {\n\n".freeze
5
+ BASE_TEMPLATE = File.expand_path("./templates/swift/base.swift", __dir__)
6
+ EVENTS_TEMPLATE = File.expand_path("./templates/swift/events.swift", __dir__)
7
+ PEOPLE_PROPERTIES_TEMPLATE = File.expand_path("./templates/swift/people_properties.swift", __dir__)
8
+ SPECIAL_PROPERTY_ENUMS_TEMPLATE = File.expand_path("./templates/swift/special_property_enums.swift", __dir__)
9
+ DESTINATIONS_TEMPLATE = File.expand_path("./templates/swift/destinations.swift", __dir__)
6
10
 
7
- EXTENSION_FOOTER =
8
- "\n\n}\n"
11
+ TAB_SIZE = " " # \t -> 4 spaces
9
12
 
10
- NATIVE_TYPES = %w[Int String Double Float Bool].freeze
13
+ NATIVE_TYPES = %w[Int String Double Float Bool Date].freeze
11
14
 
12
- def events(bundle, file_name)
15
+ def events(bundle, _file_name, _enums_file_name, _destinations_file_name)
13
16
  header_footer_wrapper do
14
- """\tenum Event {
15
- #{bundle.map { |e| event_case(e) }.join("\n")}
16
-
17
- \t\tvar data: EventData {
18
- \t\t\tswitch self {
19
- #{bundle.map { |e| event_data(e) }.join("\n\n")}
20
- \t\t\t}
21
- \t\t}
22
- \t}"""
17
+ events = bundle.map do |event|
18
+ properties = event.properties.map { |k, v|
19
+ type = native_type(v)
20
+
21
+ value_fetcher = k.to_s
22
+
23
+ if is_special_property?(type)
24
+ if type.end_with?('?')
25
+ # optional value, we need ? to access a parameter
26
+ value_fetcher += "?"
27
+ end
28
+ value_fetcher += ".rawValue"
29
+ end
30
+
31
+ {
32
+ name: k.to_s,
33
+ type: type,
34
+ value: value_fetcher,
35
+ }
36
+ }
37
+
38
+ {
39
+ case_name: camelize(event.event_name),
40
+ event_name: event.event_name,
41
+ properties: properties,
42
+ destinations: event.destinations.map { |p| camelize(p) },
43
+ }
44
+ end
45
+
46
+ template_from(EVENTS_TEMPLATE).result(binding)
23
47
  end
24
48
  end
25
49
 
26
- def event_case(event_data)
27
- function_name = camelize(event_data.event_name)
28
- if event_data.properties.empty?
29
- "\t\tcase #{function_name}"
30
- else
31
- trimmed_properties = event_data.properties.map { |k, v| k.to_s + ': ' + native_type(v) }.join(", ")
32
- "\t\tcase #{function_name}(#{trimmed_properties})"
33
- end
50
+ def event_enum
51
+ # empty
34
52
  end
35
53
 
36
- def event_data(event_data)
37
- function_name = camelize(event_data.event_name)
38
- if event_data.properties.empty?
39
- function_body = "\t\t\tcase .#{function_name}:\n" \
40
- "\t\t\t\treturn EventData(name: \"#{event_data.event_name}\")"
41
- else
42
- function_header = prepend_let(event_data.properties)
43
- function_arguments = dictionary_pairs(event_data.properties)
44
- function_body = "\t\t\tcase .#{function_name}(#{function_header}):\n"\
45
- "\t\t\t\treturn EventData(name: \"#{event_data.event_name}\", properties: [\n"\
46
- "\t\t\t\t\t#{function_arguments.join(",\n\t\t\t\t\t")} ]\n"\
47
- "\t\t\t\t)"
54
+ def people_properties(people_bundle, _file_name, _enums_file_name, _destinations_file_name)
55
+ header_footer_wrapper do
56
+ properties = people_bundle.map do |p|
57
+ type = native_type(p.type)
58
+ {
59
+ case_name: camelize(p.property_name),
60
+ property_name: p.property_name,
61
+ type: type,
62
+ is_special_property: is_special_property?(type),
63
+ destinations: p.destinations.map { |p| camelize(p) },
64
+ }
65
+ end
66
+
67
+ template_from(PEOPLE_PROPERTIES_TEMPLATE).result(binding)
48
68
  end
49
- function_body
50
69
  end
51
70
 
52
- def event_enum(enum, file_name)
71
+ def people_properties_enum
53
72
  # empty
54
73
  end
55
74
 
56
- def people_properties(people_bundle, file_name)
75
+ def special_property_enums(enums_bundle)
57
76
  header_footer_wrapper do
58
- props = "\tenum Property: String {\n"
59
- people_bundle.each do |prop|
60
- props << "\t\tcase #{camelize(prop)} = \"#{prop}\"\n"
77
+ enums = enums_bundle.map do |enum|
78
+ values = enum.values.map do |value|
79
+ {
80
+ case_name: camelize(value),
81
+ value: value
82
+ }
83
+ end
84
+
85
+ {
86
+ name: enum.enum_name,
87
+ values: values
88
+ }
61
89
  end
62
- props << "\t}"
90
+
91
+ template_from(SPECIAL_PROPERTY_ENUMS_TEMPLATE).result(binding)
63
92
  end
64
93
  end
65
94
 
66
- def special_property_enums(enums)
95
+ def destinations(destinations_bundle, _file_name)
67
96
  header_footer_wrapper do
68
- enums.map do |enum|
69
- body = "\tenum #{enum.enum_name}: String {\n"
70
- enum.values.each do |value|
71
- body << "\t\tcase #{camelize(value)} = \"#{value}\"\n"
72
- end
73
- body << "\t}"
74
- end.join("\n\n")
97
+ destinations = destinations_bundle.map { |p| camelize(p) }
98
+
99
+ template_from(DESTINATIONS_TEMPLATE).result(binding)
75
100
  end
76
101
  end
77
102
 
78
103
  private
79
104
 
80
105
  def header_footer_wrapper
81
- """// This file was automatically generated by evva: https://github.com/hole19/evva
82
-
83
- import Foundation
106
+ content = yield
107
+ .gsub(/^/, "\t").gsub(/^\t+$/, "") # add tabs, unless it's an empty line
108
+ .chop # trim trailing newlines created by sublime
84
109
 
85
- extension Analytics {
86
-
87
- #{yield.gsub("\t", " ")}
88
- }
89
- """
110
+ template_from(BASE_TEMPLATE).result(binding).gsub("\t", TAB_SIZE)
90
111
  end
91
112
 
92
- def dictionary_pairs(props)
93
- props.map do |name, type|
94
- pair = "\"#{name}\": #{name}"
95
- if is_raw_representable_property?(type)
96
- if is_optional_property?(type)
97
- pair += "?"
98
- end
99
- pair += ".rawValue"
100
- end
101
- pair += " as Any"
102
- end
103
- end
113
+ def template_from(path)
114
+ file = File.read(path)
104
115
 
105
- def is_raw_representable_property?(type)
106
- !NATIVE_TYPES.include?(native_type(type).chomp('?'))
107
- end
108
-
109
- def is_optional_property?(type)
110
- type.end_with?('?')
116
+ # - 2nd argument (nil) changes nothing
117
+ # - 3rd argument activates trim mode using "-" so that you can decide to
118
+ # not include a line (useful on loops and if statements)
119
+ ERB.new(file, nil, '-')
111
120
  end
112
121
 
113
122
  def native_type(type)
114
- type.gsub('Boolean','Bool').gsub('Long', 'Int')
123
+ type
124
+ .gsub('Boolean','Bool')
125
+ .gsub('Long', 'Int')
115
126
  end
116
127
 
117
- def prepend_let(props)
118
- props.map { |k, v| "let #{k}" }.join(', ')
128
+ def is_special_property?(type)
129
+ !NATIVE_TYPES.include?(type.chomp('?'))
119
130
  end
120
131
 
121
132
  def camelize(term)
@@ -125,6 +136,5 @@ extension Analytics {
125
136
  string.gsub!("/".freeze, "::".freeze)
126
137
  string
127
138
  end
128
-
129
139
  end
130
140
  end
@@ -0,0 +1,7 @@
1
+ package <%= package_name %>
2
+
3
+ /**
4
+ * This file was automatically generated by evva: https://github.com/hole19/evva
5
+ */
6
+
7
+ <%= content %>
@@ -0,0 +1,5 @@
1
+ enum class <%= class_name %> {
2
+ <%- destinations.each_with_index do |destination, index| -%>
3
+ <%= destination %><%= index == destinations.count - 1 ? ";" : "," %>
4
+ <%- end -%>
5
+ }
@@ -0,0 +1,5 @@
1
+ enum class <%= class_name %>(val key: String) {
2
+ <%- events.each_with_index do |event, index| -%>
3
+ <%= event[:name] %>("<%= event[:value] %>")<%= index == events.count - 1 ? ";" : "," %>
4
+ <%- end -%>
5
+ }
@@ -0,0 +1,34 @@
1
+ sealed class <%= class_name %>(event: <%= enums_class_name %>) {
2
+ val name = event.key
3
+
4
+ open val properties: Map<String, Any?>? = null
5
+ open val destinations: Array<<%= destinations_class_name %>> = []
6
+
7
+ <%- events.each_with_index do |e, index| -%>
8
+ <%- if e[:is_object] -%>
9
+ object <%= e[:class_name] %> : <%= class_name %>(<%= enums_class_name %>.<%= e[:event_name] %>)
10
+ <%- else -%>
11
+ data class <%= e[:class_name] %><% if e[:properties].count > 0 %>(
12
+ <%= e[:properties].map { |p| "val #{p[:param_name]}: #{p[:type]}" }.join(", ") %>
13
+ )<% end %> : <%= class_name %>(<%= enums_class_name %>.<%= e[:event_name] %>) {
14
+ <%- if e[:properties].count > 0 -%>
15
+ override val properties = mapOf(
16
+ <%- e[:properties].each_with_index do |p, index| -%>
17
+ "<%= p[:name] %>" to <%= p[:value_fetcher] %><% if index < e[:properties].count - 1 %>,<% end %>
18
+ <%- end -%>
19
+ )
20
+ <%- end -%>
21
+ <%- if e[:destinations].count > 0 -%>
22
+ override val destinations = [
23
+ <%- e[:destinations].each_with_index do |d, index| -%>
24
+ <%= destinations_class_name %>.<%= d %><% if index < e[:destinations].count - 1 %>,<% end %>
25
+ <%- end -%>
26
+ ]
27
+ <%- end -%>
28
+ }
29
+ <%- end -%>
30
+ <%- unless index == events.count - 1 -%>
31
+
32
+ <%- end -%>
33
+ <%- end -%>
34
+ }
@@ -0,0 +1,24 @@
1
+ sealed class <%= class_name %>(property: <%= enums_class_name %>) {
2
+ val name = property.key
3
+
4
+ open val value: Any = ""
5
+ open val destinations: Array<<%= destinations_class_name %>> = []
6
+
7
+ <%- properties.each_with_index do |property, index| -%>
8
+ data class <%= property[:class_name] %>(
9
+ val value: <%= property[:type] %>
10
+ ) : <%= class_name %>(<%= enums_class_name %>.<%= property[:property_name] %>) {
11
+ override val value = value<% if property[:is_special_property] %>.key<% end %>
12
+ <%- if property[:destinations].count > 0 -%>
13
+ override val destinations = [
14
+ <%- property[:destinations].each_with_index do |d, index| -%>
15
+ <%= destinations_class_name %>.<%= d %><% if index < property[:destinations].count - 1 %>,<% end %>
16
+ <%- end -%>
17
+ ]
18
+ <%- end -%>
19
+ }
20
+ <%- unless index == properties.count - 1 -%>
21
+
22
+ <%- end -%>
23
+ <%- end -%>
24
+ }
@@ -0,0 +1,5 @@
1
+ enum class <%= class_name %>(val key: String) {
2
+ <%- properties.each_with_index do |property, index| -%>
3
+ <%= property[:name] %>("<%= property[:value] %>")<%= index == properties.count - 1 ? ";" : "," %>
4
+ <%- end -%>
5
+ }
@@ -0,0 +1,10 @@
1
+ <%- enums.each_with_index do |enum, index| -%>
2
+ enum class <%= enum[:class_name] %>(val key: String) {
3
+ <%- enum[:values].each_with_index do |v, index| -%>
4
+ <%= v[:name] %>("<%= v[:value] %>")<%= index == enum[:values].count - 1 ? ";" : "," %>
5
+ <%- end -%>
6
+ }
7
+ <%- unless index == enums.count - 1 -%>
8
+
9
+ <%- end -%>
10
+ <%- end -%>
@@ -0,0 +1,7 @@
1
+ // This file was automatically generated by evva: https://github.com/hole19/evva
2
+
3
+ import Foundation
4
+
5
+ extension Analytics {
6
+ <%= content %>
7
+ }
@@ -0,0 +1,5 @@
1
+ enum Destination {
2
+ <%- destinations.each do |d| -%>
3
+ case <%= d %>
4
+ <%- end -%>
5
+ }
@@ -0,0 +1,65 @@
1
+ struct EventData {
2
+ let name: String
3
+ var properties: [String: Any]?
4
+ let destinations: [Destination]
5
+
6
+ init(name: String, properties: [String: Any]?, destinations: [Destination]) {
7
+ self.name = name
8
+ self.properties = properties
9
+ self.destinations = destinations
10
+ }
11
+
12
+ init(name: EventName, properties: [String: Any]?, destinations: [Destination]) {
13
+ self.init(name: name.rawValue, properties: properties, destinations: destinations)
14
+ }
15
+ }
16
+
17
+ enum EventName: String {
18
+ <%- events.each do |e| -%>
19
+ case <%= e[:case_name] %> = "<%= e[:event_name] %>"
20
+ <%- end -%>
21
+ }
22
+
23
+ enum Event {
24
+ <%- events.each do |e| -%>
25
+ <%- if e[:properties].count == 0 -%>
26
+ case <%= e[:case_name] %>
27
+ <%- else -%>
28
+ case <%= e[:case_name] %>(<%= e[:properties].map { |p| "#{p[:name]}: #{p[:type]}" }.join(", ") %>)
29
+ <%- end -%>
30
+ <%- end -%>
31
+
32
+ var data: EventData {
33
+ switch self {
34
+ <%- events.each_with_index do |e, index| -%>
35
+ <%- if e[:properties].count == 0 -%>
36
+ case .<%= e[:case_name] %>:
37
+ <%- else -%>
38
+ case let .<%= e[:case_name] %>(<%= e[:properties].map { |p| p[:name] }.join(", ") %>):
39
+ <%- end -%>
40
+ return EventData(name: .<%= e[:case_name] %>,
41
+ <%- if e[:properties].count == 0 -%>
42
+ properties: nil,
43
+ <%- else -%>
44
+ properties: [
45
+ <%- e[:properties].each do |p| -%>
46
+ "<%= p[:name] %>": <%= p[:value] %> as Any,
47
+ <%- end -%>
48
+ ],
49
+ <%- end -%>
50
+ <%- if e[:destinations].count == 0 -%>
51
+ destinations: [])
52
+ <%- else -%>
53
+ destinations: [
54
+ <%- e[:destinations].each do |d| -%>
55
+ .<%= d %>,
56
+ <%- end -%>
57
+ ])
58
+ <%- end -%>
59
+ <%- unless index == events.count - 1 -%>
60
+
61
+ <%- end -%>
62
+ <%- end -%>
63
+ }
64
+ }
65
+ }
@@ -0,0 +1,49 @@
1
+ struct PropertyData {
2
+ let name: String
3
+ let value: Any
4
+ let destinations: [Destination]
5
+
6
+ init(name: String, value: Any, destinations: [Destination]) {
7
+ self.name = name
8
+ self.value = value
9
+ self.destinations = destinations
10
+ }
11
+
12
+ init(name: PropertyName, value: Any, destinations: [Destination]) {
13
+ self.init(name: name.rawValue, value: value, destinations: destinations)
14
+ }
15
+ }
16
+
17
+ enum PropertyName: String {
18
+ <%- properties.each do |p| -%>
19
+ case <%= p[:case_name] %> = "<%= p[:property_name ] %>"
20
+ <%- end -%>
21
+ }
22
+
23
+ enum Property {
24
+ <%- properties.each do |p| -%>
25
+ case <%= p[:case_name] %>(<%= p[:type] %>)
26
+ <%- end -%>
27
+
28
+ var data: PropertyData {
29
+ switch self {
30
+ <%- properties.each_with_index do |p, index| -%>
31
+ case let .<%= p[:case_name] %>(value):
32
+ return PropertyData(name: .<%= p[:case_name] %>,
33
+ value: value<% if p[:is_special_property] %>.rawValue<% end %>,
34
+ <%- if p[:destinations].count == 0 -%>
35
+ destinations: [])
36
+ <%- else -%>
37
+ destinations: [
38
+ <%- p[:destinations].each do |d| -%>
39
+ .<%= d %>,
40
+ <%- end -%>
41
+ ])
42
+ <%- end -%>
43
+ <%- unless index == properties.count - 1 -%>
44
+
45
+ <%- end -%>
46
+ <%- end -%>
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,10 @@
1
+ <%- enums.each_with_index do |enum, index| -%>
2
+ enum <%= enum[:name] %>: String {
3
+ <%- enum[:values].each do |v| -%>
4
+ case <%= v[:case_name] %> = "<%= v[:value ] %>"
5
+ <%- end -%>
6
+ }
7
+ <%- unless index == enums.count - 1 -%>
8
+
9
+ <%- end -%>
10
+ <%- end -%>
data/lib/evva/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Evva
2
- VERSION = '0.1.4.3'.freeze
3
- VERSION_UPDATED_AT = '2018-10-12'.freeze
2
+ VERSION = '0.4.0'.freeze
3
+ VERSION_UPDATED_AT = '2021-12-21'.freeze
4
4
  end