evva 0.1.4.2 → 0.3.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
- SHA1:
3
- metadata.gz: 90dd43b0fdd3169aa137cf665a8c592693b9d686
4
- data.tar.gz: 12649831ed616d714b7357c3fdff9d1cd7cf41ea
2
+ SHA256:
3
+ metadata.gz: 32699d4abc90a02f944c069ac0cefc8e26fbf972d42342f86ad55652d198f0c2
4
+ data.tar.gz: d9e9c0e5a62a712636ebede3bf3b04a9f47c8bc36bac4f06ea4d27b48ff3703f
5
5
  SHA512:
6
- metadata.gz: 9d043c714969d7d188026015fe15d0ef3a6d0be113d05593c53624e4af1a63f755800bcfab407d35b4512fd00045791ea59085cc6cc918163faae540222dbd5c
7
- data.tar.gz: ec753ef63337efd78777711e1e2b62b46956a3c44ef699d50d2f9761ff54a9f82cec7124527cf774ca5c95fbae6a3a90785d2d9702bcf0396525dabfc692b2aa
6
+ metadata.gz: cd70916584265dc7077907d324049b93000f5805bf43bb9dda152547e36181740ba8524980606400a8bd128c556dbf09ad641d4c634d513e714b2748639a4498
7
+ data.tar.gz: a9a95c538e9d88011507e5a12e64afb84b91fbee6a5b70e0d48f431a05496a0384347c2f6edc97ad3a3164f80677ff05e0b700d4a2c7ea08bce69d7e59ab8145
data/.gitignore CHANGED
@@ -1,6 +1,5 @@
1
1
  *.sublime-*
2
- .ruby-version
3
2
  running
4
3
  coverage
5
4
  .DS_Store*
6
- .byebug_history
5
+ .byebug_history
data/.rspec CHANGED
@@ -1,5 +1,4 @@
1
1
  --color
2
2
  --format documentation
3
3
  --profile
4
- --drb
5
4
  --require spec_helper
data/.rubocop_todo.yml CHANGED
@@ -57,8 +57,8 @@ Layout/EmptyLinesAroundBlockBody:
57
57
  Layout/EmptyLinesAroundClassBody:
58
58
  Exclude:
59
59
  - 'lib/evva/android_generator.rb'
60
- - 'lib/evva/mixpanel_enum.rb'
61
- - 'lib/evva/mixpanel_event.rb'
60
+ - 'lib/evva/analytics_enum.rb'
61
+ - 'lib/evva/analytics_event.rb'
62
62
 
63
63
  # Offense count: 1
64
64
  # Cop supports --auto-correct.
@@ -163,8 +163,8 @@ Layout/TrailingBlankLines:
163
163
  - 'lib/evva/enum_generator.rb'
164
164
  - 'lib/evva/event_generator.rb'
165
165
  - 'lib/evva/google_sheet.rb'
166
- - 'lib/evva/mixpanel_enum.rb'
167
- - 'lib/evva/mixpanel_event.rb'
166
+ - 'lib/evva/analytics_enum.rb'
167
+ - 'lib/evva/analytics_event.rb'
168
168
  - 'spec/lib/evva/enum_generator_spec.rb'
169
169
  - 'spec/lib/evva/event_generator_spec.rb'
170
170
  - 'spec/lib/evva/google_sheet_spec.rb'
@@ -226,8 +226,8 @@ Lint/UselessAssignment:
226
226
  # Offense count: 2
227
227
  Lint/Void:
228
228
  Exclude:
229
- - 'lib/evva/mixpanel_enum.rb'
230
- - 'lib/evva/mixpanel_event.rb'
229
+ - 'lib/evva/analytics_enum.rb'
230
+ - 'lib/evva/analytics_event.rb'
231
231
 
232
232
  # Offense count: 8
233
233
  Metrics/AbcSize:
@@ -309,8 +309,8 @@ Style/Documentation:
309
309
  - 'lib/evva/event_generator.rb'
310
310
  - 'lib/evva/google_sheet.rb'
311
311
  - 'lib/evva/logger.rb'
312
- - 'lib/evva/mixpanel_enum.rb'
313
- - 'lib/evva/mixpanel_event.rb'
312
+ - 'lib/evva/analytics_enum.rb'
313
+ - 'lib/evva/analytics_event.rb'
314
314
 
315
315
  # Offense count: 1
