peak_flow_utils 0.0.1 → 0.1.6

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 (65) hide show
  1. checksums.yaml +5 -5
  2. data/{LICENSE.txt → MIT-LICENSE} +1 -1
  3. data/README.md +22 -13
  4. data/Rakefile +20 -30
  5. data/app/assets/config/peak_flow_utils_manifest.js +2 -0
  6. data/app/assets/javascripts/peak_flow_utils/application.js +14 -0
  7. data/app/assets/stylesheets/peak_flow_utils/application.css +15 -0
  8. data/app/controllers/peak_flow_utils/application_controller.rb +13 -0
  9. data/app/controllers/peak_flow_utils/pings/sidekiq_pings_controller.rb +10 -0
  10. data/app/handlers/peak_flow_utils/application_handler.rb +36 -0
  11. data/app/handlers/peak_flow_utils/devise_handler.rb +126 -0
  12. data/app/handlers/peak_flow_utils/file_handler.rb +42 -0
  13. data/app/handlers/peak_flow_utils/model_handler.rb +123 -0
  14. data/app/handlers/peak_flow_utils/rails_handler.rb +206 -0
  15. data/app/handlers/peak_flow_utils/simple_form_handler.rb +76 -0
  16. data/app/handlers/peak_flow_utils/validations_handler.rb +85 -0
  17. data/app/handlers/peak_flow_utils/will_paginate_handler.rb +59 -0
  18. data/app/helpers/peak_flow_utils/application_helper.rb +2 -0
  19. data/app/jobs/peak_flow_utils/application_job.rb +2 -0
  20. data/app/mailers/peak_flow_utils/application_mailer.rb +4 -0
  21. data/app/migrations/20150902155200_create_translation_keys.rb +8 -0
  22. data/app/migrations/20150907070909_create_groups.rb +12 -0
  23. data/app/migrations/20150907090900_create_handlers.rb +9 -0
  24. data/app/migrations/20150908085500_create_translation_values.rb +13 -0
  25. data/app/migrations/20150908090800_create_handler_texts.rb +22 -0
  26. data/app/migrations/20160411190500_create_scanned_files.rb +10 -0
  27. data/app/migrations/peak_flow_utils/application_migration.rb +5 -0
  28. data/app/models/peak_flow_utils/application_record.rb +9 -0
  29. data/app/models/peak_flow_utils/group.rb +22 -0
  30. data/app/models/peak_flow_utils/handler.rb +14 -0
  31. data/app/models/peak_flow_utils/handler_text.rb +46 -0
  32. data/app/models/peak_flow_utils/scanned_file.rb +2 -0
  33. data/app/models/peak_flow_utils/translation_key.rb +8 -0
  34. data/app/models/peak_flow_utils/translation_value.rb +24 -0
  35. data/app/services/peak_flow_utils/application_service.rb +2 -0
  36. data/app/services/peak_flow_utils/attribute_service.rb +32 -0
  37. data/app/services/peak_flow_utils/configuration_service.rb +11 -0
  38. data/app/services/peak_flow_utils/database_initializer_service.rb +39 -0
  39. data/app/services/peak_flow_utils/erb_inspector.rb +71 -0
  40. data/app/services/peak_flow_utils/erb_inspector/file_inspector.rb +137 -0
  41. data/app/services/peak_flow_utils/erb_inspector/translation_inspector.rb +100 -0
  42. data/app/services/peak_flow_utils/group_service.rb +50 -0
  43. data/app/services/peak_flow_utils/handlers_finder_service.rb +25 -0
  44. data/app/services/peak_flow_utils/model_inspector.rb +133 -0
  45. data/app/services/peak_flow_utils/translation_service.rb +138 -0
  46. data/app/services/peak_flow_utils/translations_parser_service.rb +211 -0
  47. data/app/views/layouts/peak_flow_utils/application.html.erb +14 -0
  48. data/bin/peak_flow_rspec_files +4 -2
  49. data/config/routes.rb +2 -0
  50. data/lib/peak_flow_utils.rb +10 -2
  51. data/lib/peak_flow_utils/engine.rb +7 -0
  52. data/lib/peak_flow_utils/handler_helper.rb +39 -0
  53. data/lib/peak_flow_utils/rspec_helper.rb +162 -25
  54. data/lib/peak_flow_utils/version.rb +3 -0
  55. data/lib/tasks/peak_flow_utils_tasks.rake +6 -0
  56. metadata +121 -42
  57. data/.document +0 -5
  58. data/.rspec +0 -1
  59. data/.rubocop.yml +0 -83
  60. data/Gemfile +0 -20
  61. data/Gemfile.lock +0 -93
  62. data/VERSION +0 -1
  63. data/peak_flow_utils.gemspec +0 -65
  64. data/spec/peak_flow_utils_spec.rb +0 -7
  65. data/spec/spec_helper.rb +0 -12
