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