api_scaffolding 1.0.2
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 +7 -0
- data/README.md +83 -0
- data/lib/api_scaffolding/configuration.rb +49 -0
- data/lib/api_scaffolding.rb +4 -0
- data/lib/generators/api_scaffold/api_scaffold_generator.rb +23 -0
- data/lib/generators/api_scaffold/controller_generator.rb +42 -0
- data/lib/generators/api_scaffold/entity_generator.rb +88 -0
- data/lib/generators/api_scaffold/helper.rb +48 -0
- data/lib/generators/api_scaffold/install_generator.rb +12 -0
- data/lib/generators/api_scaffold/modify_api_root_generator.rb +93 -0
- data/lib/generators/api_scaffold/params_concern_generator.rb +64 -0
- data/lib/generators/templates/api_controller.rb.tt +141 -0
- data/lib/generators/templates/config_initializer.rb.tt +46 -0
- data/lib/generators/templates/entity.rb.tt +15 -0
- data/lib/generators/templates/params_concern.rb.tt +18 -0
- metadata +113 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 18212ce104518b32a3b4b252161d47c91501e599a7982a704b573fa6745bab24
|
|
4
|
+
data.tar.gz: aa0a3d7c1ddd955e586dd4248f010c3465a00176e37d0c5a7d38d94e2f624480
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ff92cd603d95135cddce3443c0e9a0c0dd0554656aed89586b8d0c56201f9bcb2b3f1d621149524e293b01290006eac81696f8abd9cf15d537a268e509cd93c9
|
|
7
|
+
data.tar.gz: be967475a4cf3768f9d106824ce624a4a8132bdc01bf81b1ff35e2e6842ee1801da42d5c9e17b9df796ab216a6c5324482d3e257103b926f113f91ef31d3ce90
|
data/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# API Scaffolding
|
|
2
|
+
|
|
3
|
+
Генерация контроллеров API и модулей с параметрами Grape и Grape Entity.
|
|
4
|
+
|
|
5
|
+
## Установка
|
|
6
|
+
|
|
7
|
+
Добавить в Gemfile
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
group :development do
|
|
11
|
+
gem 'api_scaffolding'
|
|
12
|
+
end
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
И выполнить:
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
bundle
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Конфигурация
|
|
22
|
+
|
|
23
|
+
Для создания файла конфигурации выполнить:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
rails g api_scaffold:install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
И отредактировать созданный файл `config/initializers/api_scaffold.rb`
|
|
30
|
+
|
|
31
|
+
## Использование
|
|
32
|
+
|
|
33
|
+
Сгенерировать класс контроллера API, модуль с параметрами и файл сериалайзера:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
rails g api_scaffold Model
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Опции:
|
|
40
|
+
|
|
41
|
+
`--api_version` - версия API, по умолчанию отсутствует
|
|
42
|
+
|
|
43
|
+
`--no_params` - не создавать модуль с параметрами, по умолчанию - создается
|
|
44
|
+
|
|
45
|
+
`--no_entity` - не создавать класс с Grape Entity, по умолчанию - создается
|
|
46
|
+
|
|
47
|
+
#### Сгенерировать класс контроллера API отдельно:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
rails g api_scaffold:controller Model
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Опции:
|
|
54
|
+
|
|
55
|
+
`--api_version` - версия API, по умолчанию отсутствует
|
|
56
|
+
|
|
57
|
+
`--no_params` - не указывать в контроллере модуль с параметрами, по умолчанию - указывается
|
|
58
|
+
|
|
59
|
+
`--no_entity` - не указывать в контроллере класс с Grape Entity, по умолчанию - указывается
|
|
60
|
+
|
|
61
|
+
#### Сгенерировать модуль с параметрами отдельно:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
rails g api_scaffold:params_concern Model
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Опции:
|
|
68
|
+
|
|
69
|
+
`--api_version` - версия API, по умолчанию отсутствует
|
|
70
|
+
|
|
71
|
+
#### Сгенерировать Grape Entity отдельно:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
rails g api_scaffold:entity Model
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Опции:
|
|
78
|
+
|
|
79
|
+
`--api_version` - версия API, по умолчанию отсутствует
|
|
80
|
+
|
|
81
|
+
## Примечания
|
|
82
|
+
|
|
83
|
+
- При добавлении описаний методов API и параметров используются описания таблиц и их колонок в БД.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module ApiScaffolding
|
|
2
|
+
class Configuration
|
|
3
|
+
|
|
4
|
+
attr_accessor :default_api_version,
|
|
5
|
+
:api_version_modules,
|
|
6
|
+
:pagination_list_content,
|
|
7
|
+
:params_fields_exclusions,
|
|
8
|
+
:entity_fields_exclusions,
|
|
9
|
+
:abilities_check,
|
|
10
|
+
:abilities_authorize_opts
|
|
11
|
+
|
|
12
|
+
def default_api_version
|
|
13
|
+
@default_api_version || ''
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def api_version_modules
|
|
17
|
+
@api_version_modules || {}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def pagination_list_content
|
|
21
|
+
@pagination_list_content || proc {}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def params_fields_exclusions
|
|
25
|
+
@params_fields_exclusions || %w[id created_at updated_at]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def entity_fields_exclusions
|
|
29
|
+
@entity_fields_exclusions || []
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def abilities_check
|
|
33
|
+
@abilities_check || false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def abilities_authorize_opts
|
|
37
|
+
@abilities_authorize_opts || ''
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.configure
|
|
42
|
+
yield(config)
|
|
43
|
+
config
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.config
|
|
47
|
+
@config ||= Configuration.new
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module ApiScaffold
|
|
2
|
+
module Generators
|
|
3
|
+
class ApiScaffoldGenerator < Rails::Generators::NamedBase
|
|
4
|
+
|
|
5
|
+
class_option :api_version, type: :string, default: ApiScaffolding.config.default_api_version
|
|
6
|
+
class_option :entity_dir, type: :string, default: nil
|
|
7
|
+
class_option :no_params, type: :boolean, default: false
|
|
8
|
+
class_option :no_entity, type: :boolean, default: false
|
|
9
|
+
|
|
10
|
+
namespace 'api_scaffold'
|
|
11
|
+
|
|
12
|
+
source_root File.expand_path('../templates', __dir__)
|
|
13
|
+
|
|
14
|
+
def generate_files
|
|
15
|
+
generate "api_scaffold:entity #{class_name} --entity_dir=#{options['entity_dir']}"
|
|
16
|
+
generate "api_scaffold:params_concern #{class_name} --api_version=#{options['api_version']}"
|
|
17
|
+
generate "api_scaffold:controller #{class_name} --api_version=#{options['api_version']} --no_params=#{options['no_params']} --no_entity=#{options['no_entity']}"
|
|
18
|
+
generate "api_scaffold:modify_api_root #{class_name} --api_version=#{options['api_version']}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'generators/api_scaffold/helper'
|
|
2
|
+
|
|
3
|
+
module ApiScaffold
|
|
4
|
+
module Generators
|
|
5
|
+
class ControllerGenerator < Rails::Generators::NamedBase
|
|
6
|
+
|
|
7
|
+
include ApiScaffold::Generators::Helper
|
|
8
|
+
|
|
9
|
+
class_option :api_version, type: :string, default: ApiScaffolding.config.default_api_version
|
|
10
|
+
class_option :no_params, type: :boolean, default: false
|
|
11
|
+
class_option :no_entity, type: :boolean, default: false
|
|
12
|
+
|
|
13
|
+
source_root File.expand_path('../templates', __dir__)
|
|
14
|
+
|
|
15
|
+
def create_api_controller_file
|
|
16
|
+
@no_params = options['no_params']
|
|
17
|
+
@abilities_check = ApiScaffolding.config.abilities_check
|
|
18
|
+
@no_entity = options['no_entity']
|
|
19
|
+
@restoration_required = model.column_names.include?('deleted_at')
|
|
20
|
+
|
|
21
|
+
dir_name = "app/controllers/api/#{options['api_version']}"
|
|
22
|
+
filename = "#{file_name.pluralize}.rb"
|
|
23
|
+
template 'api_controller.rb', File.join(dir_name, filename)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def abilities_authorize_content(action)
|
|
29
|
+
# базовые аргументы
|
|
30
|
+
args = [action, class_name]
|
|
31
|
+
|
|
32
|
+
# дополнительные аргументы
|
|
33
|
+
options = ApiScaffolding.config.abilities_authorize_opts
|
|
34
|
+
args << options if options
|
|
35
|
+
|
|
36
|
+
# содержимое
|
|
37
|
+
"authorize: #{args}".gsub('"', '')
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'generators/api_scaffold/helper'
|
|
2
|
+
require 'faker'
|
|
3
|
+
|
|
4
|
+
module ApiScaffold
|
|
5
|
+
module Generators
|
|
6
|
+
class EntityGenerator < Rails::Generators::NamedBase
|
|
7
|
+
|
|
8
|
+
include ApiScaffold::Generators::Helper
|
|
9
|
+
|
|
10
|
+
class_option :entity_dir, type: :string, default: nil
|
|
11
|
+
|
|
12
|
+
source_root File.expand_path('../templates', __dir__)
|
|
13
|
+
|
|
14
|
+
def create_entity_file
|
|
15
|
+
dir_name = 'app/entities'
|
|
16
|
+
filename = "#{file_name}_entity.rb"
|
|
17
|
+
|
|
18
|
+
if options['entity_dir'].present?
|
|
19
|
+
dir_name += "/#{options['entity_dir']}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
template 'entity.rb', File.join(dir_name, filename)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def entity_class_name
|
|
28
|
+
entity_module_with_prefix + entity_class
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def entity_module_with_prefix
|
|
32
|
+
dir = options['entity_dir']
|
|
33
|
+
value = ApiScaffolding.config.api_version_modules[dir]
|
|
34
|
+
return '' if dir.blank? || class_name.starts_with?(value)
|
|
35
|
+
|
|
36
|
+
"#{value}::"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def list_fields
|
|
40
|
+
# предполагается, что поля определенные поля должны быть на списке по умолчанию
|
|
41
|
+
model.columns.map do |column|
|
|
42
|
+
next if %w[name].exclude?(column.name)
|
|
43
|
+
|
|
44
|
+
entity_field(column)
|
|
45
|
+
end.compact.join(fields_separator)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def entry_fields
|
|
49
|
+
# обработка всех полей модели, кроме исключений
|
|
50
|
+
model.columns.map do |column|
|
|
51
|
+
next if ApiScaffolding.config.entity_fields_exclusions.include?(column.name)
|
|
52
|
+
|
|
53
|
+
entity_field(column)
|
|
54
|
+
end.compact.join(fields_separator)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def fields_separator
|
|
58
|
+
# разделение полей в генерируемом файле
|
|
59
|
+
"\n" + (' ' * 4)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def entity_field(column)
|
|
63
|
+
case column.type
|
|
64
|
+
when :string, :enum
|
|
65
|
+
"expose :#{column.name}"
|
|
66
|
+
when :integer
|
|
67
|
+
"expose :#{column.name}, documentation: { type: 'Integer' }"
|
|
68
|
+
when :float
|
|
69
|
+
"expose :#{column.name}, documentation: { type: 'Float' }"
|
|
70
|
+
when :decimal
|
|
71
|
+
"expose :#{column.name}, documentation: { type: 'Float', values: [#{decimal_example(column)}] }"
|
|
72
|
+
when :date
|
|
73
|
+
"expose :#{column.name}, documentation: { type: 'Date' }"
|
|
74
|
+
when :boolean
|
|
75
|
+
"expose :#{column.name}, documentation: { type: 'Boolean' }"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def decimal_example(column)
|
|
80
|
+
l_digits = column.precision - column.scale
|
|
81
|
+
r_digits = column.scale
|
|
82
|
+
|
|
83
|
+
Faker::Number.decimal(l_digits:, r_digits:)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module ApiScaffold
|
|
2
|
+
module Generators
|
|
3
|
+
module Helper
|
|
4
|
+
|
|
5
|
+
def api_version_module
|
|
6
|
+
@api_version_module ||=
|
|
7
|
+
ApiScaffolding.config.api_version_modules[options['api_version']] || options['api_version'].capitalize
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def api_version_module_with_prefix
|
|
11
|
+
api_version_module.present? ? "::#{api_version_module}" : ''
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def class_prefix
|
|
15
|
+
# проверяем наличие префикса у класса
|
|
16
|
+
if class_name.include?('::')
|
|
17
|
+
class_name.split('::')[0] + '::'
|
|
18
|
+
else
|
|
19
|
+
''
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def controller_class
|
|
24
|
+
class_name.gsub(class_prefix, '').pluralize
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def model
|
|
28
|
+
class_name.constantize
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def entity_class
|
|
32
|
+
"#{class_name}Entity"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def api_address
|
|
36
|
+
controller_class.underscore
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def api_description
|
|
40
|
+
@api_description ||=
|
|
41
|
+
ActiveRecord::Base.connection.execute(
|
|
42
|
+
"SELECT obj_description('public.#{model.table_name}'::regclass) as comment"
|
|
43
|
+
)[0]['comment'].force_encoding(Encoding::BINARY)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module ApiScaffold
|
|
2
|
+
module Generators
|
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
|
4
|
+
|
|
5
|
+
source_root File.expand_path('../templates', __dir__)
|
|
6
|
+
|
|
7
|
+
def copy_initializer
|
|
8
|
+
template 'config_initializer.rb', 'config/initializers/api_scaffold.rb'
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
require 'generators/api_scaffold/helper'
|
|
2
|
+
|
|
3
|
+
module ApiScaffold
|
|
4
|
+
module Generators
|
|
5
|
+
class ModifyApiRootGenerator < Rails::Generators::NamedBase
|
|
6
|
+
|
|
7
|
+
include ApiScaffold::Generators::Helper
|
|
8
|
+
|
|
9
|
+
class_option :api_version, type: :string, default: ApiScaffolding.config.default_api_version
|
|
10
|
+
|
|
11
|
+
def add_mount_line_to_api_root
|
|
12
|
+
# строка, которую нужно вставить
|
|
13
|
+
line = "mount API#{api_version_module_with_prefix}::#{controller_class}"
|
|
14
|
+
|
|
15
|
+
# шаблон для поиска в файле root
|
|
16
|
+
pattern = "mount API#{api_version_module_with_prefix}::"
|
|
17
|
+
|
|
18
|
+
# строка, после которой нужно вставить
|
|
19
|
+
sentinel = find_root_line(pattern, controller_class) || '# API'
|
|
20
|
+
regex = /(#{Regexp.escape(sentinel.force_encoding(Encoding::BINARY))})/mi
|
|
21
|
+
|
|
22
|
+
# вставка новой строки
|
|
23
|
+
tabs = "\n" + (' ' * 6)
|
|
24
|
+
modify_api_root(regex, tabs, line)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def add_swagger_line_to_api_root
|
|
28
|
+
# строка, которую нужно вставить
|
|
29
|
+
line = "{ name: '#{api_address}', title: '#{api_address}', description: '#{api_description}' },"
|
|
30
|
+
|
|
31
|
+
# шаблон для поиска в файле root
|
|
32
|
+
pattern = "{ name: '"
|
|
33
|
+
|
|
34
|
+
# строка, после которой нужно вставить
|
|
35
|
+
sentinel = find_root_line(pattern, api_address) || 'tags: ['
|
|
36
|
+
regex = /(#{Regexp.escape(sentinel.force_encoding(Encoding::BINARY))})/mi
|
|
37
|
+
|
|
38
|
+
# проверка на то, является вставляемая строка первой либо уже содержит запятую
|
|
39
|
+
# если нет - в конце предыдущей нужно поставить запятую
|
|
40
|
+
if sentinel != 'tags: [' && sentinel.last != ','
|
|
41
|
+
# вставка запятой на предыдущей строке
|
|
42
|
+
modify_api_root(regex, '', ',')
|
|
43
|
+
|
|
44
|
+
# изменение регулярного выражения предыдущей строки
|
|
45
|
+
sentinel += ','
|
|
46
|
+
regex = /(#{Regexp.escape(sentinel.force_encoding(Encoding::BINARY))})/mi
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# вставка новой строки
|
|
50
|
+
tabs = "\n" + (' ' * 10)
|
|
51
|
+
modify_api_root(regex, tabs, line)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def api_root_file
|
|
57
|
+
"app/controllers/api/#{options['api_version']}/root.rb"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def modify_api_root(regex, tabs, line)
|
|
61
|
+
in_root do
|
|
62
|
+
gsub_file(api_root_file, regex) do |match|
|
|
63
|
+
"#{match}#{tabs}#{line}"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def find_root_line(pattern, word)
|
|
69
|
+
# поиск строк соответствующих шаблону
|
|
70
|
+
found_lines =
|
|
71
|
+
File.foreach(api_root_file).map do |line|
|
|
72
|
+
line.strip.gsub(pattern, '') if line.include?(pattern)
|
|
73
|
+
end.compact
|
|
74
|
+
|
|
75
|
+
# добавление слова к найденным строкам для последующей сортировки
|
|
76
|
+
found_lines << word
|
|
77
|
+
|
|
78
|
+
# поиск строки, после которой нужно вставить строку
|
|
79
|
+
found_lines.sort.map.with_index do |el, index|
|
|
80
|
+
next if el != word
|
|
81
|
+
|
|
82
|
+
previous_line = found_lines[index - 1]
|
|
83
|
+
|
|
84
|
+
# условие, если строка должна быть первой
|
|
85
|
+
break if previous_line == word
|
|
86
|
+
|
|
87
|
+
pattern + previous_line
|
|
88
|
+
end.try(:compact)&.first
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'generators/api_scaffold/helper'
|
|
2
|
+
|
|
3
|
+
module ApiScaffold
|
|
4
|
+
module Generators
|
|
5
|
+
class ParamsConcernGenerator < Rails::Generators::NamedBase
|
|
6
|
+
|
|
7
|
+
include ApiScaffold::Generators::Helper
|
|
8
|
+
|
|
9
|
+
class_option :api_version, type: :string, default: ApiScaffolding.config.default_api_version
|
|
10
|
+
|
|
11
|
+
source_root File.expand_path('../templates', __dir__)
|
|
12
|
+
|
|
13
|
+
def create_params_concern_file
|
|
14
|
+
dir_name = "app/controllers/concerns/params/#{options['api_version']}"
|
|
15
|
+
filename = "#{file_name.pluralize}.rb"
|
|
16
|
+
template 'params_concern.rb', File.join(dir_name, filename)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def params_fields
|
|
22
|
+
exclusions = ApiScaffolding.config.params_fields_exclusions
|
|
23
|
+
|
|
24
|
+
model.columns.select do |column|
|
|
25
|
+
next if exclusions.include?(column.name)
|
|
26
|
+
|
|
27
|
+
column
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def parameter_line(column)
|
|
32
|
+
# условия для расхождений типов Grape и полей БД
|
|
33
|
+
type =
|
|
34
|
+
case column.type
|
|
35
|
+
when :enum
|
|
36
|
+
'String'
|
|
37
|
+
when :decimal
|
|
38
|
+
'Float'
|
|
39
|
+
else
|
|
40
|
+
column.type.capitalize
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# базовая строка
|
|
44
|
+
line = "optional :#{column.name}, type: #{type}"
|
|
45
|
+
|
|
46
|
+
# добавление возможных значений enum
|
|
47
|
+
if column.type == :enum
|
|
48
|
+
values = "#{model}.#{column.name.pluralize}.values"
|
|
49
|
+
line += ", values: #{values}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# не добавлять описание, если оно отсутствует
|
|
53
|
+
desc = column.comment
|
|
54
|
+
if column.type == :enum
|
|
55
|
+
desc = "#{desc} (enum: #{column.sql_type})"
|
|
56
|
+
end
|
|
57
|
+
line += ", desc: '#{desc}'" if desc.present?
|
|
58
|
+
|
|
59
|
+
line.force_encoding(Encoding::BINARY)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
<% module_namespacing do -%>
|
|
2
|
+
module API<%= api_version_module_with_prefix %>
|
|
3
|
+
class <%= controller_class %> < API<%= api_version_module_with_prefix %>::Root
|
|
4
|
+
|
|
5
|
+
include API<%= api_version_module_with_prefix %>::Defaults
|
|
6
|
+
<%- unless @no_params -%>
|
|
7
|
+
helpers Params<%= api_version_module_with_prefix %>::<%= controller_class %>
|
|
8
|
+
<%- end -%>
|
|
9
|
+
<%- if @abilities_check -%>
|
|
10
|
+
|
|
11
|
+
before { authorize_route! }
|
|
12
|
+
<%- end -%>
|
|
13
|
+
|
|
14
|
+
resource :<%= api_address %> do
|
|
15
|
+
|
|
16
|
+
<%- if @no_entity -%>
|
|
17
|
+
desc '<%= api_description %> - список'
|
|
18
|
+
<%- else -%>
|
|
19
|
+
desc '<%= api_description %> - список', entity: <%= entity_class %>::List
|
|
20
|
+
<%- end -%>
|
|
21
|
+
oauth2
|
|
22
|
+
<%- unless @no_params -%>
|
|
23
|
+
params do
|
|
24
|
+
use :list
|
|
25
|
+
end
|
|
26
|
+
<%- end -%>
|
|
27
|
+
<%- if @abilities_check -%>
|
|
28
|
+
get root: false, <%= abilities_authorize_content(:read) %> do
|
|
29
|
+
<%- else -%>
|
|
30
|
+
get root: false do
|
|
31
|
+
<%- end -%>
|
|
32
|
+
<%= ApiScaffolding.config.pagination_list_content.call(class_name) %>
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
<%- if @no_entity -%>
|
|
36
|
+
desc '<%= api_description %> - получение записи'
|
|
37
|
+
<%- else -%>
|
|
38
|
+
desc '<%= api_description %> - получение записи', entity: <%= entity_class %>::Entry
|
|
39
|
+
<%- end -%>
|
|
40
|
+
oauth2
|
|
41
|
+
<%- if @abilities_check -%>
|
|
42
|
+
get ':id', root: false, <%= abilities_authorize_content(:read) %> do
|
|
43
|
+
<%- else -%>
|
|
44
|
+
get ':id', root: false do
|
|
45
|
+
<%- end -%>
|
|
46
|
+
<%- if @no_entity -%>
|
|
47
|
+
<%= class_name %>.find(params[:id])
|
|
48
|
+
<%- else -%>
|
|
49
|
+
record = <%= class_name %>.find(params[:id])
|
|
50
|
+
present record, with: <%= entity_class %>::Entry
|
|
51
|
+
<%- end -%>
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
<%- if @no_entity -%>
|
|
55
|
+
desc '<%= api_description %> - создание'
|
|
56
|
+
<%- else -%>
|
|
57
|
+
desc '<%= api_description %> - создание', entity: <%= entity_class %>::Entry
|
|
58
|
+
<%- end -%>
|
|
59
|
+
oauth2
|
|
60
|
+
<%- unless @no_params -%>
|
|
61
|
+
params do
|
|
62
|
+
use :<%= file_name %>
|
|
63
|
+
end
|
|
64
|
+
<%- end -%>
|
|
65
|
+
<%- if @abilities_check -%>
|
|
66
|
+
post root: false, <%= abilities_authorize_content(:create) %> do
|
|
67
|
+
<%- else -%>
|
|
68
|
+
post root: false do
|
|
69
|
+
<%- end -%>
|
|
70
|
+
attrs = declared(params, include_missing: false)
|
|
71
|
+
<%- if @no_entity -%>
|
|
72
|
+
<%= class_name %>.create!(attrs)
|
|
73
|
+
<%- else -%>
|
|
74
|
+
record = <%= class_name %>.create!(attrs)
|
|
75
|
+
present record, with: <%= entity_class %>::Entry
|
|
76
|
+
<%- end -%>
|
|
77
|
+
end
|
|
78
|
+
<%- if @restoration_required -%>
|
|
79
|
+
|
|
80
|
+
<%- if @no_entity -%>
|
|
81
|
+
desc '<%= api_description %> - восстановление записи'
|
|
82
|
+
<%- else -%>
|
|
83
|
+
desc '<%= api_description %> - восстановление записи', entity: <%= entity_class %>::Entry
|
|
84
|
+
<%- end -%>
|
|
85
|
+
oauth2
|
|
86
|
+
<%- if @abilities_check -%>
|
|
87
|
+
post ':id/restore', root: false, <%= abilities_authorize_content(:restore) %> do
|
|
88
|
+
<%- else -%>
|
|
89
|
+
post ':id/restore', root: false do
|
|
90
|
+
<%- end -%>
|
|
91
|
+
record = <%= class_name %>.deleted.find(params[:id])
|
|
92
|
+
<%- if @no_entity -%>
|
|
93
|
+
record.restore(recursive: true)
|
|
94
|
+
<%- else -%>
|
|
95
|
+
present record.restore(recursive: true), with: <%= entity_class %>::Entry
|
|
96
|
+
<%- end -%>
|
|
97
|
+
end
|
|
98
|
+
<%- end -%>
|
|
99
|
+
|
|
100
|
+
<%- if @no_entity -%>
|
|
101
|
+
desc '<%= api_description %> - редактирование'
|
|
102
|
+
<%- else -%>
|
|
103
|
+
desc '<%= api_description %> - редактирование', entity: <%= entity_class %>::Entry
|
|
104
|
+
<%- end -%>
|
|
105
|
+
oauth2
|
|
106
|
+
<%- unless @no_params -%>
|
|
107
|
+
params do
|
|
108
|
+
use :<%= file_name %>
|
|
109
|
+
end
|
|
110
|
+
<%- end -%>
|
|
111
|
+
<%- if @abilities_check -%>
|
|
112
|
+
put ':id', root: false, <%= abilities_authorize_content(:update) %> do
|
|
113
|
+
<%- else -%>
|
|
114
|
+
put ':id', root: false do
|
|
115
|
+
<%- end -%>
|
|
116
|
+
attrs = declared(params, include_missing: false)
|
|
117
|
+
|
|
118
|
+
record = <%= class_name %>.find(params[:id])
|
|
119
|
+
record.update!(attrs)
|
|
120
|
+
<%- if @no_entity -%>
|
|
121
|
+
record
|
|
122
|
+
<%- else -%>
|
|
123
|
+
present record, with: <%= entity_class %>::Entry
|
|
124
|
+
<%- end -%>
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
desc '<%= api_description %> - удаление'
|
|
128
|
+
oauth2
|
|
129
|
+
<%- if @abilities_check -%>
|
|
130
|
+
delete ':id', root: false, <%= abilities_authorize_content(:destroy) %> do
|
|
131
|
+
<%- else -%>
|
|
132
|
+
delete ':id', root: false do
|
|
133
|
+
<%- end -%>
|
|
134
|
+
<%= class_name %>.find(params[:id]).destroy
|
|
135
|
+
status(200)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
<% end -%>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<% module_namespacing do -%>
|
|
2
|
+
if defined?(ApiScaffold)
|
|
3
|
+
ApiScaffold.configure do |config|
|
|
4
|
+
|
|
5
|
+
# базовая версия API
|
|
6
|
+
# опциональная настройка
|
|
7
|
+
#
|
|
8
|
+
# config.default_api_version = ''
|
|
9
|
+
|
|
10
|
+
# соответствия версий API и названий модулей
|
|
11
|
+
# например 'main' => 'Main', 'pwa' => 'PWA'
|
|
12
|
+
# опциональная настройка
|
|
13
|
+
#
|
|
14
|
+
# config.api_version_modules = {
|
|
15
|
+
# }
|
|
16
|
+
|
|
17
|
+
# обработчик содержимого GET методов со списками
|
|
18
|
+
#
|
|
19
|
+
# config.pagination_list_content = proc do |model_name|
|
|
20
|
+
# "Paginated.collection(
|
|
21
|
+
# model: #{model_name},
|
|
22
|
+
# serialization_scope:
|
|
23
|
+
# )"
|
|
24
|
+
# end
|
|
25
|
+
|
|
26
|
+
# список исключений, для которых не будут добавляться поля в модуле с параметрами
|
|
27
|
+
#
|
|
28
|
+
# config.params_fields_exclusions = %w[
|
|
29
|
+
# id
|
|
30
|
+
# created_at
|
|
31
|
+
# updated_at
|
|
32
|
+
# deleted_at
|
|
33
|
+
# ]
|
|
34
|
+
|
|
35
|
+
# список исключений, для которых не будут добавляться поля в классе entity
|
|
36
|
+
#
|
|
37
|
+
# config.entity_fields_exclusions = %w[]
|
|
38
|
+
|
|
39
|
+
# CanCan Ability
|
|
40
|
+
#
|
|
41
|
+
# config.abilities_check = true
|
|
42
|
+
# config.abilities_authorize_opts = ''
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
<% end -%>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<% module_namespacing do -%>
|
|
2
|
+
module Params<%= api_version_module_with_prefix %>::<%= controller_class %>
|
|
3
|
+
|
|
4
|
+
extend Grape::API::Helpers
|
|
5
|
+
|
|
6
|
+
params :list do
|
|
7
|
+
optional :offset, type: Integer
|
|
8
|
+
optional :columns, type: [String], desc: 'Требуемый список колонок'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
params :<%= file_name %> do
|
|
12
|
+
<%- params_fields.each do |column| -%>
|
|
13
|
+
<%= parameter_line(column) %>
|
|
14
|
+
<%- end -%>
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
<% end -%>
|
metadata
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: api_scaffolding
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.2
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Павел Бабин
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2024-05-07 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rails
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '6.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '6.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: grape
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 1.7.0
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 1.7.0
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: grape-entity
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 1.0.0
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: 1.0.0
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: faker
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3.0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '3.0'
|
|
69
|
+
description: Генерация контроллеров API и модулей с параметрами Grape и Grape Entity
|
|
70
|
+
email: babin359@gmail.com
|
|
71
|
+
executables: []
|
|
72
|
+
extensions: []
|
|
73
|
+
extra_rdoc_files: []
|
|
74
|
+
files:
|
|
75
|
+
- README.md
|
|
76
|
+
- lib/api_scaffolding.rb
|
|
77
|
+
- lib/api_scaffolding/configuration.rb
|
|
78
|
+
- lib/generators/api_scaffold/api_scaffold_generator.rb
|
|
79
|
+
- lib/generators/api_scaffold/controller_generator.rb
|
|
80
|
+
- lib/generators/api_scaffold/entity_generator.rb
|
|
81
|
+
- lib/generators/api_scaffold/helper.rb
|
|
82
|
+
- lib/generators/api_scaffold/install_generator.rb
|
|
83
|
+
- lib/generators/api_scaffold/modify_api_root_generator.rb
|
|
84
|
+
- lib/generators/api_scaffold/params_concern_generator.rb
|
|
85
|
+
- lib/generators/templates/api_controller.rb.tt
|
|
86
|
+
- lib/generators/templates/config_initializer.rb.tt
|
|
87
|
+
- lib/generators/templates/entity.rb.tt
|
|
88
|
+
- lib/generators/templates/params_concern.rb.tt
|
|
89
|
+
homepage:
|
|
90
|
+
licenses:
|
|
91
|
+
- MIT
|
|
92
|
+
metadata:
|
|
93
|
+
rubygems_mfa_required: 'true'
|
|
94
|
+
post_install_message:
|
|
95
|
+
rdoc_options: []
|
|
96
|
+
require_paths:
|
|
97
|
+
- lib
|
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '3.2'
|
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
|
+
requirements:
|
|
105
|
+
- - ">="
|
|
106
|
+
- !ruby/object:Gem::Version
|
|
107
|
+
version: '0'
|
|
108
|
+
requirements: []
|
|
109
|
+
rubygems_version: 3.0.6
|
|
110
|
+
signing_key:
|
|
111
|
+
specification_version: 4
|
|
112
|
+
summary: Генерация компонентов API
|
|
113
|
+
test_files: []
|