316
316
  # Cop supports --auto-correct.
@@ -407,8 +407,8 @@ Style/RaiseArgs:
407
407
  # Cop supports --auto-correct.
408
408
  Style/RedundantSelf:
409
409
  Exclude:
410
- - 'lib/evva/mixpanel_enum.rb'
411
- - 'lib/evva/mixpanel_event.rb'
410
+ - 'lib/evva/analytics_enum.rb'
411
+ - 'lib/evva/analytics_event.rb'
412
412
  - 'lib/evva/object_extension.rb'
413
413
 
414
414
  # Offense count: 1
data/.travis.yml ADDED
@@ -0,0 +1 @@
1
+ language: ruby
data/Gemfile CHANGED
@@ -1,13 +1,14 @@
1
1
  source 'https://rubygems.org'
2
- ruby '2.3.3'
3
2
 
4
3
  gem 'colorize'
5
- gem 'rubocop'
6
4
  gem 'safe_yaml'
7
- gem 'xml-simple'
8
5
 
9
- gem 'rspec'
10
- gem 'rspec-its'
11
- gem 'simplecov', require: false, group: :test
12
- gem 'simplecov-rcov', require: false
13
- gem 'webmock', '~> 1.20'
6
+ group :test do
7
+ gem 'rake'
8
+ gem 'rspec'
9
+ gem 'rspec-its'
10
+ gem 'simplecov', require: false, group: :test
11
+ gem 'simplecov-rcov', require: false
12
+ gem 'webmock', '~> 1.20'
13
+ gem 'rubocop'
14
+ end
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
- addressable (2.5.2)
5
- public_suffix (>= 2.0.2, < 4.0)
4
+ addressable (2.8.0)
5
+ public_suffix (>= 2.0.2, < 5.0)
6
6
  ast (2.3.0)
7
7
  colorize (0.8.1)
8
8
  crack (0.4.3)
@@ -10,15 +10,15 @@ GEM
10
10
  diff-lcs (1.3)
11
11
  docile (1.1.5)
12
12
  hashdiff (0.3.7)
13
- json (2.1.0)
13
+ json (2.3.0)
14
14
  parallel (1.12.0)
15
15
  parser (2.4.0.0)
16
16
  ast (~> 2.2)
17
17
  powerpack (0.1.1)
18
- public_suffix (3.0.0)
18
+ public_suffix (4.0.6)
19
19
  rainbow (2.2.2)
20
20
  rake
21
- rake (12.1.0)
21
+ rake (12.3.3)
22
22
  rspec (3.7.0)
23
23
  rspec-core (~> 3.7.0)
24
24
  rspec-expectations (~> 3.7.0)
@@ -56,13 +56,13 @@ GEM
56
56
  addressable (>= 2.3.6)
57
57
  crack (>= 0.3.2)
58
58
  hashdiff
59
- xml-simple (1.1.5)
60
59
 
61
60
  PLATFORMS
62
61
  ruby
63
62
 
64
63
  DEPENDENCIES
65
64
  colorize
65
+ rake
66
66
  rspec
67
67
  rspec-its
68
68
  rubocop
@@ -70,10 +70,6 @@ DEPENDENCIES
70
70
  simplecov
71
71
  simplecov-rcov
72
72
  webmock (~> 1.20)
73
- xml-simple
74
-
75
- RUBY VERSION
76
- ruby 2.3.3p222
77
73
 
78
74
  BUNDLED WITH
79
- 1.15.4
75
+ 2.2.26
data/README.md CHANGED
@@ -1,4 +1,10 @@
1
1
  Evva
