rails_extend 1.0.0 → 1.0.1

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +20 -0
  3. data/README.md +46 -0
  4. data/config/locales/en.datetime.yml +17 -0
  5. data/config/locales/zh.datetime.yml +145 -0
  6. data/config/locales/zh.support.yml +52 -0
  7. data/lib/generators/rails_extend/ignore_generator.rb +27 -0
  8. data/lib/generators/rails_extend/migrations_generator.rb +33 -0
  9. data/lib/generators/rails_extend/remove_table_generator.rb +29 -0
  10. data/lib/generators/rails_extend/rename_module_generator.rb +29 -0
  11. data/lib/generators/rails_extend/templates/README.md +2 -0
  12. data/lib/generators/rails_extend/templates/initializer.rb.tt +10 -0
  13. data/lib/generators/rails_extend/templates/migration.rb.tt +35 -0
  14. data/lib/generators/rails_extend/templates/remove_table.rb.tt +9 -0
  15. data/lib/generators/rails_extend/templates/rename_module.rb.tt +9 -0
  16. data/lib/rails_extend/active_model/type_value.rb +26 -0
  17. data/lib/rails_extend/active_model.rb +3 -0
  18. data/lib/rails_extend/active_record/enum.rb +74 -0
  19. data/lib/rails_extend/active_record/extend.rb +200 -0
  20. data/lib/rails_extend/active_record/i18n.rb +31 -0
  21. data/lib/rails_extend/active_record/include.rb +29 -0
  22. data/lib/rails_extend/active_record/taxon.rb +29 -0
  23. data/lib/rails_extend/active_record/translation.rb +41 -0
  24. data/lib/rails_extend/active_record.rb +8 -0
  25. data/lib/rails_extend/active_storage/attachment.rb +16 -0
  26. data/lib/rails_extend/active_storage/blob_prepend.rb +40 -0
  27. data/lib/rails_extend/active_storage/variant.rb +16 -0
  28. data/lib/rails_extend/active_storage.rb +5 -0
  29. data/lib/rails_extend/config.rb +19 -0
  30. data/lib/rails_extend/core/array.rb +79 -0
  31. data/lib/rails_extend/core/date.rb +32 -0
  32. data/lib/rails_extend/core/duration.rb +12 -0
  33. data/lib/rails_extend/core/hash.rb +106 -0
  34. data/lib/rails_extend/core/module.rb +7 -0
  35. data/lib/rails_extend/core/nil.rb +11 -0
  36. data/lib/rails_extend/core/numeric.rb +11 -0
  37. data/lib/rails_extend/core/pathname.rb +15 -0
  38. data/lib/rails_extend/core/string.rb +15 -0
  39. data/lib/rails_extend/core/time_format.rb +20 -0
  40. data/lib/rails_extend/core.rb +17 -0
  41. data/lib/rails_extend/engine.rb +13 -0
  42. data/lib/rails_extend/env.rb +10 -0
  43. data/lib/rails_extend/generators/named_base.rb +22 -0
  44. data/lib/rails_extend/generators.rb +3 -0
  45. data/lib/rails_extend/models.rb +120 -0
  46. data/lib/rails_extend/quiet_logs.rb +22 -0
  47. data/lib/rails_extend/routes.rb +81 -0
  48. data/lib/rails_extend/type/i18n.rb +23 -0
  49. data/lib/rails_extend/type/taxon.rb +15 -0
  50. data/lib/rails_extend/type.rb +4 -0
  51. data/lib/rails_extend.rb +19 -0
  52. data/lib/templates/test_unit/model/fixtures.yml.tt +15 -0
  53. data/lib/templates/test_unit/model/unit_test.rb.tt +7 -0
  54. metadata +56 -5
  55. data/lib/active_model/type_value.rb +0 -20