@@ -0,0 +1,211 @@
1
+ class PeakFlowUtils::TranslationsParserService < PeakFlowUtils::ApplicationService
2
+ attr_reader :db
3
+
4
+ def execute
5
+ PeakFlowUtils::DatabaseInitializerService.execute!
6
+
7
+ cache_translations_in_dir(Rails.root.join("config/locales"))
8
+ cache_translations_in_handlers
9
+
10
+ clean_up_not_found
11
+
12
+ ServicePattern::Response.new(success: true)
13
+ end
14
+
15
+ def with_transactioner
16
+ require "active-record-transactioner"
17
+
18
+ ActiveRecordTransactioner.new do |transactioner|
19
+ @transactioner = transactioner
20
+ yield
21
+ end
22
+ end
23
+
24
+ def self.database_path
25
+ @database_path ||= Rails.root.join("db/peak_flow_utils.sqlite3").to_s
26
+ end
27
+
28
+ def database_path
29
+ @database_path ||= self.class.database_path
30
+ end
31
+
32
+ def update_handlers
33
+ @handlers_found ||= {}
34
+
35
+ PeakFlowUtils::HandlersFinderService.execute!.each do |handler|
36
+ debug "Updating handler: #{handler.name}"
37
+ handler_model = PeakFlowUtils::Handler.find_or_initialize_by(identifier: handler.id)
38
+ handler_model.update!(name: handler.name)
39
+
40
+ @handlers_found[handler_model.id] = true
41
+
42
+ yield handler_model if block_given?
43
+ end
44
+ end
45
+
46
+ def update_groups_for_handler(handler_model)
47
+ @groups_found ||= {}
48
+ handler = handler_model.at_handler
49
+
50
+ handler.groups.each do |group|
51
+ debug "Updating group: #{group.name}"
52
+ group_model = PeakFlowUtils::Group.find_or_initialize_by(handler_id: handler_model.id, identifier: group.id)
53
+ group_model.update!(name: group.name)
54
+
55
+ @groups_found[group_model.id] = true
56
+
57
+ group_model.at_group = group
58
+ yield group_model if block_given?
59
+ end
60
+ end
61
+
62
+ def update_translations_for_group(handler_model, group_model)
63
+ group = group_model.at_group
64
+ @translation_keys_found ||= {}
65
+ @handler_translations_found ||= {}
66
+
67
+ group.translations.each do |translation|
68
+ debug "Updating translation: #{translation.key}"
69
+
70
+ translation_key = PeakFlowUtils::TranslationKey.find_or_create_by!(key: translation.key)
71
+
72
+ raise "KEY ERROR: #{translation_key.inspect}" unless translation_key.id.to_i.positive?
73
+
74
+ @translation_keys_found[translation_key.id] = true
75
+
76
+ handler_translation = PeakFlowUtils::HandlerText.find_or_initialize_by(
77
+ translation_key_id: translation_key.id,
78
+ handler_id: handler_model.id,
79
+ group_id: group_model.id
80
+ )
81
+ handler_translation.assign_attributes(
82
+ default: translation.default,
83
+ file_path: translation.file_path,
84
+ line_no: translation.line_no,
85
+ key_show: translation.key_show,
86
+ full_path: translation.full_path,
87
+ dir: translation.dir
88
+ )
89
+
90
+ if @transactioner && handler_translation.persisted?
91
+ @transactioner.save!(handler_translation)
92
+ else
93
+ handler_translation.save!
94
+ end
95
+
96
+ @handler_translations_found[handler_translation.id] = true
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def debug(message)
103
+ puts message.to_s if @debug # rubocop:disable Rails/Output
104
+ end
105
+
106
+ def execute_migrations
107
+ require "baza_migrations"
108
+
109
+ executor = BazaMigrations::MigrationsExecutor.new(db: @db)
110
+ executor.add_dir "#{File.dirname(__FILE__)}/../../db/baza_translations_migrations"
111
+ executor.execute_migrations
112
+ end
113
+
114
+ def cache_translations_in_handlers
115
+ with_transactioner do
116
+ update_handlers do |handler_model|
117
+ update_groups_for_handler(handler_model) do |group_model|
118
+ update_translations_for_group(handler_model, group_model)
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ def cache_translations_in_dir(dir_path)
125
+ debug "Looking for translations in #{dir_path}"
126
+ @translation_values_found ||= {}
127
+
128
+ Dir.foreach(dir_path) do |file|
129
+ next if file == "." || file == ".."
130
+
131
+ full_path = "#{dir_path}/#{file}"
132
+
133
+ if File.directory?(full_path)
134
+ cache_translations_in_dir(full_path)
135
+ elsif File.extname(full_path) == ".yml"
136
+ cache_translations_in_file(full_path)
137
+ end
138
+ end
139
+ end
140
+
141
+ def cache_translations_in_file(file_path)
142
+ @translation_keys_found ||= {}
143
+
144
+ debug "Cache translations in #{file_path}"
145
+
146
+ i18n_hash = YAML.load_file(file_path)
147
+ debug "Hash: #{i18n_hash}"
148
+
149
+ i18n_hash.each do |locale, translations|
150
+ cache_translations_in_hash(file_path, locale, translations)
151
+ end
152
+
153
+ debug "Done caching translations in #{file_path}"
154
+ end
155
+
156
+ def cache_translations_in_hash(file_path, locale, i18n_hash, keys = [])
157
+ i18n_hash.each do |key, value|
158
+ current_key = keys.clone
159
+ current_key << key
160
+
161
+ if value.is_a?(Hash)
162
+ debug "Found new hash: #{current_key.join(".")}"
163
+ cache_translations_in_hash(file_path, locale, value, current_key)
164
+ else
165
+ debug "Found new key: #{current_key.join(".")} translated to #{value}"
166
+
167
+ key = current_key.join(".")
168
+
169
+ translation_key = PeakFlowUtils::TranslationKey.find_or_create_by!(key: key)
170
+ @translation_keys_found[translation_key.id] = true
171
+ raise "KEY ERROR: #{translation_key.inspect}" unless translation_key.id.to_i.positive?
172
+
173
+ translation_value = PeakFlowUtils::TranslationValue.find_or_initialize_by(
174
+ translation_key_id: translation_key.id,
175
+ locale: locale,
176
+ file_path: file_path
177
+ )
178
+ translation_value.assign_attributes(value: value)
179
+ translation_value.save!
180
+
181
+ @translation_values_found[translation_value.id] = true
182
+ end
183
+ end
184
+ end
185
+
186
+ def clean_up_not_found
187
+ debug "Cleaning up not found"
188
+
189
+ PeakFlowUtils::ApplicationRecord.transaction do
190
+ PeakFlowUtils::Handler
191
+ .where.not(id: @handlers_found.keys)
192
+ .destroy_all
193
+
194
+ PeakFlowUtils::HandlerText
195
+ .where.not(id: @handler_translations_found.keys)
196
+ .destroy_all
197
+
198
+ PeakFlowUtils::Group
199
+ .where.not(id: @groups_found.keys)
200
+ .destroy_all
201
+
202
+ PeakFlowUtils::TranslationKey
203
+ .where.not(id: @translation_keys_found.keys)
204
+ .destroy_all
205
+
206
+ PeakFlowUtils::TranslationValue
207
+ .where.not(id: @translation_values_found.keys)
208
+ .destroy_all
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Peak flow utils</title>
5
+ <%= stylesheet_link_tag "peak_flow_utils/application", media: "all" %>
6
+ <%= javascript_include_tag "peak_flow_utils/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -13,7 +13,9 @@ end
13
13
 