2
+ ========
3
+
4
+ [![Status](https://travis-ci.org/hole19/evva.svg?branch=master)](https://travis-ci.org/hole19/evva?branch=master)
5
+ [![Gem](https://img.shields.io/gem/v/evva.svg?style=flat)](http://rubygems.org/gems/evva "View this project in Rubygems")
6
+
7
+ Evva automatically generates code for triggering events based on a Google Sheets specification. It generated code for both iOS (Swift) and Android (Kotlin).
2
8
 
3
9
  # Instalation
4
10
 
@@ -19,9 +25,13 @@ Evva
19
25
  data_source:
20
26
  type: google_sheet
21
27
  sheet_id: <GOOGLE-DRIVE-SHEET-ID>
28
+ events_url: <GOOGLE-DRIVE-EVENTS-SHEET-URL>
29
+ people_properties_url: <GOOGLE-DRIVE-PEOPLE-PROPERTIES-SHEET-URL>
30
+ enum_classes_url: <GOOGLE-DRIVE-ENUM-CLASSES-SHEET-URL>
22
31
 
23
32
  out_path: /folder/where/analytics/classes/are
24
33
  event_file_name: /file/with/tracking/functions
25
34
  event_enum_file_name: /file/with/event/names
26
35
  people_file_name: /file/with/people/properties
36
+ special_enum_file_name: //file/with/special/enum/properties/
27
37
  ```
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "rake"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.pattern = Dir.glob("spec/**/*_spec.rb")
6
+ t.rspec_opts = "--format documentation"
7
+ end
8
+
9
+ task default: :spec
data/changelog.md CHANGED
@@ -1,4 +1,20 @@
1
1
  # Change Log
2
+
3
+ ## [0.3.0] - 2021-12-16
4
+ - Revamp Android generator to generate events as classes instead of methods.
5
+
6
+ ## [0.2.0] - 2021-08-30
7
+ - Google Spreadsheet option stopped working due to a change in the API. This version fixes that.
8
+
9
+ Note: You'll need a new setup. View README.
10
+
11
+ ## [0.1.4.4] - 2019-02-04
12
+ - Adds support for dynamic android package name
13
+
14
+ ## [0.1.4.3] - 2018-10-12
15
+ - Fixes swift and kotlin tabs, indentation and property names
16
+ - Merges all special enums in a single file
17
+
2
18
  ## [0.1.4.2] - 2018-02-14
3
19
  - Replaces Swift headers
4
20
 
@@ -19,5 +35,6 @@
19
35
  ## [0.1.1] - 2017-11-07
20
36
  - Fixes mismatch between file name and class name generated.
21
37
 
22
- ## [0.1.0] - 2017/10/26
23
- - Initial Release.
38
+ ## [0.1.0] - 2017-10-26
39
+ - Initial Release.
40
+
data/evva.gemspec CHANGED
@@ -18,7 +18,4 @@ Gem::Specification.new do |s|
18
18
 
19
19
  s.add_runtime_dependency 'safe_yaml', '~> 1.0'
20
20
  s.add_runtime_dependency 'colorize', '~> 0.7'
21
- s.add_runtime_dependency 'xml-simple', '~> 1.1'
22
-
23
- s.add_development_dependency 'webmock', '~> 1.20'
24
21
  end
data/evva_config.yml CHANGED
@@ -3,8 +3,12 @@ type: iOS
3
3
  data_source:
4
4
  type: google_sheet
5
5
  sheet_id: 1LaJd68os3g_GFlerogC64grNIlXb2iukMznOvdml7A4
6
+ events_url: https://path-to-csv
7
+ people_properties_url: https://path-to-csv
8
+ enum_classes_url: https://path-to-csv
6
9
 
7
10
  out_path: analytics
8
- event_file_name: MixpanelAnalytics
9
- event_enum_file_name: MixpanelEvent
10
- people_file_name: MixpanelProperties
11
+ event_file_name: AnalyticsEvent
12
+ event_enum_file_name: AnalyticsEvents
13
+ people_file_name: AnalyticsProperties
14
+ package_name: com.hole19golf.hole19.analytics
@@ -1,5 +1,5 @@
1
1
  module Evva
2
- class MixpanelEnum
2
+ class AnalyticsEnum
3
3
  attr_reader :enum_name, :values
4
4
  def initialize(enum_name, values)
5
5
  @enum_name = enum_name
@@ -1,5 +1,5 @@
1
1
  module Evva
2
- class MixpanelEvent
2
+ class AnalyticsEvent
3
3
  attr_reader :event_name, :properties
4
4
  def initialize(event_name, properties = {})
5
5
  @event_name = event_name
@@ -1,100 +1,112 @@
1
1
  module Evva
2
2
  class AndroidGenerator
3
- KOTLIN_EVENT_HEADER =
4
- "package com.hole19golf.hole19.analytics\n\n"\
5
- "import com.hole19golf.hole19.analytics.Event\n"\
6
- "import com.hole19golf.hole19.analytics.MixpanelAnalyticsMask\n"\
7
- "import org.json.JSONObject\n\n".freeze
8
-
9
- KOTLIN_PEOPLE_HEADER =
10
- "package com.hole19golf.hole19.analytics\n"\
11
- "import com.hole19golf.hole19.analytics.Event\n\n".freeze
12
-
13
- KOTLIN_BUNDLE_HEADER =
14
- "package com.hole19golf.hole19.analytics\n"\
15
- "import com.hole19golf.hole19.analytics.Event\n\n".freeze
16
-
17
- KOTIN_PEOPLE_FUNCTIONS =
18
- "\nopen fun updateProperties(property: MixpanelProperties, value: Any) {\n"\
19
- "\t\tmixpanelMask.updateProperties(property.key, value)"\
20
- "\t\n} \n"\
21
- "\nopen fun incrementCounter(property: MixpanelProperties) {\n"\
22
- "\t\tmixpanelMask.incrementCounter(property.key)"\
23
- "\t\n} \n".freeze
3
+ attr_accessor :package_name
4
+
5
+ def initialize(package_name)
6
+ @package_name = package_name
7
+ end
24
8
 
25
9
  NATIVE_TYPES = %w[Long Int String Double Float Boolean].freeze
26
10
 
27
11
  def events(bundle, file_name)
28
- event_file = KOTLIN_EVENT_HEADER + "open class #{file_name}(private val mixpanelMask: MixpanelAnalyticsMask) {\n".freeze
29
- bundle.each do |event|
30
- event_file += "\n#{kotlin_function(event)}"
12
+ header_footer_wrapper do
13
+ """sealed class #{file_name}(event: AnalyticsEvents) {
14
+ \tval name = event.key
15
+
16
+ \topen val properties: Map<String, Any?>? = null
17
+
18
+ #{bundle.map { |e| event_class(e, file_name) }.join("\n\n")}
19
+ }"""
31
20
  end
32
- event_file += KOTIN_PEOPLE_FUNCTIONS
33
- event_file += "\n}"
34
21
  end
35
22
 
36
23
  def people_properties(people_bundle, file_name)
37
- properties = KOTLIN_PEOPLE_HEADER + "enum class #{file_name}(val key: String) {\n"
38
- properties += people_bundle.map { |prop| "\t\t#{prop.upcase}(\"#{prop}\")" }.join(",\n")
39
- properties += ";\n}\n"
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}"
28
+ end
40
29
  end
41
30
 
42
31
  def event_enum(bundle, file_name)
43
- event_file = KOTLIN_BUNDLE_HEADER + "enum class #{file_name}(override val key: String) : Event {\n"
44
- event_file += bundle.map { |event| "\t\t#{event.event_name.upcase}(\"#{event.event_name}\")"}.join(", \n")
45
- event_file += "\n}\n"
32
+ 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}"
36
+ end
46
37
  end
47
38
 
48
- def kotlin_function(event_data)
49
- function_name = 'track' + titleize(event_data.event_name)
50
- function_arguments = event_data.properties.map { |name, type| "#{name}: #{type}" }.join(', ')
51
- if !function_arguments.empty?
52
- props = json_props(event_data.properties)
53
- function_body =
54
- "open fun #{function_name}(#{function_arguments}) {"\
55
- "#{props}"\
56
- "\tmixpanelMask.trackEvent(MixpanelEvent.#{event_data.event_name.upcase}, properties)\n"
57
- else
58
- function_body =
59
- "open fun #{function_name}() {\n"\
60
- "\tmixpanelMask.trackEvent(MixpanelEvent.#{event_data.event_name.upcase})\n"
39
+ def special_property_enums(enums)
40
+ 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")
61
46
  end
62
- function_body += "}\n"
63
47
  end
64
48
 
65
- def special_property_enum(enum)
66
- enum_body = "package com.hole19golf.hole19.analytics\n\n"
67
- enum_body += "enum class #{enum.enum_name}(val key: String) {\n"
68
- enum_body += enum.values.map { |vals| "\t#{vals.tr(' ', '_').upcase}(\"#{vals}\")"}.join(",\n")
69
- enum_body += "\n}\n"
49
+ private
50
+
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"
70
55
  end
71
56
 
72
- private
57
+ def header_footer_wrapper(imports = [])
58
+ <<-Kotlin
59
+ package #{@package_name}
60
+
61
+ #{imports_header(imports)}/**
62
+ * This file was automatically generated by evva: https://github.com/hole19/evva
63
+ */
64
+
65
+ #{yield.gsub("\t", " ")}
66
+ Kotlin
67
+ end
68
+
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)
73
74
 
74
- def json_props(properties)
75
+ """\tdata class #{class_name}(
76
+ \t\t#{class_arguments}
77
+ \t) : #{superclass_name}(AnalyticsEvents.#{event_data.event_name.upcase}) {
78
+ #{props}
79
+ \t}"""
80
+
81
+ else
82
+ """\tobject #{class_name} : #{superclass_name}(AnalyticsEvents.#{event_data.event_name.upcase})"""
83
+ end
84
+ end
85
+
86
+ def props_map(properties)
75
87
  split_properties =
76
88
  properties
77
- .map do |name, type|
89
+ .map.with_index do |data, index|
90
+ name, type = data
91
+ prop = "\t\t\t\"#{name}\" to #{camelize(name, false)}"
92
+
78
93
  if special_property?(type)
79
94
  if optional_property?(type)
80
- "#{name}?.let { put(\"#{name}\", it.key) }"
81
- else
82
- "put(\"#{name}\", #{name}.key)"
83
- end
84
- else
85
- if optional_property?(type)
86
- "#{name}?.let { put(\"#{name}\", it) }"
87
- else
88
- "put(\"#{name}\", #{name})"
95
+ prop = "#{prop}?"
89
96
  end
97
+ prop = "#{prop}.key"
98
+ end
99
+
100
+ if index < properties.size - 1
101
+ # add list comma to every property except the last one
102
+ prop = "#{prop},"
90
103
  end
104
+
105
+ prop
91
106
  end
92
- .map { |line| "\t\t#{line}" }
93
107
  .join("\n")
94
108
 
95
- resulting_json = "\n\tval properties = JSONObject().apply {\n" +
96
- +split_properties.to_s
97
- resulting_json += "\n\t}\n"
109
+ "\t\toverride val properties = mapOf(\n#{split_properties}\n\t\t)"
98
110
  end
99
111
 
100
112
  def special_property?(type)
@@ -105,8 +117,15 @@ module Evva
105
117
  type.include?('?')
106
118
  end
107
119
 
108
- def titleize(str)
109
- str.split('_').collect(&:capitalize).join
120
+ # extracted from Rails' ActiveSupport
121
+ def camelize(string, uppercase_first_letter = true)
122
+ string = string.to_s
123
+ if uppercase_first_letter
124
+ string = string.sub(/^[a-z\d]*/) { |match| match.capitalize }
125
+ else
126
+ string = string.sub(/^(?:(?=\b|[A-Z_])|\w)/) { |match| match.downcase }
127
+ end
128
+ string.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }.gsub("/", "::")
110
129
  end
111
130
  end
112
131
  end
data/lib/evva/config.rb CHANGED
@@ -39,6 +39,14 @@ module Evva
39
39
  @hash[:event_enum_file_name]
40
40
  end
41
41
 
42
+ def special_enum_file_name
43
+ @hash[:special_enum_file_name]
44
+ end
45
+
46
+ def package_name
47
+ @hash[:package_name]
48
+ end
49
+
42
50
  CONFIG_STRUCT = {
43
51
  type: Hash,
44
52
  elements: {
@@ -49,7 +57,8 @@ module Evva
49
57
  out_path: { type: String },
50
58
  event_file_name: { type: String },
51
59
  event_enum_file_name: { type: String },
52
- people_file_name: { type: String }
60
+ people_file_name: { type: String },
61
+ package_name: { type: String }
53
62
  }
54
63
  }.freeze
55
64
 
@@ -57,7 +66,9 @@ module Evva
57
66
  type: Hash,
58
67
  elements: {
59
68
  type: { type: String },
60
- sheet_id: { type: String }
69
+ events_url: { type: String },
70
+ people_properties_url: { type: String },
71
+ enum_classes_url: { type: String },
61
72
  }
62
73
  }.freeze
63
74
 
@@ -1,83 +1,86 @@
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
+ def initialize(events_url, people_properties_url, enum_classes_url)
7
+ @events_url = events_url
8
+ @people_properties_url = people_properties_url
9
+ @enum_classes_url = enum_classes_url
8
10
  end
9
11
 
10
12
  def events
11
- raw = raw_data(@sheet_id, 0)
12
- Logger.info('Downloading dictionary from Google Sheet...')
13
- non_language_columns = %w[id updated category
14
- title content link]
13
+ Logger.info("Downloading data from Google Sheet at #{@events_url}")
14
+ csv = get_csv(@events_url)
15
+
15
16
  event_list = []
16
- raw['entry'].each do |entry|
17
- filtered_entry = entry.reject { |c| non_language_columns.include?(c) }
18
- event_name = filtered_entry['eventname'].first
19
- properties = hash_parser(filtered_entry['props'].first)
20
- event_list.push(Evva::MixpanelEvent.new(event_name, properties))
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)
21
21
  end
22
22
  event_list
23
23
  end
24
24
 
25
25
  def people_properties
26
- raw = raw_data(@sheet_id, 1)
26
+ Logger.info("Downloading data from Google Sheet at #{@people_properties_url}")
27
+ csv = get_csv(@people_properties_url)
28
+
27
29
  people_list = []
28
- Logger.info('Downloading dictionary from Google Sheet...')
29
- non_language_columns = %w[id updated category title content link]
30
- raw['entry'].each do |entry|
31
- filtered_entry = entry.reject { |c| non_language_columns.include?(c) }
32
- value = filtered_entry['value'].first
30
+ csv.each do |row|
31
+ value = row['Property Name']
33
32
  people_list << value
34
33
  end
35
34
  people_list
36
35
  end
37
36
 
38
37
  def enum_classes
39
- raw = raw_data(@sheet_id, 2)
40
- Logger.info('Downloading dictionary from Google Sheet...')
41
- non_language_columns = %w[id updated category title content link]
38
+ Logger.info("Downloading data from Google Sheet at #{@enum_classes_url}")
39
+ csv = get_csv(@enum_classes_url)
40
+
42
41
  enum_list = []
43
- raw['entry'].each do |entry|
44
- filtered_entry = entry.reject { |c| non_language_columns.include?(c) }
45
- enum_name = filtered_entry['enum'].first
46
- values = filtered_entry['values'].first.split(',')
47
- enum_list.push(Evva::MixpanelEnum.new(enum_name, values))
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)
48
46
  end
49
47
  enum_list
50
48
  end
51
49
 
52
- def xml_data(uri, headers = nil)
53
- uri = URI.parse(uri)
54
- http = Net::HTTP.new(uri.host, uri.port)
55
- http.use_ssl = true
56
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
57
- data = http.get(uri.path, headers)
58
- unless data.code.to_i == 200
59
- raise 'Cannot access sheet at #{uri} - HTTP #{data.code}'
60
- end
50
+ private
51
+
52
+ def get_csv(url)
53
+ data = get(url)
61
54
 
62
55
  begin
63
- XmlSimple.xml_in(data.body, 'KeyAttr' => 'name')
64
- rescue
65
- raise 'Cannot parse. Expected XML at #{uri}'
56
+ CSV.parse(data, headers: true)
57
+ rescue StandardError => e
58
+ raise "Cannot parse. Expected CSV at #{url}: #{e}"
66
59
  end
67
60
  end
68
61
 
69
- def raw_data(sheet_id, sheet_number)
70
- Logger.info('Downloading Google Sheet...')
71
- sheet = xml_data("https://spreadsheets.google.com/feeds/worksheets/#{sheet_id}/public/full")
72
- url = sheet['entry'][sheet_number]['link'][0]['href']
73
- xml_data(url)
74
- end
62
+ def get(url, max_redirects = 1)
63
+ raise "Too may redirects" if max_redirects == -1
75
64
 
76
- private
65
+ uri = URI(url)
66
+
67
+ http = Net::HTTP.new(uri.host, uri.port)
68
+ http.use_ssl = true
69
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
70
+
71
+ request = Net::HTTP::Get.new(uri.request_uri)
72
+ response = http.request(request)
73
+
74
+ return get(response['location'], max_redirects - 1) if response.is_a? Net::HTTPRedirection
75
+
76
+ raise "Http Error #{response.body}" if response.code.to_i >= 400
77
+
78
+ response.body
79
+ end
77
80
 
78
81
  def hash_parser(property_array)
79
82
  h = {}
80
- unless property_array.empty?
83
+ unless property_array.nil? || property_array.empty?
81
84
  property_array.split(',').each do |prop|
82
85
  split_prop = prop.split(':')
83
86
  prop_name = split_prop[0].to_sym