@@ -0,0 +1,11 @@
1
+ class Numeric
2
+
3
+ def half_round
4
+ (self * 2).round / 2.0
5
+ end
6
+
7
+ def half_floor
8
+ (self * 2).floor / 2.0
9
+ end
10
+
11
+ end
@@ -0,0 +1,15 @@
1
+ class Pathname
2
+
3
+ # like present? and presence
4
+ # if exist? return self
5
+ def existence
6
+ self if exist?
7
+ end
8
+
9
+ # xx.html.erb => xx
10
+ def without_extname
11
+ suffix = basename.to_s.split('.')[0]
12
+ dirname.join(suffix)
13
+ end
14
+
15
+ end
@@ -0,0 +1,15 @@
1
+ class String
2
+
3
+ def integer?
4
+ Integer(self).is_a?(Integer)
5
+ rescue ArgumentError, TypeError
6
+ false
7
+ end
8
+
9
+ def numeric?
10
+ Float(self).is_a?(Numeric)
11
+ rescue ArgumentError, TypeError
12
+ false
13
+ end
14
+
15
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ Time::DATE_FORMATS[:datetime] = '%Y-%m-%d %H:%M'
4
+ Time::DATE_FORMATS[:local] = '%Y-%m-%dT%H:%M:%S'
5
+ Time::DATE_FORMATS[:week] = ->(time) {
6
+ I18n.t('date.day_names')[time.wday]
7
+ }
8
+ Time::DATE_FORMATS[:date] = ->(time) {
9
+ t = Time.zone.at time
10
+ t.strftime '%Y-%m-%d'
11
+ }
12
+ Time::DATE_FORMATS[:month] = ->(time) {
13
+ I18n.t('date.month_names')[time.month]
14
+ }
15
+ Date::DATE_FORMATS[:week] = ->(date) {
16
+ I18n.t('date.day_names')[date.wday]
17
+ }
18
+ Date::DATE_FORMATS[:month] = ->(date) {
19
+ I18n.t('date.month_names')[date.month]
20
+ }
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Ruby core extension
4
+ require 'rails_extend/core/hash'
5
+ require 'rails_extend/core/nil'
6
+ require 'rails_extend/core/array'
7
+ require 'rails_extend/core/date'
8
+ require 'rails_extend/core/numeric'
9
+ require 'rails_extend/core/string'
10
+ require 'rails_extend/core/time_format'
11
+ require 'rails_extend/core/module'
12
+
13
+ # Ruby Strand Library extensions
14
+ require 'rails_extend/core/pathname'
15
+
16
+ # Rails
17
+ require 'rails_extend/core/duration'
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsExtend
4
+ class Engine < ::Rails::Engine #:nodoc:
5
+
6
+ initializer 'rails_extend.quiet_logs' do |app|
7
+ if RailsExtend.config.quiet_logs.present?
8
+ app.middleware.insert_before ::Rails::Rack::Logger, ::RailsExtend::QuietLogs
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsExtend::Env
4
+ extend self
5
+
6
+ def environments
7
+ Dir.children(Rails.root.join('config', 'environments')).map! { |rb| rb.delete_suffix!('.rb') }
8
+ end
9
+
10
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ module RailsExtend::Generators
5
+ module NamedBase
6
+
7
+ def class_name
8
+ file_name.classify
9
+ end
10
+
11
+ def singular_route_name
12
+ [class_path[-1], singular_name].join('_')
13
+ end
14
+
15
+ def plural_route_name
16
+ [class_path[-1], plural_name].join('_')
17
+ end
18
+
19
+ end
20
+ end
21
+
22
+ Rails::Generators::NamedBase.prepend RailsExtend::Generators::NamedBase
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_extend/generators/named_base'
@@ -0,0 +1,120 @@
1
+ module RailsExtend::Models
2
+ extend self
3
+
4
+ def models_hash(root = ActiveRecord::Base)
5
+ return @models_hash if defined? @models_hash
6
+ Zeitwerk::Loader.eager_load_all
7
+ @models_hash = root.subclasses_tree
8
+ end
9
+
10
+ def models
11
+ return @models if defined? @models
12
+ Zeitwerk::Loader.eager_load_all
13
+ @models = ActiveRecord::Base.descendants
14
+ @models.reject!(&:abstract_class?)
15
+ @models
16
+ end
17
+
18
+ def db_tables_hash
19
+ result = {}
20
+
21
+ models.group_by(&->(i) { i.connection.migrations_paths }).each do |migrations_paths, record_classes|
22
+ result[migrations_paths] = migrate_tables_hash
23
+ end
24
+
25
+ result
26
+ end
27
+
28
+ def tables_hash(root = ActiveRecord::Base, records_hash = models_hash)
29
+ @tables ||= {}
30
+
31
+ records_hash[root].each_key do |node|
32
+ next if RailsExtend.config.ignore_models.include?(node.to_s)
33
+
34
+ unless node.abstract_class?
35
+ @tables[node.table_name] ||= {}
36
+ r = @tables[node.table_name]
37
+ r[:models] ||= []
38
+ r[:models] << node
39
+
40
+ r[:table_exists] = r[:table_exists] || node.table_exists?
41
+
42
+ r[:model_attributes] ||= {}
43
+ r[:model_attributes].reverse_merge! node.migrate_attributes_by_model
44
+
45
+ r[:model_references] ||= {}
46
+ r[:model_references].reverse_merge! node.references_by_model
47
+
48
+ r[:indexes] ||= []
49
+ r[:indexes] |= node.indexes_by_model
50
+
51
+ r[:model_defaults] ||= []
52
+ r[:model_defaults] |= node.attributes_by_default
53
+
54
+ r[:belongs_attributes] ||= {}
55
+ r[:belongs_attributes].reverse_merge! node.attributes_by_belongs
56
+ end
57
+
58
+ tables_hash(node, records_hash[root])
59
+ end
60
+
61
+ @tables
62
+ end
63
+
64
+ def migrate_tables_hash
65
+ tables = {}
66
+
67
+ tables_hash.each do |table_name, cols|
68
+ db = cols[:models][0].migrate_attributes_by_db
69
+
70
+ r = cols.slice(:indexes, :table_exists)
71
+ r[:add_attributes] = cols[:model_attributes].except *db.keys
72
+ r[:add_references] = cols[:model_references].except *db.keys
73
+ r[:timestamps] = ['created_at', 'updated_at'] & r[:add_attributes].keys
74
+ r[:remove_attributes] = db.except(*cols[:model_attributes].keys, *cols[:belongs_attributes].keys, *cols[:model_defaults])
75
+
76
+ tables[table_name] = r unless r[:add_attributes].blank? && r[:add_references].blank? && r[:remove_attributes].blank?
77
+ end
78
+
79
+ tables
80
+ end
81
+
82
+ def migrate_modules_hash
83
+ @modules = {}
84
+
85
+ models.group_by(&:module_parent).each do |module_name, record_classes|
86
+ new_prefix = (module_name.respond_to?(:table_name_prefix) && module_name.table_name_prefix) || ''
87
+ old_prefix = (module_name.respond_to?(:old_table_name_prefix) && module_name.old_table_name_prefix) || ''
88
+
89
+ record_classes.each do |record_class|
90
+ unless record_class.table_exists?
91
+ possible = record_class.table_name.sub(/^#{new_prefix}/, old_prefix)
92
+ @modules.merge! record_class.table_name => possible if tables.any?(possible)
93
+ end
94
+ end
95
+ end
96
+
97
+ arr = @modules.values
98
+ result = arr.find_all { |e| arr.rindex(e) != arr.index(e) }
99
+ warn "Please check #{result}"
100
+
101
+ @modules
102
+ end
103
+
104
+ def unbound_tables
105
+ tables - models.map(&:table_name) - ['schema_migrations', 'ar_internal_metadata']
106
+ end
107
+
108
+ def ignore_models
109
+ models.group_by(&->(i){ i.attributes_to_define_after_schema_loads.size }).transform_values!(&->(i) { i.map(&:to_s) })
110
+ end
111
+
112
+ def tables
113
+ ActiveRecord::Base.connection.tables
114
+ end
115
+
116
+ def model_names
117
+ models.map(&:to_s)
118
+ end
119
+
120
+ end
@@ -0,0 +1,22 @@
1
+ module RailsExtend
2
+ class QuietLogs
3
+
4
+ def initialize(app)
5
+ @app = app
6
+ @assets_regex = %r(\A/{0,2}(#{RailsExtend.config.quiet_logs.join('|')}))
7
+ end
8
+
9
+ def call(env)
10
+ if env['PATH_INFO'] =~ @assets_regex
11
+ Rails.logger.debug "Silenced: #{env['PATH_INFO']}"
12
+ Rails.logger.silence { @app.call(env) }
13
+ else
14
+ unless Rails.env.development?
15
+ Rails.logger.debug "\e[33m #{'- ~ ' * 40}- \e[0m"
16
+ end
17
+ @app.call(env)
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsExtend::Routes
4
+ extend self
5
+
6
+ def verbs(controller, action)
7
+ routes_wrapper.select { |i| i[:controller] == controller.to_s && i[:action] == action.to_s }.map { |i| i[:verb] }.uniq
8
+ end
9
+
10
+ def actions(cached = true)
11
+ return @actions if cached && defined? @actions
12
+
13
+ @actions = routes_wrapper(cached).group_by(&->(i){ i[:business] }).transform_values! do |businesses|
14
+ businesses.group_by(&->(i){ i[:namespace] }).transform_values! do |namespaces|
15
+ namespaces.group_by(&->(i){ i[:controller] }).transform_values! do |controllers|
16
+ controllers.each_with_object({}) { |i, h| h.merge! i[:action] => i }
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ def controllers(cached = true)
23
+ return @controllers if cached && defined? @controllers
24
+
25
+ @controllers = routes_wrapper(cached).group_by(&->(i){ i[:controller] }).transform_values! do |controllers|
26
+ controllers.each_with_object({}) { |i, h| h.merge! i[:action] => i }
27
+ end
28
+ end
29
+
30
+ def controller_paths(cached = true)
31
+ return @controller_paths if cached && defined? @controller_paths
32
+
33
+ @controller_paths = routes_wrapper(cached).group_by(&->(i){ i[:controller] }).transform_values! do |controllers|
34
+ controllers[0].slice(:business, :namespace)
35
+ end
36
+ end
37
+
38
+ def businesses(cached = true)
39
+ return @businesses if cached && defined? @businesses
40
+
41
+ @businesses = routes_wrapper(cached).group_by(&->(i){ i[:business] })
42
+ end
43
+
44
+ def namespaces(cached = true)
45
+ return @namespaces if cached && defined? @namespaces
46
+
47
+ @namespaces = routes_wrapper(cached).group_by(&->(i){ i[:namespace] })
48
+ end
49
+
50
+ def routes_wrapper(cached = true)
51
+ return @routes_wrapper if cached && defined?(@routes_wrapper)
52
+
53
+ @routes_wrapper = Rails.application.routes.routes.map do |route|
54
+ next if (route.defaults[:controller].blank? || route.defaults[:action].blank?)
55
+ detail(route)
56
+ end.compact
57
+ end
58
+
59
+ def blank_routes_wrapper(cached = true)
60
+ return @blank_routes_wrapper if cached && defined?(@blank_routes_wrapper)
61
+
62
+ @blank_routes_wrapper = Rails.application.routes.routes.map do |route|
63
+ next unless (route.defaults[:controller].blank? || route.defaults[:action].blank?)
64
+ detail(route)
65
+ end.compact
66
+ end
67
+
68
+ private
69
+ def detail(route)
70
+ {
71
+ verb: route.verb,
72
+ path: route.path.spec.to_s,
73
+ namespace: route.defaults[:namespace].to_s,
74
+ business: route.defaults[:business].to_s,
75
+ controller: route.defaults[:controller],
76
+ action: route.defaults[:action],
77
+ required_parts: route.required_parts
78
+ }
79
+ end
80
+
81
+ end
@@ -0,0 +1,23 @@
1
+ module ActiveRecord::Type
2
+ class I18n < Json
3
+
4
+ def type
5
+ :i18n
6
+ end
7
+
8
+ def deserialize(value)
9
+ if super && super.respond_to?(:[])
10
+ super[::I18n.locale.to_s]
11
+ else
12
+ value
13
+ end
14
+ end
15
+
16
+ def migrate_type
17
+ :json
18
+ end
19
+
20
+ end
21
+ end
22
+
23
+ ActiveRecord::Type.register(:i18n, ActiveRecord::Type::I18n)
@@ -0,0 +1,15 @@
1
+ module ActiveRecord::Type
2
+ class Taxon < Json
3
+
4
+ def input_type
5
+ :taxon
6
+ end
7
+
8
+ def migrate_type
9
+ :json
10
+ end
11
+
12
+ end
13
+ end
14
+
15
+ ActiveRecord::Type.register(:taxon, ActiveRecord::Type::Taxon)
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_extend/type/i18n'
4
+ require 'rails_extend/type/taxon'
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_extend/config'
4
+ require 'rails_extend/engine'
5
+
6
+ require 'rails_extend/core'
7
+
8
+ require 'rails_extend/active_model'
9
+ require 'rails_extend/active_record'
10
+ require 'rails_extend/active_storage'
11
+ require 'rails_extend/type' # 支持的 attribute type 扩展
12
+ require 'rails_extend/generators'
13
+
14
+ # Meta for Rails
15
+ require 'rails_extend/routes'
16
+ require 'rails_extend/models'
17
+ require 'rails_extend/env'
18
+
19
+ require 'rails_extend/quiet_logs'
@@ -0,0 +1,15 @@
1
+ <% ['one', 'two'].each do |name| -%>
2
+ <%= name %>:
3
+ <% attributes.each do |attribute| -%>
4
+ <%- if attribute.password_digest? -%>
5
+ password_digest: <%%= BCrypt::Password.create('secret') %>
6
+ <%- elsif attribute.reference? -%>
7
+ <%= yaml_key_value(attribute.column_name.delete_suffix("_id"), attribute.default || name) %>
8
+ <%- elsif !attribute.virtual? -%>
9
+ <%= yaml_key_value(attribute.column_name, attribute.default) %>
10
+ <%- end -%>
11
+ <%- if attribute.polymorphic? -%>
12
+ <%= yaml_key_value("#{attribute.name}_type", attribute.human_name) %>
13
+ <%- end -%>
14
+ <% end -%>
15
+ <% end -%>
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ <% module_namespacing do -%>
4
+ class <%= class_name %>Test < ActiveSupport::TestCase
5
+
6
+ end
7
+ <% end -%>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_extend
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - qinmingyuan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-06 00:00:00.000000000 Z
11
+ date: 2021-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '6.1'
19
+ version: '5.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '6.1'
26
+ version: '5.0'
27
27
  description: Common utils for Rails Application
28
28
  email:
29
29
  - mingyuan0715@foxmail.com
@@ -31,7 +31,58 @@ executables: []
31
31
  extensions: []
32
32
  extra_rdoc_files: []
33
33
  files:
34
- - lib/active_model/type_value.rb
34
+ - LICENSE
35
+ - README.md
36
+ - config/locales/en.datetime.yml
37
+ - config/locales/zh.datetime.yml
38
+ - config/locales/zh.support.yml
39
+ - lib/generators/rails_extend/ignore_generator.rb
40
+ - lib/generators/rails_extend/migrations_generator.rb
41
+ - lib/generators/rails_extend/remove_table_generator.rb
42
+ - lib/generators/rails_extend/rename_module_generator.rb
43
+ - lib/generators/rails_extend/templates/README.md
44
+ - lib/generators/rails_extend/templates/initializer.rb.tt
45
+ - lib/generators/rails_extend/templates/migration.rb.tt
46
+ - lib/generators/rails_extend/templates/remove_table.rb.tt
47
+ - lib/generators/rails_extend/templates/rename_module.rb.tt
48
+ - lib/rails_extend.rb
49
+ - lib/rails_extend/active_model.rb
50
+ - lib/rails_extend/active_model/type_value.rb
51
+ - lib/rails_extend/active_record.rb
52
+ - lib/rails_extend/active_record/enum.rb
53
+ - lib/rails_extend/active_record/extend.rb
54
+ - lib/rails_extend/active_record/i18n.rb
55
+ - lib/rails_extend/active_record/include.rb
56
+ - lib/rails_extend/active_record/taxon.rb
57
+ - lib/rails_extend/active_record/translation.rb
58
+ - lib/rails_extend/active_storage.rb
59
+ - lib/rails_extend/active_storage/attachment.rb
60
+ - lib/rails_extend/active_storage/blob_prepend.rb
61
+ - lib/rails_extend/active_storage/variant.rb
62
+ - lib/rails_extend/config.rb
63
+ - lib/rails_extend/core.rb
64
+ - lib/rails_extend/core/array.rb
65
+ - lib/rails_extend/core/date.rb
66
+ - lib/rails_extend/core/duration.rb
67
+ - lib/rails_extend/core/hash.rb
68
+ - lib/rails_extend/core/module.rb
69
+ - lib/rails_extend/core/nil.rb
70
+ - lib/rails_extend/core/numeric.rb
71
+ - lib/rails_extend/core/pathname.rb
72
+ - lib/rails_extend/core/string.rb
73
+ - lib/rails_extend/core/time_format.rb
74
+ - lib/rails_extend/engine.rb
75
+ - lib/rails_extend/env.rb
76
+ - lib/rails_extend/generators.rb
77
+ - lib/rails_extend/generators/named_base.rb
78
+ - lib/rails_extend/models.rb
79
+ - lib/rails_extend/quiet_logs.rb
80
+ - lib/rails_extend/routes.rb
81
+ - lib/rails_extend/type.rb
82
+ - lib/rails_extend/type/i18n.rb
83
+ - lib/rails_extend/type/taxon.rb
84
+ - lib/templates/test_unit/model/fixtures.yml.tt
85
+ - lib/templates/test_unit/model/unit_test.rb.tt
35
86
  homepage: https://github.com/work-design/rails_extend
36
87
  licenses:
37
88
  - MIT
@@ -1,20 +0,0 @@
1
- require 'active_model/type/value'
2
- module RailsCom
3
- module ActiveModel
4
- module TypeValue
5
- attr_reader :options
6
-
7
- def initialize(precision: nil, limit: nil, scale: nil, **options)
8
- @options = options
9
- super(precision: precision, limit: scale, scale: limit)
10
- end
11
-
12
- def input_type
13
- type
14
- end
15
-
16
- end
17
- end
18
- end
19
-
20
- ActiveModel::Type::Value.prepend RailsCom::ActiveModel::TypeValue