rails_extend 1.0.0 → 1.0.1

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