14
14
  rspec_helper = PeakFlowUtils::RspecHelper.new(
15
15
  groups: args.fetch("groups").to_i,
16
- group_number: args.fetch("group-number").to_i
16
+ group_number: args.fetch("group-number").to_i,
17
+ only_types: args["only-types"]&.split(","),
18
+ tags: args["tags"]&.split(",")
17
19
  )
18
20
 
19
- print rspec_helper.group_files.join(" ")
21
+ print rspec_helper.group_files.map { |group_file| group_file.fetch(:path) }.join(" ")
@@ -0,0 +1,2 @@
1
+ PeakFlowUtils::Engine.routes.draw do
2
+ end
@@ -1,3 +1,11 @@
1
- class PeakFlowUtils
2
- autoload :RspecHelper, "#{File.dirname(__FILE__)}/peak_flow_utils/rspec_helper"
1
+ require_relative "peak_flow_utils/engine"
2
+
3
+ require "array_enumerator"
4
+ require "service_pattern"
5
+
6
+ module PeakFlowUtils
7
+ path = "#{File.dirname(__FILE__)}/peak_flow_utils"
8
+
9
+ autoload :RspecHelper, "#{path}/rspec_helper"
10
+ autoload :HandlerHelper, "#{path}/handler_helper"
3
11
  end
