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,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