evva 0.3.0 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32699d4abc90a02f944c069ac0cefc8e26fbf972d42342f86ad55652d198f0c2
4
- data.tar.gz: d9e9c0e5a62a712636ebede3bf3b04a9f47c8bc36bac4f06ea4d27b48ff3703f
3
+ metadata.gz: f74dbff0766dc7623ca1ac518e7636172440511a4470398d594fefef8364fba9
4
+ data.tar.gz: 4793e14af612e48d0e7cf85aa313d5c6c4f92c5eb440be7a853503f39fd093e6
5
5
  SHA512:
6
- metadata.gz: cd70916584265dc7077907d324049b93000f5805bf43bb9dda152547e36181740ba8524980606400a8bd128c556dbf09ad641d4c634d513e714b2748639a4498
7
- data.tar.gz: a9a95c538e9d88011507e5a12e64afb84b91fbee6a5b70e0d48f431a05496a0384347c2f6edc97ad3a3164f80677ff05e0b700d4a2c7ea08bce69d7e59ab8145
6
+ metadata.gz: ebbee6abfa8abd7e6717f20246a1271a7d7b35e4b9a42414293ff436cff842e82ac45beb7638dc642cdb00c1408f7c81cb4b8dcfdd7d4ee6dafa04f121388b5a
7
+ data.tar.gz: 18c42c24f8f2b7d923c9a99b5ec58a43d258340b2523fdb4bf8f136bb0d4d9a075f3497b4c0c8a8176c4e01b07db56f116066b1139389104497db86e6ed9e30b
data/README.md CHANGED
@@ -24,7 +24,6 @@ Evva automatically generates code for triggering events based on a Google Sheets
24
24
 
25
25
  data_source:
26
26
  type: google_sheet
27
- sheet_id: <GOOGLE-DRIVE-SHEET-ID>
28
27
  events_url: <GOOGLE-DRIVE-EVENTS-SHEET-URL>
29
28
  people_properties_url: <GOOGLE-DRIVE-PEOPLE-PROPERTIES-SHEET-URL>
30
29
  enum_classes_url: <GOOGLE-DRIVE-ENUM-CLASSES-SHEET-URL>
@@ -33,5 +32,7 @@ Evva automatically generates code for triggering events based on a Google Sheets
33
32
  event_file_name: /file/with/tracking/functions
34
33
  event_enum_file_name: /file/with/event/names
35
34
  people_file_name: /file/with/people/properties