@@ -0,0 +1,7 @@
1
+ require "rails"
2
+
3
+ module PeakFlowUtils; end
4
+
5
+ class PeakFlowUtils::Engine < ::Rails::Engine
6
+ isolate_namespace PeakFlowUtils
7
+ end
@@ -0,0 +1,39 @@
1
+ class PeakFlowUtils::HandlerHelper
2
+ delegate :translations, to: :instance
3
+
4
+ def self.find(id)
5
+ PeakFlowUtils::HandlersFinderService.execute!.each do |handler|
6
+ return handler if handler.id == id.to_s
7
+ end
8
+
9
+ raise ActiveRecord::RecordNotFound, "Handlers not found: '#{id}'."
10
+ end
11
+
12
+ def initialize(data)
13
+ @data = data
14
+ end
15
+
16
+ def id
17
+ @data.fetch(:id)
18
+ end
19
+
20
+ def to_param
21
+ id
22
+ end
23
+
24
+ def name
25
+ @data.fetch(:name)
26
+ end
27
+
28
+ def const
29
+ PeakFlowUtils.const_get(@data.fetch(:const_name))
30
+ end
31
+
32
+ def instance
33
+ const.new
34
+ end
35
+
36
+ def groups
37
+ const.new.groups
38
+ end
39
+ end
@@ -1,54 +1,191 @@
1
1
  class PeakFlowUtils::RspecHelper
2
- def initialize(args)
3
- @groups = args.fetch(:groups)
4
- @group_number = args.fetch(:group_number)
2
+ attr_reader :only_types, :tags
3
+
4
+ def initialize(groups:, group_number:, only_types: nil, tags: nil)
5
+ @groups = groups
6
+ @group_number = group_number
7
+ @example_data_exists = File.exist?("spec/examples.txt")
8
+ @only_types = only_types
9
+ @tags = tags
10
+ end
11
+
12
+ def example_data_exists?
13
+ @example_data_exists
14
+ end
15
+
16
+ def example_data
17
+ @example_data ||= begin
18
+ raw_data = File.read("spec/examples.txt")
19
+
20
+ result = []
21
+ raw_data.scan(/^\.\/(.+)\[(.+?)\]\s+\|\s+(.+?)\s+\|\s+((.+?) seconds|)\s+\|$/) do |match|
22
+ file_path = match[0]
23
+ spec_result = match[1]
24
+ seconds = match[4]&.to_f
25
+
26
+ spec_data = {
27
+ file_path: file_path,
28
+ spec_result: spec_result,
29
+ seconds: seconds
30
+ }
31
+
32
+ result << spec_data
33
+ end
34
+
35
+ result
36
+ end
37
+ end
38
+
39
+ def example_files
40
+ @example_files ||= begin
41
+ files = {}
42
+ example_data.each do |spec_data|
43
+ file_path = spec_data.fetch(:file_path)
44
+ seconds = spec_data.fetch(:seconds)
45
+
46
+ files[file_path] ||= {examples: 0, seconds: 0.0}
47
+ files[file_path][:examples] += 1
48
+ files[file_path][:seconds] += seconds if seconds
49
+ end
50
+
51
+ files
52
+ end
53
+ end
54
+
55
+ def example_file(path)
56
+ example_files[path]
5
57
  end
6
58
 
7
59
  def group_files
8
60
  return @group_files if @group_files
9
61
 
10
62
  # Sort them so that they are sorted by file path in three groups so each group have an equal amount of controller specs, features specs and so on
11
- group_orders = []
12
- @groups.times do
13
- group_orders << []
63
+
64
+ sorted_files.each do |file|
65
+ file_path = file.fetch(:path)
66
+ file_data = example_file(file_path) if example_data_exists?
67
+
68
+ if file_data
69
+ examples = file_data.fetch(:examples)
70
+ seconds = file_data.fetch(:seconds)
71
+ else
72
+ examples = file.fetch(:examples)
73
+ end
74
+
75
+ group = group_with_least
76
+ group[:examples] += examples
77
+ group[:files] << file
78
+ group[:seconds] += seconds if seconds
14
79
  end
