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,12 @@
1
+ class CreateGroups < PeakFlowUtils::ApplicationMigration
2
+ def change
3
+ create_table :peak_flow_utils_groups do |t|
4
+ t.references :handler, null: false
5
+ t.string :identifier, index: true
6
+ t.string :name
7
+ t.timestamps
8
+ end
9
+
10
+ add_foreign_key :peak_flow_utils_groups, :peak_flow_utils_handlers, column: "handler_id"
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ class CreateHandlers < PeakFlowUtils::ApplicationMigration
2
+ def change
3
+ create_table :peak_flow_utils_handlers do |t|
4
+ t.string :identifier, index: true, null: false
5
+ t.string :name, null: false
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ class CreateTranslationValues < PeakFlowUtils::ApplicationMigration
2
+ def change
3
+ create_table :peak_flow_utils_translation_values do |t|
4
+ t.references :translation_key, null: false
5
+ t.string :file_path
6
+ t.string :locale, index: true
7
+ t.string :value
8
+ t.timestamps
9
+ end
10
+
11
+ add_foreign_key :peak_flow_utils_translation_values, :peak_flow_utils_translation_keys, column: "translation_key_id"
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ class CreateHandlerTexts < PeakFlowUtils::ApplicationMigration
2
+ def change
3
+ create_table :peak_flow_utils_handler_texts do |t|
4
+ t.belongs_to :handler, null: false
5
+ t.belongs_to :translation_key, index: false, null: false
6
+ t.belongs_to :group, null: false
7
+ t.string :key_show
8
+ t.string :file_path
9
+ t.integer :line_no
10
+ t.string :full_path, index: true
11
+ t.string :dir
12
+ t.string :default
13
+ t.timestamps
14
+ end
15
+
16
+ add_index :peak_flow_utils_handler_texts, :handler_id, name: "index_handler_translations_handler_id"
17
+
18
+ add_foreign_key :peak_flow_utils_handler_texts, :peak_flow_utils_handlers, column: "handler_id"
19
+ add_foreign_key :peak_flow_utils_handler_texts, :peak_flow_utils_translation_keys, column: "translation_key_id"
20
+ add_foreign_key :peak_flow_utils_handler_texts, :peak_flow_utils_groups, column: "group_id"
21
+ end
22
+ end
@@ -0,0 +1,10 @@
1
+ class CreateScannedFiles < PeakFlowUtils::ApplicationMigration
2
+ def change
3
+ create_table :peak_flow_utils_scanned_files do |t|
4
+ t.string :file_path, index: true, null: false
5
+ t.integer :file_size, null: false
6
+ t.datetime :last_changed_at, null: false
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ class PeakFlowUtils::ApplicationMigration < ActiveRecord::Migration[5.1]
2
+ def connection
3
+ PeakFlowUtils::ApplicationRecord.connection
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ class PeakFlowUtils::ApplicationRecord < ActiveRecord::Base
2
+ self.abstract_class = true
3
+ self.table_name_prefix = "peak_flow_utils_"
4
+
5
+ establish_connection(
6
+ adapter: "sqlite3",
7
+ database: "db/peak_flow_utils.sqlite3"
8
+ )
9
+ end
@@ -0,0 +1,22 @@
1
+ class PeakFlowUtils::Group < PeakFlowUtils::ApplicationRecord
2
+ attr_writer :at_group
3
+
4
+ belongs_to :handler
5
+
6
+ has_many :handler_translations, dependent: :destroy
7
+ has_many :translation_keys, dependent: :destroy
8
+
9
+ validates :name, :handler, presence: true
10
+
11
+ def at_handler
12
+ @at_handler ||= handler.at_handler
13
+ end
14
+
15
+ def at_group
16
+ @at_group ||= PeakFlowUtils::GroupService.find_by_handler_and_id(at_handler, identifier) # rubocop:disable Rails/DynamicFindBy
17
+ end
18
+
19
+ def to_param
20
+ identifier
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ class PeakFlowUtils::Handler < PeakFlowUtils::ApplicationRecord
2
+ has_many :groups, dependent: :destroy
3
+ has_many :handler_texts, dependent: :destroy
4
+
5
+ validates :name, presence: true
6
+
7
+ def at_handler
8
+ @at_handler ||= PeakFlowUtils::HandlerHelper.find(identifier)
9
+ end
10
+
11
+ def to_param
12
+ identifier
13
+ end
14
+ end
@@ -0,0 +1,46 @@
1
+ class PeakFlowUtils::HandlerText < PeakFlowUtils::ApplicationRecord
2
+ belongs_to :group
3
+ belongs_to :handler
4
+ belongs_to :translation_key
5
+
6
+ validates :handler, :translation_key, presence: true
7
+
8
+ delegate :key, :last_key, to: :translation_key
9
+ delegate :value, to: :translation, prefix: true
10
+ delegate :array_translation?, :file_line_content, :file_line_content?, :translated_value_for_locale, to: :translation
11
+
12
+ def key_show_with_fallback
13
+ key_show.presence || last_key
14
+ end
15
+
16
+ def translation
17
+ @translation ||= PeakFlowUtils::Translation.new(
18
+ key: key,
19
+ dir: dir,
20
+ full_path: full_path,
21
+ file_path: file_path,
22
+ line_no: line_no
23
+ )
24
+ end
25
+
26
+ def finished?
27
+ @_finished = translation.finished? if @finished.nil?
28
+ @_finished
29
+ end
30
+
31
+ def unfinished?
32
+ !finished?
33
+ end
34
+
35
+ def array_key
36
+ return unless (match = key.match(/\A(.+)\[(\d+)\]\Z/))
37
+
38
+ match[1]
39
+ end
40
+
41
+ def array_no
42
+ return unless (match = key.match(/\A(.+)\[(\d+)\]\Z/))
43
+
44
+ match[2].to_i
45
+ end
46
+ end
@@ -0,0 +1,2 @@
1
+ class PeakFlowUtils::ScannedFile < PeakFlowUtils::ApplicationRecord
2
+ end
@@ -0,0 +1,8 @@
1
+ class PeakFlowUtils::TranslationKey < PeakFlowUtils::ApplicationRecord
2
+ has_many :handler_translations, dependent: :destroy
3
+ has_many :translation_values, dependent: :destroy
4
+
5
+ def last_key
6
+ key.to_s.split(".").last
7
+ end
8
+ end
@@ -0,0 +1,24 @@
1
+ class PeakFlowUtils::TranslationValue < PeakFlowUtils::ApplicationRecord
2
+ belongs_to :translation_key
3
+
4
+ validates :translation_key, presence: true
5
+
6
+ delegate :key, to: :translation_key
7
+
8
+ def calculated_translation_file_path
9
+ "#{handler_translation.dir}/#{locale}.yml" if handler_translation
10
+ end
11
+
12
+ def handler_translation
13
+ @handler_translation ||= PeakFlowUtils::HandlerText
14
+ .find_by(translation_key_id: translation_key_id)
15
+ end
16
+
17
+ def migrate_to_awesome_translations_namespace!
18
+ PeakFlowUtils::TranslationMigrator.new(
19
+ translation_key: translation_key,
20
+ handler_translation: handler_translation,
21
+ translation_value: self
22
+ ).execute
23
+ end
24
+ end
@@ -0,0 +1,2 @@
1
+ class PeakFlowUtils::ApplicationService < ServicePattern::Service
2
+ end
@@ -0,0 +1,32 @@
1
+ class PeakFlowUtils::AttributeService
2
+ attr_reader :name, :model_inspector
3
+
4
+ def initialize(model_inspector, name)
5
+ @model_inspector = model_inspector
6
+ @name = name
7
+ end
8
+
9
+ def i18n_key
10
+ "activerecord.attributes.#{@model_inspector.snake_name}.#{@name}"
11
+ end
12
+
13
+ def simple_form_include_blank_key
14
+ "simple_form.include_blanks.#{@model_inspector.snake_name}.#{@name}"
15
+ end
16
+
17
+ def simple_form_label_key
18
+ "simple_form.labels.#{@model_inspector.snake_name}.#{@name}"
19
+ end
20
+
21
+ def simple_form_hint_key
22
+ "simple_form.hints.#{@model_inspector.snake_name}.#{@name}"
23
+ end
24
+
25
+ def simple_form_placeholder_key
26
+ "simple_form.placeholders.#{@model_inspector.snake_name}.#{@name}"
27
+ end
28
+
29
+ def simple_form_prompt_key
30
+ "simple_form.prompts.#{@model_inspector.snake_name}.#{@name}"
31
+ end
32
+ end
@@ -0,0 +1,11 @@
1
+ class PeakFlowUtils::ConfigurationService
2
+ attr_accessor :paths_to_translate
3
+
4
+ def self.current
5
+ @current ||= PeakFlowUtils::ConfigurationService.new
6
+ end
7
+
8
+ def initialize
9
+ @paths_to_translate = [Rails.root.to_s]
10
+ end
11
+ end
@@ -0,0 +1,39 @@
1
+ class PeakFlowUtils::DatabaseInitializerService < PeakFlowUtils::ApplicationService
2
+ def execute
3
+ path = File.realpath("#{File.dirname(__FILE__)}/../../migrations")
4
+ create_schema_table unless schema_table_exists?
5
+
6
+ Dir["#{path}/[0-9]*_*.rb"].sort.map do |filename|
7
+ match = filename.match(/migrations\/(\d+)_(.+)\.rb\Z/)
8
+ next unless match
9
+
10
+ version = match[1]
11
+ next if version_migrated?(version)
12
+
13
+ require filename
14
+ migration = match[2].camelize.constantize
15
+ migration.migrate(:up)
16
+ register_migration_migrated(version)
17
+ end
18
+
19
+ ServicePattern::Response.new(success: true)
20
+ end
21
+
22
+ private
23
+
24
+ def create_schema_table
25
+ PeakFlowUtils::ApplicationRecord.connection.execute("CREATE TABLE schema_migrations (version VARCHAT)")
26
+ end
27
+
28
+ def register_migration_migrated(version)
29
+ PeakFlowUtils::ApplicationRecord.connection.execute("INSERT INTO schema_migrations (version) VALUES ('#{version}')")
30
+ end
31
+
32
+ def schema_table_exists?
33
+ PeakFlowUtils::ApplicationRecord.connection.execute("SELECT * FROM sqlite_master WHERE type = 'table' AND name = 'schema_migrations'").any?
34
+ end
35
+
36
+ def version_migrated?(version)
37
+ PeakFlowUtils::ApplicationRecord.connection.execute("SELECT * FROM schema_migrations WHERE version = '#{version}'").any?
38
+ end
39
+ end
@@ -0,0 +1,71 @@
1
+ class PeakFlowUtils::ErbInspector
2
+ def initialize(args = {})
3
+ @args = args
4
+ @args[:exts] ||= [".erb", ".haml", ".liquid", ".markerb", ".rb", ".rake", ".slim", "."] + PeakFlowUtils::ErbInspector::FileInspector::JS_FILE_EXTS
5
+
6
+ if @args[:dirs]
7
+ @dirs = @args[:dirs]
8
+ else
9
+ @dirs = PeakFlowUtils::ConfigurationService.current.paths_to_translate
10
+ end
11
+ end
12
+
13
+ # Yields all relevant .erb- and .haml-files.
14
+ def files
15
+ Enumerator.new do |yielder|
16
+ @dirs.each do |dir|
17
+ scan_dir("", dir, yielder)
18
+ end
19
+ end
20
+ end
21
+
22
+ def file(root_path, file_path)
23
+ PeakFlowUtils::ErbInspector::FileInspector.new(
24
+ file_path: file_path,
25
+ root_path: root_path
26
+ )
27
+ end
28
+
29
+ private
30
+
31
+ def scan_dir(path, root_path, yielder)
32
+ Dir.foreach("#{root_path}/#{path}") do |file|
33
+ next if file == "." || file == ".."
34
+
35
+ file_path = path.clone
36
+ file_path << "/" unless file_path.empty?
37
+ file_path << file
38
+
39
+ file_path_with_path = "#{path}/#{file_path}"
40
+
41
+ full_path = "#{root_path}/#{file_path}"
42
+ ext = File.extname(file_path)
43
+
44
+ if File.directory?(full_path)
45
+ scan_dir(file_path, root_path, yielder)
46
+ elsif @args[:exts].include?(ext)
47
+ scanned_file = PeakFlowUtils::ScannedFile.find_or_initialize_by(file_path: file_path_with_path)
48
+ file_size = File.size(full_path)
49
+ last_changed_at = File.mtime(full_path)
50
+
51
+ changed = false
52
+ changed = true unless file_size == scanned_file.file_size
53
+ changed = true unless last_changed_at.to_s == scanned_file.last_changed_at.to_s
54
+
55
+ if changed
56
+ scanned_file.assign_attributes(
57
+ file_size: file_size,
58
+ last_changed_at: last_changed_at
59
+ )
60
+ scanned_file.save!
61
+ end
62
+
63
+ yielder << PeakFlowUtils::ErbInspector::FileInspector.new(
64
+ file_path: file_path,
65
+ root_path: root_path,
66
+ changed: changed
67
+ )
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,137 @@
1
+ class PeakFlowUtils::ErbInspector::FileInspector
2
+ JS_FILE_EXTS = [".coffee", ".coffee.erb", ".es6", ".es6.erb", ".js", ".js.erb"].freeze
3
+ METHOD_NAMES = %w[t controller_t helper_t].freeze
4
+ VALID_BEGINNING = '(^|\s+|\(|\{|\[|<%=\s*|I18n\.)'.freeze
5
+
6
+ attr_reader :root_path, :file_path
7
+
8
+ def initialize(args)
9
+ @args = args
10
+ @root_path = args[:root_path]
11
+ @file_path = args[:file_path]
12
+ @method_names ||= ["t"]
13
+ end
14
+
15
+ def translations
16
+ Enumerator.new do |yielder|
17
+ File.open(full_path, "r") do |fp|
18
+ extname = File.extname(full_path)
19
+ translations_found = []
20
+ line_no = 0
21
+
22
+ fp.each_line do |line|
23
+ line_no += 1
24
+ line = force_utf8(line)
25
+
26
+ if extname == ".liquid"
27
+ parse_content_liquid(line_no, line, translations_found, yielder)
28
+ elsif JS_FILE_EXTS.include?(extname)
29
+ parse_content_js(line_no, line, translations_found, yielder)
30
+ else
31
+ parse_content(line_no, line, translations_found, yielder)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def full_path
39
+ "#{@root_path}/#{@file_path}"
40
+ end
41
+
42
+ def basename
43
+ File.basename(@file_path).match(/\A(.+?)\./)[1]
44
+ end
45
+
46
+ def changed?
47
+ @args.fetch(:changed)
48
+ end
49
+
50
+ def to_s
51
+ "<PeakFlowUtils::ErbInspector::FileInspector file_path=\"#{@file_path}\">"
52
+ end
53
+
54
+ def inspect
55
+ to_s
56
+ end
57
+
58
+ private
59
+
60
+ def parse_content_liquid(line_no, line, translations_found, yielder)
61
+ line.scan(/\"([^\"]+?)\"\s+\|\s+t\s*(\%}|\}\}|\|)/) do |match|
62
+ add_translation(line_no, "t", match[0], translations_found, yielder)
63
+ end
64
+
65
+ line.scan(/\'([^\']+?)\'\s+\|\s+t\s*(\%}|\}\}|\|)/) do |match|
66
+ add_translation(line_no, "t", match[0], translations_found, yielder)
67
+ end
68
+
69
+ line.scan(/\"([^\"]+?)\"\s+\|\s+val:\s*\"([^\"]+?)\"\s*,\s*(.+?)\s*\|\s+t\s*/) do |match|
70
+ add_translation(line_no, "t", match[0], translations_found, yielder)
71
+ end
72
+
73
+ line.scan(/'([^\"]+?)'\s+\|\s+val:\s*'([^\"]+?)'\s*,\s*(.+?)\s*\|\s+t\s*/) do |match|
74
+ add_translation(line_no, "t", match[0], translations_found, yielder)
75
+ end
76
+ end
77
+
78
+ def parse_content_js(line_no, line, translations_found, yielder)
79
+ line.scan(/\I18n\.t\('(.+?)'\)/) do |match|
80
+ add_translation(line_no, "I18n.t", match[0], translations_found, yielder)
81
+ end
82
+
83
+ line.scan(/\I18n\.t\("(.+?)"\)/) do |match|
84
+ add_translation(line_no, "I18n-js.t", match[0], translations_found, yielder)
85
+ end
86
+ end
87
+
88
+ def parse_content(line_no, line, translations_found, yielder)
89
+ METHOD_NAMES.each do |method_name|
90
+ if (last_method_match = line.match(/def\s+(.+?)(\(|\n|\r\n)/))
91
+ @last_method = last_method_match[1]
92
+ end
93
+
94
+ # Scan for the various valid formats.
95
+ line.scan(/#{VALID_BEGINNING}(#{Regexp.escape(method_name)})\s*\("(.+?)"/) do |match|
96
+ add_translation(line_no, match[1], match[2], translations_found, yielder)
97
+ end
98
+
99
+ line.scan(/#{VALID_BEGINNING}(#{Regexp.escape(method_name)})\s*"(.+?)"/) do |match|
100
+ add_translation(line_no, match[1], match[2], translations_found, yielder)
101
+ end
102
+
103
+ line.scan(/#{VALID_BEGINNING}(#{Regexp.escape(method_name)})\s*\('(.+?)'/) do |match|
104
+ add_translation(line_no, match[1], match[2], translations_found, yielder)
105
+ end
106
+
107
+ line.scan(/#{VALID_BEGINNING}(#{Regexp.escape(method_name)})\s*'(.+?)'/) do |match|
108
+ add_translation(line_no, match[1], match[2], translations_found, yielder)
109
+ end
110
+ end
111
+ end
112
+
113
+ def add_translation(line_no, method, key, translations_found, yielder)
114
+ translation_inspector = PeakFlowUtils::ErbInspector::TranslationInspector.new(
115
+ last_method: @last_method,
116
+ root_path: @root_path,
117
+ file_path: @file_path,
118
+ line_no: line_no,
119
+ method: method,
120
+ key: key
121
+ )
122
+
123
+ return if translation_inspector.contains_interpolations?
124
+ return if translation_with_key_exists?(translations_found, translation_inspector.full_key)
125
+
126
+ yielder << translation_inspector
127
+ translations_found << translation_inspector
128
+ end
129
+
130
+ def force_utf8(string)
131
+ string.encode("UTF-8", "binary", invalid: :replace, undef: :replace, replace: "")
132
+ end
133
+
134
+ def translation_with_key_exists?(translations_found, translation_full_key)
135
+ translations_found.select { |t| t.full_key == translation_full_key }.any?
136
+ end
137
+ end