36
- special_enum_file_name: //file/with/special/enum/properties/
35
+ people_file_name: /file/with/people/property/names
36
+ destinations_file_name: /file/with/destinations
37
+ special_enum_file_name: /file/with/special/enum/properties/
37
38
  ```
data/changelog.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Change Log
2
2
 
3
+ ## [0.4.0] - 2021-12-21
4
+ - Adds type to people properties
5
+ - Adds a list of destinations to events and people properties
6
+
3
7
  ## [0.3.0] - 2021-12-16
4
8
  - Revamp Android generator to generate events as classes instead of methods.
5
9
 
@@ -1,6 +1,7 @@
1
1
  module Evva
2
2
  class AnalyticsEnum
3
3
  attr_reader :enum_name, :values
4
+
4
5
  def initialize(enum_name, values)
5
6
  @enum_name = enum_name
6
7
  @values = values
@@ -1,13 +1,17 @@
1
1
  module Evva
2
2
  class AnalyticsEvent
3
- attr_reader :event_name, :properties
4
- def initialize(event_name, properties = {})
3
+ attr_reader :event_name, :properties, :destinations
4
+
5
+ def initialize(event_name, properties, destinations)
5
6
  @event_name = event_name
6
7
  @properties = properties
8
+ @destinations = destinations
7
9
  end
8
10
 
9
11
  def ==(other)
10
- event_name == other.event_name
12
+ event_name == other.event_name &&
13
+ properties == other.properties &&
14
+ destinations == other.destinations
11
15
  end
12
16
  end
13
17
  end
@@ -0,0 +1,17 @@
1
+ module Evva
2
+ class AnalyticsProperty
3
+ attr_reader :property_name, :type, :destinations
4
+
5
+ def initialize(property_name, type, destinations)
6
+ @property_name = property_name
7
+ @type = type
8
+ @destinations = destinations
9
+ end
10
+
11
+ def ==(other)
12
+ property_name == other.property_name &&
13
+ type == other.type &&
14
+ destinations == other.destinations
15
+ end
16
+ end
17
+ end
@@ -6,115 +6,158 @@ module Evva
6
6
  @package_name = package_name
7
7
  end
8
8
 
9
- NATIVE_TYPES = %w[Long Int String Double Float Boolean].freeze
9
+ BASE_TEMPLATE = File.expand_path("./templates/kotlin/base.kt", __dir__)
10
+ EVENTS_TEMPLATE = File.expand_path("./templates/kotlin/events.kt", __dir__)
11
+ EVENT_ENUM_TEMPLATE = File.expand_path("./templates/kotlin/event_enum.kt", __dir__)
12
+ PEOPLE_PROPERTIES_TEMPLATE = File.expand_path("./templates/kotlin/people_properties.kt", __dir__)
13
+ PEOPLE_PROPERTIES_ENUM_TEMPLATE = File.expand_path("./templates/kotlin/people_properties_enum.kt", __dir__)
14
+ SPECIAL_PROPERTY_ENUMS_TEMPLATE = File.expand_path("./templates/kotlin/special_property_enums.kt", __dir__)
15
+ DESTINATIONS_TEMPLATE = File.expand_path("./templates/kotlin/destinations.kt", __dir__)
10
16
 
11
- def events(bundle, file_name)
17
+ TAB_SIZE = " " # \t -> 4 spaces
18
+
19
+ NATIVE_TYPES = %w[Long Int String Double Float Boolean Date].freeze
20
+
21
+ def events(bundle, file_name, enums_file_name, destinations_file_name)
12
22
  header_footer_wrapper do
13
- """sealed class #{file_name}(event: AnalyticsEvents) {
14
- \tval name = event.key
23
+ class_name = file_name
24
+ enums_class_name = enums_file_name
25
+ destinations_class_name = destinations_file_name
26
+
27
+ events = bundle.map do |event|
28
+ properties = event.properties.map do |name, type|
29
+ param_name = camelize(name.to_s, false)
30
+ value_fetcher = param_name
31
+
32
+ if is_special_property?(type)
33
+ if type.end_with?('?')
34
+ # optional value, we need ? to access a parameter
35
+ value_fetcher += "?"
36
+ end
37
+ value_fetcher += ".key"
38
+ end
15
39
 
16
- \topen val properties: Map<String, Any?>? = null
40
+ {
41
+ param_name: param_name,
42
+ value_fetcher: value_fetcher,
43
+ type: type,
44
+ name: name.to_s,
45
+ }
46
+ end
17
47
 
18
- #{bundle.map { |e| event_class(e, file_name) }.join("\n\n")}
19
- }"""
20
- end
21
- end
48
+ destinations = event.destinations.map { |p| constantize(p) }
22
49
 
23
- def people_properties(people_bundle, file_name)
24
- header_footer_wrapper do
25
- body = "enum class #{file_name}(val key: String) {\n"
26
- body << people_bundle.map { |prop| "\t#{prop.upcase}(\"#{prop}\")" }.join(",\n")
27
- body << ";\n}"
50
+ {
51
+ class_name: camelize(event.event_name),
52
+ event_name: constantize(event.event_name),
53
+ properties: properties,
54
+ destinations: destinations,
55
+ is_object: properties.count == 0 && destinations.count == 0,
56
+ }
57
+ end
58
+
59
+ template_from(EVENTS_TEMPLATE).result(binding)
28
60
  end
29
61
  end
30
62
 
31
63
  def event_enum(bundle, file_name)
32
64
  header_footer_wrapper do
33
- body = "enum class #{file_name}(val key: String) {\n"
34
- body << bundle.map(&:event_name).map { |prop| "\t#{prop.upcase}(\"#{prop}\")" }.join(",\n")
35
- body << ";\n}"
65
+ class_name = file_name
66
+
67
+ events = bundle.map(&:event_name).map do |event_name|
68
+ {
69
+ name: constantize(event_name),
70
+ value: event_name,
71
+ }
72
+ end
73
+
74
+ template_from(EVENT_ENUM_TEMPLATE).result(binding)
36
75
  end
37
76
  end
38
77
 
39
- def special_property_enums(enums)
78
+ def people_properties(people_bundle, file_name, enums_file_name, destinations_file_name)
40
79
  header_footer_wrapper do
41
- enums.map do |enum|
42
- body = "enum class #{enum.enum_name}(val key: String) {\n"
43
- body << enum.values.map { |vals| "\t#{vals.tr(' ', '_').upcase}(\"#{vals}\")"}.join(",\n")
44
- body << ";\n}"
45
- end.join("\n\n")
80
+ class_name = file_name
81
+ enums_class_name = enums_file_name
82
+ destinations_class_name = destinations_file_name
83
+
84
+ properties = people_bundle.map do |property|
85
+ {
86
+ class_name: camelize(property.property_name),
87
+ property_name: constantize(property.property_name),
88
+ type: property.type,
89
+ is_special_property: is_special_property?(property.type),
90
+ destinations: property.destinations.map { |p| constantize(p) },
91
+ }
92
+ end
93
+
94
+ template_from(PEOPLE_PROPERTIES_TEMPLATE).result(binding)
46
95
  end
47
96
  end
48
97
 
49
- private
98
+ def people_properties_enum(people_bundle, file_name)
99
+ header_footer_wrapper do
100
+ class_name = file_name
101
+
102
+ properties = people_bundle.map(&:property_name).map do |property_name|
103
+ {
104
+ name: constantize(property_name),
105
+ value: property_name,
106
+ }
107
+ end
50
108
 
51
- def imports_header(imports = [])
52
- return unless imports.length > 0
53
- imports.map { |ev| ev. gsub("packagename", @package_name) }
54
- .join("\n") + "\n\n"
109
+ template_from(PEOPLE_PROPERTIES_ENUM_TEMPLATE).result(binding)
110
+ end
55
111
  end
56
112
 
57
- def header_footer_wrapper(imports = [])
58
- <<-Kotlin
59
- package #{@package_name}
113
+ def special_property_enums(enums_bundle)
114
+ header_footer_wrapper do
115
+ enums = enums_bundle.map do |enum|
116
+ values = enum.values.map do |value|
117
+ {
118
+ name: constantize(value),
119
+ value: value,
120
+ }
121
+ end
60
122
 
61
- #{imports_header(imports)}/**
62
- * This file was automatically generated by evva: https://github.com/hole19/evva
63
- */
123
+ {
124
+ class_name: enum.enum_name,
125
+ values: values,
126
+ }
127
+ end
64
128
 
65
- #{yield.gsub("\t", " ")}
66
- Kotlin
129
+ template_from(SPECIAL_PROPERTY_ENUMS_TEMPLATE).result(binding)
130
+ end
67
131
  end
68
132
 
69
- def event_class(event_data, superclass_name)
70
- class_name = camelize(event_data.event_name)
71
- class_arguments = event_data.properties.map { |name, type| "val #{camelize(name, false)}: #{type}" }.join(', ')
72
- if !class_arguments.empty?
73
- props = props_map(event_data.properties)
133
+ def destinations(bundle, file_name)
134
+ header_footer_wrapper do
135
+ class_name = file_name
74
136
 
75
- """\tdata class #{class_name}(
76
- \t\t#{class_arguments}
77
- \t) : #{superclass_name}(AnalyticsEvents.#{event_data.event_name.upcase}) {
78
- #{props}
79
- \t}"""
137
+ destinations = bundle.map { |d| constantize(d) }
80
138
 
81
- else
82
- """\tobject #{class_name} : #{superclass_name}(AnalyticsEvents.#{event_data.event_name.upcase})"""
139
+ template_from(DESTINATIONS_TEMPLATE).result(binding)
83
140
  end
84
141
  end
85
142
 
86
- def props_map(properties)
87
- split_properties =
88
- properties
89
- .map.with_index do |data, index|
90
- name, type = data
91
- prop = "\t\t\t\"#{name}\" to #{camelize(name, false)}"
143
+ private
92
144
 
93
- if special_property?(type)
94
- if optional_property?(type)
95
- prop = "#{prop}?"
96
- end
97
- prop = "#{prop}.key"
98
- end
145
+ def header_footer_wrapper
146
+ package_name = @package_name
99
147
 
100
- if index < properties.size - 1
101
- # add list comma to every property except the last one
102
- prop = "#{prop},"
103
- end
148
+ content = yield
149
+ .chop # trim trailing newlines created by sublime
104
150
 
105
- prop
106
- end
107
- .join("\n")
108
-
109
- "\t\toverride val properties = mapOf(\n#{split_properties}\n\t\t)"
151
+ template_from(BASE_TEMPLATE).result(binding).gsub("\t", TAB_SIZE)
110
152
  end
111
153
 
112
- def special_property?(type)
113
- !NATIVE_TYPES.include?(type.chomp('?'))
114
- end
154
+ def template_from(path)
155
+ file = File.read(path)
115
156
 
116
- def optional_property?(type)
117
- type.include?('?')
157
+ # - 2nd argument (nil) changes nothing
158
+ # - 3rd argument activates trim mode using "-" so that you can decide to
159
+ # not include a line (useful on loops and if statements)
160
+ ERB.new(file, nil, '-')
118
161
  end
119
162
 
120
163
  # extracted from Rails' ActiveSupport
@@ -127,5 +170,13 @@ Kotlin
127
170
  end
128
171
  string.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }.gsub("/", "::")
129
172
  end
173
+
174
+ def constantize(string)
175
+ string.tr(' ', '_').upcase
176
+ end
177
+
178
+ def is_special_property?(type)
179
+ !NATIVE_TYPES.include?(type.chomp('?'))
180
+ end
130
181
  end
131
182
  end
data/lib/evva/config.rb CHANGED
@@ -31,18 +31,26 @@ module Evva
31
31
  @hash[:event_file_name]
32
32
  end
33
33
 
34
+ def event_enum_file_name
35
+ @hash[:event_enum_file_name]
36
+ end
37
+
34
38
  def people_file_name
35
39
  @hash[:people_file_name]
36
40
  end
37
41
 
38
- def event_enum_file_name
39
- @hash[:event_enum_file_name]
42
+ def people_enum_file_name
43
+ @hash[:people_enum_file_name]
40
44
  end
41
45
 
42
46
  def special_enum_file_name
43
47
  @hash[:special_enum_file_name]
44
48
  end
45
49
 
50
+ def destinations_file_name
51
+ @hash[:destinations_file_name]
52
+ end
53
+
46
54
  def package_name
47
55
  @hash[:package_name]
48
56
  end
@@ -58,6 +66,8 @@ module Evva
58
66
  event_file_name: { type: String },
59
67
  event_enum_file_name: { type: String },
60
68
  people_file_name: { type: String },
69
+ people_enum_file_name: { type: String },
70
+ destinations_file_name: { type: String },
61
71
  package_name: { type: String }
62
72
  }
63
73
  }.freeze
@@ -3,6 +3,17 @@ require 'csv'
3
3
 
4
4
  module Evva
5
5
  class GoogleSheet
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
+
6
17
  def initialize(events_url, people_properties_url, enum_classes_url)
7
18
  @events_url = events_url
8
19
  @people_properties_url = people_properties_url
@@ -10,41 +21,48 @@ module Evva
10
21
  end
11
22
 
12
23
  def events
13
- Logger.info("Downloading data from Google Sheet at #{@events_url}")
14
- csv = get_csv(@events_url)
15
-
16
- event_list = []
17
- csv.each do |row|
18
- event_name = row['Event Name']
19
- properties = hash_parser(row['Event Properties'])
20
- event_list << Evva::AnalyticsEvent.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 || [])
21
34
  end
22
- event_list
23
35
  end
24
36
 
25
37
  def people_properties
26
- Logger.info("Downloading data from Google Sheet at #{@people_properties_url}")
27
- csv = get_csv(@people_properties_url)
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
28
42
 
29
- people_list = []
30
- csv.each do |row|
31
- value = row['Property Name']
32
- people_list << value
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 || [])
33
48
  end
34
- people_list
35
49
  end
36
50
 
37
51
  def enum_classes
38
- Logger.info("Downloading data from Google Sheet at #{@enum_classes_url}")
39
- csv = get_csv(@enum_classes_url)
40
-
41
- enum_list = []
42
- csv.each do |row|
43
- enum_name = row['Enum Name']
44
- values = row['Possible Values'].split(',')
45
- enum_list << Evva::AnalyticsEnum.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)
46
61
  end
47
- enum_list
62
+ end
63
+
64
+ def destinations
65
+ @destinations ||= events.map(&:destinations).flatten.uniq
48
66
  end
49
67
 
50
68
  private