15
80
 
16
- group_index = 0
17
- files.sort.each do |file|
18
- group_orders[group_index] << file
19
- group_index += 1
20
- group_index = 0 if group_index >= group_orders.length
81
+ @group_files = group_orders[@group_number - 1].fetch(:files)
82
+ end
83
+
84
+ def group_orders
85
+ @group_orders ||= begin
86
+ group_orders = []
87
+ @groups.times do
88
+ group_orders << {
89
+ examples: 0,
90
+ files: [],
91
+ seconds: 0.0
92
+ }
93
+ end
94
+ group_orders
21
95
  end
96
+ end
22
97
 
23
- @group_files = group_orders[@group_number - 1]
98
+ def group_with_least
99
+ group_orders.min do |group1, group2|
100
+ if example_data_exists? && group1.fetch(:seconds) != 0.0 && group2.fetch(:seconds) != 0.0
101
+ group1.fetch(:seconds) <=> group2.fetch(:seconds)
102
+ else
103
+ group1.fetch(:examples) <=> group2.fetch(:examples)
104
+ end
105
+ end
24
106
  end
25
107
 
26
- def total_tests
27
- files unless @total_tests
28
- @total_tests
108
+ def sorted_files
109
+ files.values.sort do |file1, file2|
110
+ file1_path = file1.fetch(:path)
111
+ file2_path = file2.fetch(:path)
112
+
113
+ file1_data = example_file(file1_path) if example_data_exists?
114
+ file2_data = example_file(file2_path) if example_data_exists?
115
+
116
+ if file1_data && file2_data && file1_data.fetch(:seconds) != 0.0 && file2_data.fetch(:seconds) != 0.0
117
+ value1 = file1_data[:seconds]
118
+ else
119
+ value1 = file1.fetch(:points)
120
+ end
121
+
122
+ if file2_data && file2_data && file2_data.fetch(:seconds) != 0.0 && file2_data.fetch(:seconds) != 0.0
123
+ value2 = file2_data[:seconds]
124
+ else
125
+ value2 = file2.fetch(:points)
126
+ end
127
+
128
+ value2 <=> value1
129
+ end
29
130
  end
30
131
 
31
132
  private
32
133
 
134
+ def dry_result_command
135
+ command = "bundle exec rspec --dry-run --format json"
136
+
137
+ tags&.each do |tag|
138
+ command << " --tag #{tag}"
139
+ end
140
+
141
+ command
142
+ end
143
+
33
144
  def dry_result
34
145
  require "json"
35
- @dry_result ||= ::JSON.parse(`bundle exec rspec --dry-run --format json`)
146
+ @dry_result ||= ::JSON.parse(`#{dry_result_command}`)
147
+ end
148
+
149
+ def dry_file(path)
150
+ files.fetch(path)
36
151
  end
37
152
 
38
153
  def files
39
- return @files if @files
154
+ @files ||= begin
155
+ result = {}
156
+ dry_result.fetch("examples").each do |example|
157
+ file_path = example.fetch("file_path")
158
+ file_path = file_path[2, file_path.length]
159
+ type = type_from_path(file_path)
160
+ points = points_from_type(type)
40
161
 
41
- @total_tests = 0
162
+ next if ignore_type?(type)
42
163
 
43
- @files = []
44
- dry_result.fetch("examples").each do |example|
45
- file_path = example.fetch("file_path")
46
- file_path = file_path[2, file_path.length]
164
+ result[file_path] = {examples: 0, path: file_path, points: 0, type: type} unless result.key?(file_path)
165
+ result[file_path][:examples] += 1
166
+ result[file_path][:points] += points
167
+ end
47
168
 
48
- @files << file_path unless @files.include?(file_path)
49
- @total_tests += 1
169
+ result
50
170
  end
171
+ end
51
172
 
52
- @files
173
+ def ignore_type?(type)
174
+ only_types && !only_types.include?(type)
175
+ end
176
+
177
+ def type_from_path(file_path)
178
+ match = file_path.match(/^spec\/(.+?)\//)
179
+ match[1] if match
180
+ end
181
+
182
+ def points_from_type(type)
183
+ if type == "feature" || type == "system"
184
+ 10
185
+ elsif type == "controllers"
186
+ 3
187
+ else
188
+ 1
189
+ end
53
190
  end
54
191
  end