peak_flow_utils 0.0.1 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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