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,100 @@
1
+ class PeakFlowUtils::ErbInspector::TranslationInspector
2
+ attr_reader :dir, :file_path, :last_method, :line_no, :method, :key, :full_key, :full_path, :root_path
3
+
4
+ def initialize(args)
5
+ @file_path = args[:file_path]
6
+ @full_path = args[:full_path]
7
+ @line_no = args[:line_no]
8
+ @method = args[:method]
9
+ @key = args[:key]
10
+ @root_path = args[:root_path]
11
+ @last_method = args[:last_method]
12
+
13
+ @full_path = "#{@root_path}/#{@file_path}"
14
+
15
+ generate_full_key
16
+ generate_dir
17
+ end
18
+
19
+ def model
20
+ PeakFlowUtils::TranslationService.new(
21
+ key: @full_key,
22
+ dir: @dir,
23
+ full_path: @full_path,
24
+ file_path: @file_path,
25
+ line_no: @line_no
26
+ )
27
+ end
28
+
29
+ def global?
30
+ !relative? && !key.include?(".")
31
+ end
32
+
33
+ def relative?
34
+ key.start_with?(".")
35
+ end
36
+
37
+ def contains_interpolations?
38
+ key =~ /#\{(.+?)\}/
39
+ end
40
+
41
+ private
42
+
43
+ def generate_full_key
44
+ if (@method == "t" || @method == "helper_t" || @method == "controller_t" || @method == "I18n-js.t") && @key.start_with?(".")
45
+ @full_key = File.dirname(@file_path).to_s
46
+
47
+ if @full_key.starts_with?("app/mailers")
48
+ @full_key.gsub!(/\Aapp\/mailers(\/|)/, "")
49
+ is_mailer = true
50
+ elsif @full_key.start_with?("app/views/")
51
+ # Remove "app/views" from view-translations since that doesn't get used in keys.
52
+ @full_key.gsub!(/\Aapp\/views\//, "")
53
+ elsif @full_key.start_with?("app/controllers")
54
+ # Remove "app/controllers" from controller-translations since that doesn't get used in keys.
55
+ @full_key.gsub!(/\Aapp\/controllers(\/?)/, "")
56
+ is_controller = true
57
+ elsif @full_key.start_with?("app/cells")
58
+ @full_key.gsub!(/\Aapp\/cells\//, "")
59
+ elsif @full_key.start_with?("app/")
60
+ # Remove "app" from controller- and helper-translations since that doesn't get used.
61
+ @full_key.gsub!(/\Aapp\//, "")
62
+ end
63
+
64
+ @full_key.tr!("/", ".")
65
+ @full_key << "." unless @full_key.empty?
66
+ @full_key << file_key(@file_path)
67
+ @full_key << ".#{@last_method}" if (is_mailer || is_controller) && @last_method && @method != "controller_t"
68
+ @full_key << "."
69
+ @full_key << @key.gsub(/\A\./, "")
70
+ elsif @method == "I18n-js.t" || @method == "t" || @method == "helper_t" || @method == "controller_t"
71
+ @full_key = @key
72
+ else
73
+ raise "Unknown method-name: '#{@method}'."
74
+ end
75
+ end
76
+
77
+ def file_key(file_path)
78
+ key = File.basename(file_path)
79
+
80
+ # Remove extension
81
+ key = key.match(/\A(.+?)\./)[1]
82
+
83
+ # Remove leading "_" from partials
84
+ key = key.gsub(/\A_/, "")
85
+
86
+ # Remove '_controller' from controllers
87
+ key = key.gsub(/_controller\Z/, "")
88
+
89
+ key
90
+ end
91
+
92
+ def generate_dir
93
+ parts = %w[config locales awesome_translations]
94
+
95
+ key_parts = @full_key.split(".").reject(&:blank?)
96
+ key_parts.pop
97
+
98
+ @dir = Rails.root.join(*(parts + key_parts)).to_s
99
+ end
100
+ end
@@ -0,0 +1,50 @@
1
+ class PeakFlowUtils::GroupService
2
+ attr_reader :handler, :id, :data
3
+
4
+ def self.find_by_handler_and_id(handler, id)
5
+ handler.groups.each do |group|
6
+ return group if group.id == id.to_s
7
+ end
8
+
9
+ raise ActiveRecord::RecordNotFound, "Group not found by handler and ID: '#{handler.name}', '#{id}'."
10
+ end
11
+
12
+ def initialize(args)
13
+ @handler = args.fetch(:handler)
14
+ @id = args.fetch(:id)
15
+ @data = args[:data] || {}
16
+ raise "Invalid ID: #{@id}" if @id.blank?
17
+ end
18
+
19
+ def translations(args = {})
20
+ translations_list = @handler.translations_for_group(self)
21
+
22
+ args.each do |key, value|
23
+ if key == :finished
24
+ translations_list = translations_list.select(&:finished?) if value
25
+ elsif key == :unfinished
26
+ translations_list = translations_list.select(&:unfinished?) if value
27
+ else
28
+ raise "Unknown key: #{key}"
29
+ end
30
+ end
31
+
32
+ translations_list
33
+ end
34
+
35
+ def to_param
36
+ id
37
+ end
38
+
39
+ def name
40
+ @data[:name].presence || id.presence
41
+ end
42
+
43
+ def to_s
44
+ "<PeakFlowUtils::GroupService id=\"#{@id}\" name=\"#{name}\">"
45
+ end
46
+
47
+ def inspect
48
+ to_s
49
+ end
50
+ end
@@ -0,0 +1,25 @@
1
+ class PeakFlowUtils::HandlersFinderService < PeakFlowUtils::ApplicationService
2
+ def execute
3
+ handlers = []
4
+
5
+ Dir.foreach("#{File.dirname(__FILE__)}/../../handlers/peak_flow_utils") do |file|
6
+ match = file.match(/\A(.+)_handler\.rb\Z/)
7
+ next unless match
8
+
9
+ const_name_snake = "#{match[1]}_handler"
10
+ next if const_name_snake == "application_handler"
11
+
12
+ const_name_camel = const_name_snake.camelize
13
+
14
+ handler = PeakFlowUtils::HandlerHelper.new(
15
+ id: const_name_snake,
16
+ const_name: const_name_camel,
17
+ name: const_name_camel
18
+ )
19
+
20
+ handlers << handler if handler.instance.enabled?
21
+ end
22
+
23
+ ServicePattern::Response.new(result: handlers)
24
+ end
25
+ end
@@ -0,0 +1,133 @@
1
+ class PeakFlowUtils::ModelInspector
2
+ attr_reader :clazz
3
+ cattr_accessor :models_loaded
4
+
5
+ # Yields a model-inspector for each model found in the application.
6
+ def self.model_classes
7
+ # Make sure all models are loaded.
8
+ load_models
9
+
10
+ @scanned = {}
11
+ @yielded = {}
12
+ @skip = ["ActiveRecord::SchemaMigration"]
13
+
14
+ ArrayEnumerator.new do |yielder|
15
+ find_subclasses(ActiveRecord::Base) do |model_inspector|
16
+ next if !model_inspector.clazz.name || @skip.include?(model_inspector.clazz.name)
17
+
18
+ yielder << model_inspector
19
+ end
20
+ end
21
+ end
22
+
23
+ def initialize(clazz)
24
+ @clazz = clazz
25
+ end
26
+
27
+ def attributes
28
+ ArrayEnumerator.new do |yielder|
29
+ @clazz.attribute_names.each do |attribute_name|
30
+ yielder << PeakFlowUtils::AttributeService.new(self, attribute_name)
31
+ end
32
+ end
33
+ end
34
+
35
+ def paperclip_attachments
36
+ return unless ::Kernel.const_defined?("Paperclip")
37
+
38
+ Paperclip::AttachmentRegistry.names_for(@clazz).each do |name|
39
+ yield name
40
+ end
41
+ end
42
+
43
+ def money_attributes
44
+ return if !::Kernel.const_defined?("Money") || !@clazz.respond_to?(:monetized_attributes)
45
+
46
+ @clazz.monetized_attributes.each do |attribute|
47
+ yield attribute[0].to_s
48
+ end
49
+ end
50
+
51
+ def globalize_attributes
52
+ return if !::Kernel.const_defined?("Globalize") || !@clazz.respond_to?(:translated_attribute_names)
53
+
54
+ @clazz.translated_attribute_names.each do |attribute|
55
+ yield attribute.to_s
56
+ end
57
+ end
58
+
59
+ def snake_name
60
+ clazz.name.gsub("::", "/").split("/").map(&:underscore).join("/")
61
+ end
62
+
63
+ def class_key
64
+ "activerecord.models.#{snake_name}"
65
+ end
66
+
67
+ def class_key_one
68
+ "#{class_key}.one"
69
+ end
70
+
71
+ def class_key_other
72
+ "#{class_key}.other"
73
+ end
74
+
75
+ # TODO: Maybe this should yield a ModelInspector::Relationship instead?
76
+ def relationships
77
+ @clazz.reflections.each do |key, reflection|
78
+ yield key, reflection
79
+ end
80
+ end
81
+
82
+ def attribute_key(attribute_name)
83
+ "activerecord.attributes.#{snake_name}.#{attribute_name}"
84
+ end
85
+
86
+ def to_s
87
+ "<PeakFlowUtils::ModelInspector class-name: \"#{@clazz.name}\">"
88
+ end
89
+
90
+ def inspect
91
+ to_s
92
+ end
93
+
94
+ def self.find_subclasses(clazz, &blk)
95
+ return if @scanned[clazz.name]
96
+
97
+ @scanned[clazz.name] = true
98
+
99
+ clazz.subclasses.each do |subclass|
100
+ blk.call ::PeakFlowUtils::ModelInspector.new(subclass)
101
+ find_subclasses(subclass, &blk)
102
+ end
103
+ end
104
+
105
+ # Preloads all models for Rails app and all engines (if they aren't loaded, then they cant be inspected).
106
+ def self.load_models
107
+ return false if PeakFlowUtils::ModelInspector.models_loaded
108
+
109
+ PeakFlowUtils::ModelInspector.models_loaded = true
110
+
111
+ load_models_for(Rails.root)
112
+ engines.each do |engine|
113
+ load_models_for(engine.root)
114
+ end
115
+
116
+ true
117
+ end
118
+
119
+ def self.engines
120
+ ::Rails::Engine.subclasses.map(&:instance)
121
+ end
122
+
123
+ # Loads models for the given app-directory (Rails-root or engine).
124
+ def self.load_models_for(root)
125
+ Dir.glob("#{root}/app/models/**/*.rb") do |model_path|
126
+ require model_path
127
+ rescue StandardError => e
128
+ warn "Could not load model in #{model_path}"
129
+ warn e.inspect
130
+ warn e.backtrace
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,138 @@
1
+ class PeakFlowUtils::TranslationService
2
+ attr_reader :default, :dir, :key, :key_show, :file_path, :line_no, :full_path
3
+
4
+ def initialize(data)
5
+ @data = data
6
+ @dir = data[:dir]
7
+ @file_path = data[:file_path]
8
+ @full_path = data[:full_path]
9
+ @line_no = data[:line_no]
10
+ @key = data[:key]
11
+ @key_show = data[:key_show]
12
+ @default = data[:default]
13
+
14
+ raise "Dir wasn't valid: '#{@dir}'." if @dir.blank?
15
+ end
16
+
17
+ def last_key
18
+ key.to_s.split(".").last
19
+ end
20
+
21
+ def key_show_with_fallback
22
+ @key_show.presence || last_key
23
+ end
24
+
25
+ def array_translation?
26
+ return true if /\[(\d+)\]\Z/.match?(@key)
27
+
28
+ false
29
+ end
30
+
31
+ def array_key
32
+ return unless (match = @key.match(/\A(.+)\[(\d+)\]\Z/))
33
+
34
+ match[1]
35
+ end
36
+
37
+ def array_no
38
+ return unless (match = @key.match(/\A(.+)\[(\d+)\]\Z/))
39
+
40
+ match[2].to_i
41
+ end
42
+
43
+ def to_param
44
+ id
45
+ end
46
+
47
+ def name
48
+ key
49
+ end
50
+
51
+ def translated_values
52
+ result = []
53
+
54
+ I18n.available_locales.each do |locale|
55
+ next unless value_for?(locale)
56
+
57
+ result << AwesomeTranslations::TranslatedValue.new(
58
+ file: "#{dir}/#{locale}.yml",
59
+ key: @key,
60
+ locale: locale,
61
+ value: value(locale: locale)
62
+ )
63
+ end
64
+
65
+ result
66
+ end
67
+
68
+ def finished?
69
+ I18n.available_locales.each do |locale|
70
+ next if value_for?(locale)
71
+
72
+ return false
73
+ end
74
+
75
+ true
76
+ end
77
+
78
+ def translated_value_for_locale(locale)
79
+ AwesomeTranslations::TranslatedValue.new(
80
+ file: "#{dir}/#{locale}.yml",
81
+ key: @key,
82
+ locale: locale,
83
+ value: value_for?(locale) ? value(locale: locale) : ""
84
+ )
85
+ end
86
+
87
+ def value_for?(locale)
88
+ if array_translation?
89
+ I18n.with_locale(locale) { I18n.exists?(array_key) && I18n.t(array_key)[array_no].present? }
90
+ else
91
+ I18n.with_locale(locale) { I18n.exists?(@key) }
92
+ end
93
+ end
94
+
95
+ def value(args = {})
96
+ locale = (args[:locale] || I18n.locale || I18n.default_locale).to_sym
97
+
98
+ return nil unless value_for?(locale)
99
+
100
+ if array_translation?
101
+ I18n.with_locale(locale) { I18n.t(array_key)[array_no] }
102
+ else
103
+ I18n.with_locale(locale) { I18n.t(@key) }
104
+ end
105
+ end
106
+
107
+ def file_line_content?
108
+ return true if @full_path && @line_no && File.exist?(@full_path)
109
+
110
+ false
111
+ end
112
+
113
+ def file_line_content
114
+ count = 0
115
+
116
+ File.open(@full_path, "r") do |fp|
117
+ fp.each_line do |line|
118
+ count += 1
119
+ return line if count == @line_no
120
+ end
121
+ end
122
+
123
+ nil
124
+ end
125
+
126
+ def to_s
127
+ "<PeakFlowUtils::TranslationService " \
128
+ "key=\"#{@key}\" " \
129
+ "dir=\"#{@dir}\" " \
130
+ "array_translation?=\"#{array_translation?}\" " \
131
+ "array_key=\"#{array_key}\" " \
132
+ "array_no=\"#{array_no}\">"
133
+ end
134
+
135
+ def inspect
136
+ to_s
137
+ end
138
+ end