upgrow 0.0.4 → 0.0.5
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.
- checksums.yaml +4 -4
- data/lib/generators/test_unit/input/input_generator.rb +22 -0
- data/lib/generators/test_unit/input/templates/input_test.rb.tt +8 -0
- data/lib/generators/test_unit/install/install_generator.rb +48 -0
- data/lib/generators/test_unit/record/record_generator.rb +22 -0
- data/lib/generators/test_unit/record/templates/record_test.rb.tt +8 -0
- data/lib/generators/test_unit/repository/repository_generator.rb +23 -0
- data/lib/generators/test_unit/repository/templates/repository_test.rb.tt +8 -0
- data/lib/generators/upgrow.rb +54 -0
- data/lib/generators/upgrow/action/USAGE +13 -0
- data/lib/generators/upgrow/action/action_generator.rb +24 -0
- data/lib/generators/upgrow/action/templates/action.rb.tt +9 -0
- data/lib/generators/upgrow/input/USAGE +10 -0
- data/lib/generators/upgrow/input/input_generator.rb +26 -0
- data/lib/generators/upgrow/input/templates/input.rb.tt +6 -0
- data/lib/generators/upgrow/install/USAGE +25 -0
- data/lib/generators/upgrow/install/install_generator.rb +56 -0
- data/lib/generators/upgrow/install/templates/app/actions/application_action.rb.tt +4 -0
- data/lib/generators/upgrow/install/templates/app/inputs/application_input.rb.tt +4 -0
- data/lib/generators/upgrow/install/templates/app/models/application_model.rb.tt +4 -0
- data/lib/generators/upgrow/install/templates/app/repositories/application_repository.rb.tt +4 -0
- data/lib/generators/upgrow/model/USAGE +10 -0
- data/lib/generators/upgrow/model/model_generator.rb +24 -0
- data/lib/generators/upgrow/model/templates/model.rb.tt +6 -0
- data/lib/generators/upgrow/record/record_generator.rb +34 -0
- data/lib/generators/upgrow/record/templates/record.rb.tt +6 -0
- data/lib/generators/upgrow/repository/USAGE +10 -0
- data/lib/generators/upgrow/repository/repository_generator.rb +27 -0
- data/lib/generators/upgrow/repository/templates/repository.rb.tt +6 -0
- data/lib/upgrow.rb +3 -0
- data/lib/upgrow/active_record_conversion.rb +2 -3
- data/lib/upgrow/active_record_queries.rb +1 -2
- data/lib/upgrow/active_record_schema.rb +1 -3
- data/lib/upgrow/basic_model.rb +11 -0
- data/lib/upgrow/model.rb +2 -1
- data/lib/upgrow/naming.rb +40 -0
- data/lib/upgrow/railtie.rb +9 -0
- data/lib/upgrow/record.rb +121 -0
- data/test/dummy/app/records/application_record.rb +2 -0
- data/test/dummy/app/records/article_record.rb +2 -3
- data/test/dummy/app/records/comment_record.rb +2 -3
- data/test/dummy/app/records/user_record.rb +2 -4
- data/test/dummy/app/repositories/article_repository.rb +3 -3
- data/test/test_unit/generators/input_generator_test.rb +56 -0
- data/test/test_unit/generators/install_generator_test.rb +138 -0
- data/test/test_unit/generators/record_generator_test.rb +56 -0
- data/test/test_unit/generators/repository_generator_test.rb +57 -0
- data/test/upgrow/active_record_conversion_test.rb +2 -2
- data/test/upgrow/active_record_schema_test.rb +1 -1
- data/test/upgrow/basic_model_test.rb +85 -0
- data/test/upgrow/generators/action_generator_test.rb +59 -0
- data/test/upgrow/generators/helper_test.rb +86 -0
- data/test/upgrow/generators/input_generator_test.rb +65 -0
- data/test/upgrow/generators/install_generator_test.rb +158 -0
- data/test/upgrow/generators/model_generator_test.rb +39 -0
- data/test/upgrow/generators/record_generator_test.rb +65 -0
- data/test/upgrow/generators/repository_generator_test.rb +50 -0
- data/test/upgrow/naming_test.rb +22 -0
- data/test/upgrow/record_test.rb +176 -0
- metadata +60 -3
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'generators/upgrow'
|
4
|
+
|
5
|
+
module Upgrow
|
6
|
+
module Generators
|
7
|
+
class RecordGenerator < Rails::Generators::NamedBase
|
8
|
+
include Helper
|
9
|
+
|
10
|
+
def create_record_file
|
11
|
+
template(
|
12
|
+
'record.rb',
|
13
|
+
File.join('app/records', class_path, "#{file_name}_record.rb")
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
hook_for :migration,
|
18
|
+
default: :active_record,
|
19
|
+
as: :migration do |instance, generator|
|
20
|
+
instance.invoke(
|
21
|
+
generator, ["create_#{instance.send(:table_name)}", instance.args]
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
hook_for :test_framework
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def file_name
|
30
|
+
super.delete_suffix('_record')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'generators/upgrow'
|
4
|
+
|
5
|
+
module Upgrow
|
6
|
+
module Generators
|
7
|
+
class RepositoryGenerator < Rails::Generators::NamedBase
|
8
|
+
include Helper
|
9
|
+
|
10
|
+
def create_repository_file
|
11
|
+
template(
|
12
|
+
'repository.rb',
|
13
|
+
File.join('app/repositories', class_path,
|
14
|
+
"#{file_name}_repository.rb")
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
hook_for :test_framework
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def file_name
|
23
|
+
super.delete_suffix('_repository')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/upgrow.rb
CHANGED
@@ -4,8 +4,11 @@ require_relative 'upgrow/action'
|
|
4
4
|
require_relative 'upgrow/actions'
|
5
5
|
require_relative 'upgrow/input'
|
6
6
|
require_relative 'upgrow/model'
|
7
|
+
require_relative 'upgrow/record'
|
7
8
|
require_relative 'upgrow/repository'
|
8
9
|
|
10
|
+
require 'upgrow/railtie' if defined?(Rails::Railtie)
|
11
|
+
|
9
12
|
# The gem's main namespace.
|
10
13
|
module Upgrow
|
11
14
|
end
|
@@ -29,11 +29,10 @@ module Upgrow
|
|
29
29
|
association = record.association(reflection.to_sym)
|
30
30
|
next unless association.loaded?
|
31
31
|
|
32
|
-
|
33
|
-
[name, to_model(record.public_send(reflection))]
|
32
|
+
[reflection.to_sym, to_model(record.public_send(reflection))]
|
34
33
|
end.compact.to_h
|
35
34
|
|
36
|
-
model_class = Object.const_get(record.class.name
|
35
|
+
model_class = Object.const_get(Naming.record_to_model(record.class.name))
|
37
36
|
|
38
37
|
attributes = record.attributes.merge(associations)
|
39
38
|
|
@@ -19,8 +19,7 @@ module Upgrow
|
|
19
19
|
# @return [Class] the Active Record Base class to be used as the
|
20
20
|
# Repository base according to the architecture's naming convention.
|
21
21
|
def default_base
|
22
|
-
|
23
|
-
Object.const_get(base_name)
|
22
|
+
Object.const_get(Naming.repository_to_record(name))
|
24
23
|
end
|
25
24
|
end
|
26
25
|
|
@@ -47,9 +47,7 @@ module Upgrow
|
|
47
47
|
#
|
48
48
|
# @return [Array<Symbol>] the list of attribute names.
|
49
49
|
def association_names
|
50
|
-
association_names = base.reflections.keys.map
|
51
|
-
key.sub('_record', '').to_sym
|
52
|
-
end
|
50
|
+
association_names = base.reflections.keys.map(&:to_sym)
|
53
51
|
|
54
52
|
association_names | @default_schema.association_names
|
55
53
|
end
|
data/lib/upgrow/basic_model.rb
CHANGED
@@ -50,6 +50,17 @@ module Upgrow
|
|
50
50
|
super(**attributes)
|
51
51
|
end
|
52
52
|
|
53
|
+
# Returns a Hash representation of Model along with all loaded associations.
|
54
|
+
#
|
55
|
+
# @return [Hash<Symbol, Object>] the list of attribute names
|
56
|
+
# and associations, if loaded.
|
57
|
+
def to_h
|
58
|
+
associations_hash = associations.compact.transform_values do |models|
|
59
|
+
models.respond_to?(:map) ? models.map(&:to_h) : models.to_h
|
60
|
+
end
|
61
|
+
attributes.merge(associations_hash)
|
62
|
+
end
|
63
|
+
|
53
64
|
private
|
54
65
|
|
55
66
|
def method_missing(name, *args, &block)
|
data/lib/upgrow/model.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative 'active_record_schema'
|
4
4
|
require_relative 'basic_model'
|
5
|
+
require_relative 'naming'
|
5
6
|
|
6
7
|
module Upgrow
|
7
8
|
# Models are objects that represent core entities of the app's business logic.
|
@@ -27,7 +28,7 @@ module Upgrow
|
|
27
28
|
super
|
28
29
|
|
29
30
|
subclass.schema = ActiveRecordSchema.new(
|
30
|
-
|
31
|
+
Naming.model_to_record(subclass.name), subclass.schema
|
31
32
|
)
|
32
33
|
end
|
33
34
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Upgrow
|
4
|
+
# Functions to derive constant names and other identifiers according to
|
5
|
+
# Upgrow's conventions.
|
6
|
+
module Naming
|
7
|
+
extend self
|
8
|
+
|
9
|
+
# Convert a Model name to a Record name. The Record name by convention is
|
10
|
+
# the Model name with a `Record` suffix.
|
11
|
+
#
|
12
|
+
# @param model_name [String] the Model name.
|
13
|
+
#
|
14
|
+
# @return [String] the Record name.
|
15
|
+
def model_to_record(model_name)
|
16
|
+
"#{model_name}Record"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Convert a Record name to a Model name. The Model name by convention is the
|
20
|
+
# Record name without the `Record` suffix.
|
21
|
+
#
|
22
|
+
# @param record_name [String] the Record name.
|
23
|
+
#
|
24
|
+
# @return [String] the Model name.
|
25
|
+
def record_to_model(record_name)
|
26
|
+
record_name.delete_suffix('Record')
|
27
|
+
end
|
28
|
+
|
29
|
+
# Convert a Repository name to a Record name. The Record name is inferred by
|
30
|
+
# the Repository name without the `Repository` suffix, and with the `Record`
|
31
|
+
# suffix added.
|
32
|
+
#
|
33
|
+
# @param repository_name [String] the Repository name.
|
34
|
+
#
|
35
|
+
# @return [String] the Record name.
|
36
|
+
def repository_to_record(repository_name)
|
37
|
+
"#{repository_name.delete_suffix("Repository")}Record"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Upgrow
|
4
|
+
# Upgrow's Railtie. This class allows Upgrow to change Rails' default configs.
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
config.app_generators.orm(:upgrow)
|
7
|
+
config.app_generators.fallbacks[:upgrow] = :active_record
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Upgrow
|
4
|
+
# Utility mixin to help adjust Active Record Base classes according to
|
5
|
+
# Upgrow's conventions. It allows the use of the `Record` suffix in class
|
6
|
+
# naming while keeping it out of table and association names, among other
|
7
|
+
# adaptations.
|
8
|
+
module Record
|
9
|
+
# Class methods to be extended by the class that includes the Record module.
|
10
|
+
module ClassMethods
|
11
|
+
# Overwrites the table name reader from ActiveRecord::ModelSchema,
|
12
|
+
# removing the `records` suffix by default while still allowing table name
|
13
|
+
# to be set explicitly.
|
14
|
+
#
|
15
|
+
# See https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema/ClassMethods.html
|
16
|
+
def table_name
|
17
|
+
return @table_name if defined?(@table_name)
|
18
|
+
|
19
|
+
self.table_name = super&.sub('_record', '')
|
20
|
+
end
|
21
|
+
|
22
|
+
# Overwrites the has many association macro to adjust the default class
|
23
|
+
# and foreign key names to Upgrow's conventions.
|
24
|
+
#
|
25
|
+
# The default class name for the associated collection of Records is based
|
26
|
+
# on the association name and the `Record` suffix. The association's
|
27
|
+
# foreign key is derived from the caller's model name.
|
28
|
+
#
|
29
|
+
# All these values can be set explicitly according to Active Record's
|
30
|
+
# original behaviour.
|
31
|
+
#
|
32
|
+
# See https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
|
33
|
+
def has_many(name, scope = nil, **options, &extension)
|
34
|
+
options = apply_default_options(name, options)
|
35
|
+
|
36
|
+
unless options.key?(:as)
|
37
|
+
options[:foreign_key] ||= foreign_key(model_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
# Overwrites the has one association macro to adjust the default class
|
44
|
+
# and foreign key names to Upgrow's conventions.
|
45
|
+
#
|
46
|
+
# The default class name for the associated Record is based on the
|
47
|
+
# association name and the `Record` suffix. The association's foreign key
|
48
|
+
# is derived from the caller's model name.
|
49
|
+
#
|
50
|
+
# All these values can be set explicitly according to Active Record's
|
51
|
+
# original behaviour.
|
52
|
+
#
|
53
|
+
# See https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
|
54
|
+
def has_one(name, scope = nil, **options, &extension)
|
55
|
+
options = apply_default_options(name, options)
|
56
|
+
|
57
|
+
unless options.key?(:as)
|
58
|
+
options[:foreign_key] ||= foreign_key(model_name)
|
59
|
+
end
|
60
|
+
|
61
|
+
super
|
62
|
+
end
|
63
|
+
|
64
|
+
# Overwrites the belongs to association macro to adjust the default class
|
65
|
+
# and foreign key names to Upgrow's conventions.
|
66
|
+
#
|
67
|
+
# The default class name for the associated Record is based on the
|
68
|
+
# association name and the `Record` suffix.
|
69
|
+
#
|
70
|
+
# All these values can be set explicitly according to Active Record's
|
71
|
+
# original behaviour.
|
72
|
+
#
|
73
|
+
# See https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
|
74
|
+
def belongs_to(name, scope = nil, **options)
|
75
|
+
options = apply_default_options(name, options)
|
76
|
+
super
|
77
|
+
end
|
78
|
+
|
79
|
+
# Overwrites the has and belongs to many association macro to adjust the
|
80
|
+
# default class and foreign key names to Upgrow's conventions.
|
81
|
+
#
|
82
|
+
# The default class name for the associated Record is based on the
|
83
|
+
# association name and the `Record` suffix. The association's foreign key
|
84
|
+
# is derived from the caller's model name.
|
85
|
+
#
|
86
|
+
# All these values can be set explicitly according to Active Record's
|
87
|
+
# original behaviour.
|
88
|
+
#
|
89
|
+
# See https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
|
90
|
+
def has_and_belongs_to_many(name, scope = nil, **options, &extension)
|
91
|
+
options = apply_default_options(name, options)
|
92
|
+
|
93
|
+
options[:foreign_key] ||= foreign_key(model_name)
|
94
|
+
|
95
|
+
options[:association_foreign_key] ||=
|
96
|
+
foreign_key(options.fetch(:class_name))
|
97
|
+
|
98
|
+
super
|
99
|
+
end
|
100
|
+
|
101
|
+
# @private
|
102
|
+
def apply_default_options(name, options)
|
103
|
+
default_options = {
|
104
|
+
class_name: Naming.model_to_record(name.to_s.singularize.camelize),
|
105
|
+
}
|
106
|
+
|
107
|
+
default_options.merge(options)
|
108
|
+
end
|
109
|
+
|
110
|
+
# @private
|
111
|
+
def foreign_key(record_name)
|
112
|
+
Naming.record_to_model(record_name.to_s).foreign_key
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# @private
|
117
|
+
def self.included(base)
|
118
|
+
base.extend(ClassMethods)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class ArticleRecord < ApplicationRecord
|
4
|
-
|
5
|
-
|
6
|
-
belongs_to :user_record, foreign_key: :user_id
|
4
|
+
has_many :comments, dependent: :destroy
|
5
|
+
belongs_to :user
|
7
6
|
end
|
@@ -1,10 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class UserRecord < ApplicationRecord
|
4
|
-
self.table_name = 'users'
|
5
|
-
|
6
4
|
has_secure_password
|
7
5
|
|
8
|
-
has_many :
|
9
|
-
has_many :
|
6
|
+
has_many :articles, dependent: :destroy
|
7
|
+
has_many :comments, dependent: :destroy
|
10
8
|
end
|
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
class ArticleRepository < Upgrow::Repository
|
4
4
|
def all
|
5
|
-
to_model(base.all.includes(:
|
5
|
+
to_model(base.all.includes(:user))
|
6
6
|
end
|
7
7
|
|
8
8
|
def find_with_comments(id)
|
9
9
|
record = base
|
10
|
-
.includes(:
|
11
|
-
.includes(
|
10
|
+
.includes(:user)
|
11
|
+
.includes(comments: :user)
|
12
12
|
.find(id)
|
13
13
|
|
14
14
|
to_model(record)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
require 'rails/generators/test_case'
|
5
|
+
require 'generators/test_unit/input/input_generator'
|
6
|
+
|
7
|
+
module TestUnit
|
8
|
+
module Generators
|
9
|
+
class InputGeneratorTest < Rails::Generators::TestCase
|
10
|
+
tests InputGenerator
|
11
|
+
destination File.expand_path('tmp')
|
12
|
+
setup :prepare_destination
|
13
|
+
|
14
|
+
test 'generate Input test file' do
|
15
|
+
run_generator(['article'])
|
16
|
+
|
17
|
+
assert_file 'test/inputs/article_input_test.rb', <<~RUBY
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
require 'test_helper'
|
21
|
+
|
22
|
+
class ArticleInputTest < ActiveSupport::TestCase
|
23
|
+
end
|
24
|
+
RUBY
|
25
|
+
end
|
26
|
+
|
27
|
+
test 'generate Input test file when suffix is specified' do
|
28
|
+
run_generator(['ArticleInput'])
|
29
|
+
|
30
|
+
assert_file 'test/inputs/article_input_test.rb', <<~RUBY
|
31
|
+
# frozen_string_literal: true
|
32
|
+
|
33
|
+
require 'test_helper'
|
34
|
+
|
35
|
+
class ArticleInputTest < ActiveSupport::TestCase
|
36
|
+
end
|
37
|
+
RUBY
|
38
|
+
end
|
39
|
+
|
40
|
+
test 'generate namespaced Input test file' do
|
41
|
+
run_generator(['articles/article'])
|
42
|
+
|
43
|
+
assert_file 'test/inputs/articles/article_input_test.rb', <<~RUBY
|
44
|
+
# frozen_string_literal: true
|
45
|
+
|
46
|
+
require 'test_helper'
|
47
|
+
|
48
|
+
module Articles
|
49
|
+
class ArticleInputTest < ActiveSupport::TestCase
|
50
|
+
end
|
51
|
+
end
|
52
|
+
RUBY
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|