gemfather-stable 2.2.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 +145 -0
- data/bin/gemfather +6 -0
- data/gem_template/%app_name%.gemspec.tt +32 -0
- data/gem_template/.gitignore.tt +26 -0
- data/gem_template/.rubocop-rspec.yml.tt +38 -0
- data/gem_template/.rubocop-ruby.yml.tt +54 -0
- data/gem_template/.rubocop.yml.tt +11 -0
- data/gem_template/Gemfile.tt +17 -0
- data/gem_template/Makefile.tt +21 -0
- data/gem_template/README.md.tt +180 -0
- data/gem_template/Rakefile.tt +6 -0
- data/gem_template/bin/console.tt +21 -0
- data/gem_template/bin/generate.tt +6 -0
- data/gem_template/bin/rubocop.tt +29 -0
- data/gem_template/lib/%app_name%.rb.tt +25 -0
- data/gem_template/lib/%app_short_name%/client.rb.tt +18 -0
- data/gem_template/lib/%app_short_name%/http_errors.rb.tt +20 -0
- data/gem_template/lib/%app_short_name%/railtie.rb.tt +5 -0
- data/gem_template/lib/%app_short_name%/version.rb.tt +5 -0
- data/gem_template/log/.keep.tt +0 -0
- data/gem_template/spec/spec_helper.rb.tt +35 -0
- data/lib/api_generator/client/config.rb +57 -0
- data/lib/api_generator/client/connection.rb +149 -0
- data/lib/api_generator/commands/generate.rb +56 -0
- data/lib/api_generator/helpers/utils.rb +56 -0
- data/lib/api_generator/middleware/error_code_middleware.rb +43 -0
- data/lib/api_generator/middleware/error_handler_middleware.rb +26 -0
- data/lib/api_generator/middleware/handle_unsuccessful_request_middleware.rb +36 -0
- data/lib/api_generator/middleware/http_errors.rb +21 -0
- data/lib/api_generator/middleware/raise_error_base.rb +11 -0
- data/lib/api_generator/middleware/raise_error_dsl.rb +36 -0
- data/lib/api_generator/middleware.rb +4 -0
- data/lib/api_generator/models/base.rb +15 -0
- data/lib/api_generator/models/data.rb +16 -0
- data/lib/api_generator/pagination/dsl.rb +32 -0
- data/lib/api_generator/pagination/limit_offset_relation.rb +24 -0
- data/lib/api_generator/pagination/page_relation.rb +21 -0
- data/lib/api_generator/pagination/relation.rb +114 -0
- data/lib/api_generator/pagination.rb +2 -0
- data/lib/api_generator/railtie.rb +24 -0
- data/lib/api_generator/services/base_create.rb +56 -0
- data/lib/api_generator/services/create_api.rb +87 -0
- data/lib/api_generator/services/create_model.rb +69 -0
- data/lib/api_generator/services/create_scaffold.rb +53 -0
- data/lib/api_generator/services/gemfather.rb +81 -0
- data/lib/api_generator/version.rb +3 -0
- data/lib/api_generator.rb +18 -0
- data/templates/api/action.erb +10 -0
- data/templates/api/action_paginate.erb +10 -0
- data/templates/api/api_module.erb +11 -0
- data/templates/api/include_helpers.erb +9 -0
- data/templates/api/include_namespace.erb +1 -0
- data/templates/api/path.erb +1 -0
- data/templates/models/request.erb +11 -0
- data/templates/models/response.erb +11 -0
- data/templates/specs/api_spec.erb +15 -0
- data/templates/specs/request_spec.erb +12 -0
- data/templates/specs/response_spec.erb +12 -0
- metadata +229 -0
@@ -0,0 +1,114 @@
|
|
1
|
+
class ApiGenerator::Pagination::Relation
|
2
|
+
include Enumerable
|
3
|
+
|
4
|
+
attr_reader :options
|
5
|
+
|
6
|
+
def initialize(config, options = {}, &fetch_block)
|
7
|
+
@config = config
|
8
|
+
@options = options
|
9
|
+
@fetch_block = fetch_block
|
10
|
+
end
|
11
|
+
|
12
|
+
# Получение всех записей начиная с текущей страницы (страницы грузятся по мере необходимости,
|
13
|
+
# и элементы передаются в enumerator)
|
14
|
+
def all_remaining
|
15
|
+
expand(all_remaining: true)
|
16
|
+
end
|
17
|
+
|
18
|
+
def order(sort)
|
19
|
+
expand(sort: sort)
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [Enumerator, ApiGenerator::Pagination::Relation] Enumerator по всем элементам,
|
23
|
+
# Если задана опция all_remaining, клиент посылает запросы за следующими страницами
|
24
|
+
# по мере необходимости, иначе загружаются только элементы текущей страницы
|
25
|
+
def each(&block)
|
26
|
+
return to_enum(:each) unless block
|
27
|
+
|
28
|
+
data.each(&block)
|
29
|
+
|
30
|
+
return self if !all_remaining? || last_page?
|
31
|
+
|
32
|
+
next_relation.each(&block)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Возвращает ответ в исходном виде
|
36
|
+
def response
|
37
|
+
@response ||= fetch_block.call(self)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Integer] количество элементов на текущей странице
|
41
|
+
def size
|
42
|
+
data.size
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [Integer] общее количество элементов на всех страницах
|
46
|
+
# @raise [NotImplementedError] в случае, если коллбэк `total` не задан в конфиге DSL
|
47
|
+
def total
|
48
|
+
raise NotImplementedError, 'Total callback is not set in configuration' if config[:total].blank?
|
49
|
+
|
50
|
+
config[:total]&.call(response)
|
51
|
+
end
|
52
|
+
alias total_count total
|
53
|
+
|
54
|
+
# @return [Integer] общее количество элементов на всех страницах (сначала загрузит все страницы)
|
55
|
+
def total!
|
56
|
+
total
|
57
|
+
rescue NotImplementedError
|
58
|
+
self.class.new(config, {}, &fetch_block).all_remaining.count
|
59
|
+
end
|
60
|
+
alias total_count! total!
|
61
|
+
|
62
|
+
alias all to_a
|
63
|
+
|
64
|
+
def inspect
|
65
|
+
class_name_with_status = [self.class, ('(not fetched)' if @response.blank?)].compact.join(' ')
|
66
|
+
|
67
|
+
"#<#{class_name_with_status} #{options}>"
|
68
|
+
end
|
69
|
+
|
70
|
+
alias to_s inspect
|
71
|
+
|
72
|
+
def pretty_print(pretty_printer)
|
73
|
+
pretty_printer.text(inspect)
|
74
|
+
end
|
75
|
+
|
76
|
+
def request_options
|
77
|
+
options.except(:all_remaining)
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
attr_reader :fetch_block, :config
|
83
|
+
|
84
|
+
def data
|
85
|
+
case data_key
|
86
|
+
when Symbol, String
|
87
|
+
response.public_send(data_key)
|
88
|
+
when Array
|
89
|
+
response.dig(*data_key)
|
90
|
+
else
|
91
|
+
raise ArgumentError, 'Data key should be a symbol, string or array'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def expand(**options)
|
96
|
+
self.class.new(config, self.options.merge(options), &fetch_block)
|
97
|
+
end
|
98
|
+
|
99
|
+
def data_key
|
100
|
+
config[:data_key] || :itself
|
101
|
+
end
|
102
|
+
|
103
|
+
def all_remaining?
|
104
|
+
options[:all_remaining]
|
105
|
+
end
|
106
|
+
|
107
|
+
def next_relation
|
108
|
+
raise NotImplementedError
|
109
|
+
end
|
110
|
+
|
111
|
+
def last_page?
|
112
|
+
raise NotImplementedError
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ApiGenerator
|
2
|
+
module Railtie
|
3
|
+
# rubocop:disable Metrics/MethodLength,Metrics/AbcSize
|
4
|
+
def self.extended(klass)
|
5
|
+
return unless defined?(Rails)
|
6
|
+
|
7
|
+
klass.class_eval do |target_class|
|
8
|
+
initializer_name = "#{target_class.to_s.deconstantize.underscore}.configure"
|
9
|
+
initializer initializer_name, after: 'initialize_logger' do
|
10
|
+
target_class.name.deconstantize.constantize::Client.configure do |config|
|
11
|
+
config.user_agent = [
|
12
|
+
Rails.application.class.module_parent_name.underscore,
|
13
|
+
Rails.env,
|
14
|
+
config.user_agent,
|
15
|
+
].join(' - ')
|
16
|
+
|
17
|
+
config.logger = Rails.logger if Rails.env.development? || Rails.env.test?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
# rubocop:enable Metrics/MethodLength,Metrics/AbcSize
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module ApiGenerator
|
2
|
+
module Services
|
3
|
+
class BaseCreate
|
4
|
+
include Helpers::Utils
|
5
|
+
|
6
|
+
attr_reader :target, :data
|
7
|
+
|
8
|
+
def initialize(target, data)
|
9
|
+
@target = target
|
10
|
+
@data = data
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
raise NotImplementedError
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def templates(name)
|
20
|
+
File.expand_path(templates_files[name.to_sym], templates_folder)
|
21
|
+
end
|
22
|
+
|
23
|
+
def folders(name)
|
24
|
+
File.expand_path(target_folders[name.to_sym], root)
|
25
|
+
end
|
26
|
+
|
27
|
+
def render_template(name)
|
28
|
+
render(templates(name.to_sym), data.for_template)
|
29
|
+
end
|
30
|
+
|
31
|
+
def root
|
32
|
+
target || File.expand_path(Dir.pwd)
|
33
|
+
end
|
34
|
+
|
35
|
+
def source_root
|
36
|
+
gemfather_lib_path = $LOAD_PATH.grep(/gems\/gemfather/).first
|
37
|
+
|
38
|
+
return File.expand_path('../', gemfather_lib_path) if gemfather_lib_path
|
39
|
+
|
40
|
+
File.expand_path('../../../', __dir__)
|
41
|
+
end
|
42
|
+
|
43
|
+
def templates_folder
|
44
|
+
File.expand_path('./templates', source_root)
|
45
|
+
end
|
46
|
+
|
47
|
+
def templates_files
|
48
|
+
raise NotImplementedError
|
49
|
+
end
|
50
|
+
|
51
|
+
def target_folders
|
52
|
+
raise NotImplementedError
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module ApiGenerator
|
2
|
+
module Services
|
3
|
+
class CreateApi < BaseCreate
|
4
|
+
PATH_MARKER = 'PATHS'.freeze
|
5
|
+
ACTION_MARKER = 'ACTIONS'.freeze
|
6
|
+
INCLUDE_MARKER = 'INCLUDES'.freeze
|
7
|
+
|
8
|
+
def call
|
9
|
+
prepare_folders
|
10
|
+
|
11
|
+
create_api_module
|
12
|
+
add_path
|
13
|
+
add_action
|
14
|
+
add_module_to_client
|
15
|
+
|
16
|
+
create_api_spec
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def prepare_folders
|
22
|
+
create_dir(folders(:api))
|
23
|
+
create_dir(folders(:spec_api))
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_api_module
|
27
|
+
return if File.exist?(api_module)
|
28
|
+
|
29
|
+
copy_template(templates(:api_module), api_module, data.for_template)
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_path
|
33
|
+
inject_after_str(api_module, PATH_MARKER, render_template(:path))
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_action
|
37
|
+
if data.paginate
|
38
|
+
inject_after_str(api_module, INCLUDE_MARKER, render_template(:include_helpers))
|
39
|
+
inject_after_str(api_module, ACTION_MARKER, render_template(:action_paginate))
|
40
|
+
else
|
41
|
+
inject_after_str(api_module, ACTION_MARKER, render_template(:action))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_module_to_client
|
46
|
+
inject_after_str(client_class, INCLUDE_MARKER, render_template(:include_namespace))
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_api_spec
|
50
|
+
copy_template(templates(:api_spec), api_spec, data.for_template)
|
51
|
+
end
|
52
|
+
|
53
|
+
def api_module
|
54
|
+
File.expand_path("./#{data.namespace}.rb", folders(:api))
|
55
|
+
end
|
56
|
+
|
57
|
+
def client_class
|
58
|
+
File.expand_path('./client.rb', folders(:app))
|
59
|
+
end
|
60
|
+
|
61
|
+
def api_spec
|
62
|
+
File.expand_path("./#{data.namespace}_spec.rb", folders(:spec_api))
|
63
|
+
end
|
64
|
+
|
65
|
+
def templates_files
|
66
|
+
{
|
67
|
+
api_module: './api/api_module.erb',
|
68
|
+
path: './api/path.erb',
|
69
|
+
action: './api/action.erb',
|
70
|
+
action_paginate: './api/action_paginate.erb',
|
71
|
+
include_helpers: './api/include_helpers.erb',
|
72
|
+
include_namespace: './api/include_namespace.erb',
|
73
|
+
api_spec: './specs/api_spec.erb',
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def target_folders
|
78
|
+
{
|
79
|
+
app: "./lib/#{data.app_short_name}",
|
80
|
+
api: "./lib/#{data.app_short_name}/api",
|
81
|
+
spec: './spec',
|
82
|
+
spec_api: './spec/api',
|
83
|
+
}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module ApiGenerator
|
2
|
+
module Services
|
3
|
+
class CreateModel < BaseCreate
|
4
|
+
def call
|
5
|
+
prepare_folders
|
6
|
+
|
7
|
+
create_models
|
8
|
+
create_models_specs
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def prepare_folders
|
14
|
+
create_dir(folders(:model_namespace_action))
|
15
|
+
create_dir(folders(:spec_model))
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_models
|
19
|
+
models.each do |model|
|
20
|
+
copy_template(templates(model), target_model(model), data.for_template)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_models_specs
|
25
|
+
specs.each do |template|
|
26
|
+
copy_template(templates(template), target_spec(template), data.for_template)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def models
|
31
|
+
%i[request response]
|
32
|
+
end
|
33
|
+
|
34
|
+
def specs
|
35
|
+
%i[request_spec response_spec]
|
36
|
+
end
|
37
|
+
|
38
|
+
def target_spec(template)
|
39
|
+
File.expand_path("./#{template}.rb", folders(:spec_model))
|
40
|
+
end
|
41
|
+
|
42
|
+
def target_model(template)
|
43
|
+
File.expand_path("./#{template}.erb", folders(:model_namespace_action))
|
44
|
+
end
|
45
|
+
|
46
|
+
def target_folders
|
47
|
+
{
|
48
|
+
model: "./lib/#{data.app_short_name}/model",
|
49
|
+
model_namespace: "./lib/#{data.app_short_name}/model/#{data.namespace}",
|
50
|
+
model_namespace_action:
|
51
|
+
"./lib/#{data.app_short_name}/model/#{data.namespace}/#{data.action}",
|
52
|
+
spec: './spec',
|
53
|
+
spec_model: "./spec/model/#{data.namespace}/#{data.action}",
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def templates_files
|
58
|
+
{
|
59
|
+
request: './models/request.erb',
|
60
|
+
response: './models/response.erb',
|
61
|
+
responses: './models/responses.erb',
|
62
|
+
paginated_response: './models/paginated_response.erb',
|
63
|
+
request_spec: './specs/request_spec.erb',
|
64
|
+
response_spec: './specs/response_spec.erb',
|
65
|
+
}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ApiGenerator
|
2
|
+
module Services
|
3
|
+
class CreateScaffold
|
4
|
+
attr_accessor :namespace, :action, :http_method, :paginate
|
5
|
+
|
6
|
+
# rubocop:disable Style/OptionalBooleanParameter
|
7
|
+
def initialize(namespace, action, http_method, paginate = false, root = nil)
|
8
|
+
@namespace = namespace
|
9
|
+
@action = action
|
10
|
+
@http_method = http_method
|
11
|
+
@paginate = paginate
|
12
|
+
@root = root || File.expand_path(Dir.pwd)
|
13
|
+
end
|
14
|
+
# rubocop:enable Style/OptionalBooleanParameter
|
15
|
+
|
16
|
+
def call
|
17
|
+
create_api_w_specs
|
18
|
+
create_models_w_specs
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def create_api_w_specs
|
24
|
+
Services::CreateApi.new(@root, data).call
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_models_w_specs
|
28
|
+
Services::CreateModel.new(@root, data).call
|
29
|
+
end
|
30
|
+
|
31
|
+
def data
|
32
|
+
Models::Data.new(
|
33
|
+
namespace: namespace,
|
34
|
+
action: action,
|
35
|
+
http_method: http_method,
|
36
|
+
paginate: paginate,
|
37
|
+
app_name: app_name,
|
38
|
+
app_short_name: app_name,
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def app_name
|
43
|
+
@app_name ||= begin
|
44
|
+
gemspec = Dir[File.expand_path('./*', @root)].grep(/\.gemspec/).first
|
45
|
+
|
46
|
+
raise 'Not root of the API gem' unless gemspec
|
47
|
+
|
48
|
+
File.basename(gemspec, '.gemspec')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module ApiGenerator
|
2
|
+
module Services
|
3
|
+
class Gemfather < Thor
|
4
|
+
include Thor::Actions
|
5
|
+
|
6
|
+
# octal notation for rubocop
|
7
|
+
EXEC_MODE = 0o0755
|
8
|
+
|
9
|
+
cattr_accessor :target_dir
|
10
|
+
attr_accessor :app_name, :app_name_class, :app_short_name,
|
11
|
+
:app_short_name_class, :author, :email, :version
|
12
|
+
|
13
|
+
# rubocop:disable Metrics/MethodLength
|
14
|
+
desc 'generates API gem', 'generates basic API gem with the provided name'
|
15
|
+
def generate_client(app_name)
|
16
|
+
check_app_name(app_name)
|
17
|
+
setup_template_variables(app_name)
|
18
|
+
|
19
|
+
check_if_folder_exists
|
20
|
+
|
21
|
+
directory(template_path, destination_path, { context: binding })
|
22
|
+
|
23
|
+
inside(destination_path) do
|
24
|
+
empty_directory('log')
|
25
|
+
run('bundle')
|
26
|
+
run('bundle binstubs rspec-core rubocop --force')
|
27
|
+
run('git init')
|
28
|
+
set_executables
|
29
|
+
end
|
30
|
+
end
|
31
|
+
# rubocop:enable Metrics/MethodLength
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
private_class_method :source_root
|
36
|
+
|
37
|
+
def check_app_name(app_name)
|
38
|
+
raise(Thor::Error, 'APP_NAME is not provided') unless app_name
|
39
|
+
raise(Thor::Error, "Folder #{app_name} name already exists") if Dir.exist?("./#{app_name}")
|
40
|
+
end
|
41
|
+
|
42
|
+
def setup_template_variables(app_name)
|
43
|
+
self.app_name = app_name
|
44
|
+
self.app_short_name = app_name
|
45
|
+
self.app_name_class = app_short_name.camelize
|
46
|
+
self.app_short_name_class = app_short_name.camelize
|
47
|
+
self.author = 'Domclick Ruby Team'
|
48
|
+
self.email = `git config user.email`
|
49
|
+
self.version = ApiGenerator::VERSION
|
50
|
+
end
|
51
|
+
|
52
|
+
def check_if_folder_exists
|
53
|
+
Dir.exist?(destination_path) &&
|
54
|
+
(file_collision(destination_path) ||
|
55
|
+
raise(Thor::Error, 'Directory already exists'))
|
56
|
+
end
|
57
|
+
|
58
|
+
def destination_path
|
59
|
+
File.expand_path(app_name, called_from_path)
|
60
|
+
end
|
61
|
+
|
62
|
+
def called_from_path
|
63
|
+
self.class.target_dir || Dir.pwd
|
64
|
+
end
|
65
|
+
|
66
|
+
def template_path
|
67
|
+
File.expand_path('./gem_template', self.class.source_root)
|
68
|
+
end
|
69
|
+
|
70
|
+
def set_executables
|
71
|
+
Dir[File.expand_path('./*', 'bin')].each do |file|
|
72
|
+
chmod(file, EXEC_MODE)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.source_root
|
77
|
+
File.expand_path('./../../../', __dir__)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
require 'active_support/core_ext/module/introspection'
|
4
|
+
require 'active_support/core_ext/object/try'
|
5
|
+
require 'dry-configurable'
|
6
|
+
require 'faraday_middleware'
|
7
|
+
require 'faraday'
|
8
|
+
require 'hashie'
|
9
|
+
require 'delegate'
|
10
|
+
require 'thor'
|
11
|
+
require 'erb'
|
12
|
+
|
13
|
+
require 'zeitwerk'
|
14
|
+
loader = Zeitwerk::Loader.for_gem
|
15
|
+
loader.setup
|
16
|
+
|
17
|
+
module ApiGenerator
|
18
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
def <%= action %>(request_or_hash)
|
2
|
+
request = if request_or_hash.is_a?(Model::<%= namespace.camelize %>::<%= action.camelize %>::Request)
|
3
|
+
request_or_hash
|
4
|
+
else
|
5
|
+
Model::<%= namespace.camelize %>::<%= action.camelize %>::Request.new(params)
|
6
|
+
end
|
7
|
+
|
8
|
+
response = connection.<%= http_method %>(<%= action.upcase %>_PATH, request)
|
9
|
+
Model::<%= namespace.camelize %>::<%= action.camelize %>::Response.new(response.body)
|
10
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
def <%= action %>(request_or_hash, &req_block)
|
2
|
+
request = if request_or_hash.is_a?(Model::<%= namespace.camelize %>::<%= action.camelize %>::Request)
|
3
|
+
request_or_hash
|
4
|
+
else
|
5
|
+
Model::<%= namespace.camelize %>::<%= action.camelize %>::Request.new(params)
|
6
|
+
end
|
7
|
+
|
8
|
+
response = connection.<%= http_method %>(<%= action.upcase %>_PATH, request, &req_block)
|
9
|
+
Model::<%= namespace.camelize %>::<%= action.camelize %>::Response.new(response.body)
|
10
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
include <%= app_short_name.camelize %>::Api::<%= namespace.camelize %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= action.upcase %>_PATH = '/<%= action %>'.freeze
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe <%= app_short_name.camelize %>::Api::<%= namespace.camelize %> do
|
4
|
+
describe '<%= namespace %>' do
|
5
|
+
let(:client) { <%= app_short_name.camelize %>.client }
|
6
|
+
|
7
|
+
describe '#<%= action %>' do
|
8
|
+
let(:params) { {} }
|
9
|
+
|
10
|
+
it 'makes successful request', vcr: { cassette_name: '<%= namespace.camelize %>/<%= action %>/success' } do
|
11
|
+
expect { client.<%= action %>(params) }.not_to raise_error
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe <%= app_short_name.camelize %>::Model::<%= namespace.camelize %>::<%= action.camelize %>::Request do
|
4
|
+
describe 'request model' do
|
5
|
+
let(:properties) { {} }
|
6
|
+
let(:model) { described_class.new(properties) }
|
7
|
+
|
8
|
+
it 'behaves like request' do
|
9
|
+
expect(model).to eq(properties)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe <%= app_short_name.camelize %>::Model::<%= namespace.camelize %>::<%= action.camelize %>::Response do
|
4
|
+
describe 'response model' do
|
5
|
+
let(:properties) { {} }
|
6
|
+
let(:model) { described_class.new(properties) }
|
7
|
+
|
8
|
+
it 'behaves like response' do
|
9
|
+
expect(model).to eq(properties)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|