rest-api-generator 0.1.0 → 0.1.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 +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +171 -44
- data/README.md +232 -64
- data/Rakefile +1 -1
- data/lib/generators/rest_api_generator/helpers.rb +30 -0
- data/lib/generators/rest_api_generator/resource_generator.rb +73 -13
- data/lib/generators/rest_api_generator/templates/child_api_controller.rb.tt +9 -8
- data/lib/generators/rest_api_generator/templates/child_api_spec.rb.tt +37 -34
- data/lib/generators/rest_api_generator/templates/implicit_child_resource_controller.rb.tt +4 -0
- data/lib/generators/rest_api_generator/templates/implicit_resource_controller.rb.tt +4 -0
- data/lib/generators/rest_api_generator/templates/rest_api_controller.rb.tt +3 -1
- data/lib/generators/rest_api_generator/templates/rest_api_spec.rb.tt +5 -5
- data/lib/rest-api-generator.rb +3 -0
- data/lib/rest_api_generator/application_controller.rb +8 -0
- data/lib/rest_api_generator/child_resource_controller.rb +97 -0
- data/lib/rest_api_generator/filterable.rb +30 -0
- data/lib/rest_api_generator/helpers/render.rb +1 -1
- data/lib/rest_api_generator/orderable.rb +30 -0
- data/lib/rest_api_generator/resource_controller.rb +73 -0
- data/lib/rest_api_generator/version.rb +1 -1
- data/lib/rest_api_generator.rb +11 -1
- data/rest-api-generator.gemspec +41 -0
- metadata +73 -11
- data/.rspec +0 -3
- data/.rubocop.yml +0 -23
- data/CODE_OF_CONDUCT.md +0 -84
- data/LICENSE.txt +0 -21
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "rails/generators"
|
4
|
+
require "rails/generators/active_model"
|
5
|
+
require "rails/generators/rails/model/model_generator"
|
4
6
|
require "generators/rest_api_generator/helpers"
|
5
7
|
module RestApiGenerator
|
6
8
|
class ResourceGenerator < Rails::Generators::NamedBase
|
@@ -8,31 +10,89 @@ module RestApiGenerator
|
|
8
10
|
source_root File.expand_path("templates", __dir__)
|
9
11
|
|
10
12
|
argument :attributes, type: :array, default: [], banner: "field[:type][:index] field[:type][:index]"
|
13
|
+
class_option :eject, type: :boolean, default: false
|
11
14
|
class_option :scope, type: :string, default: ""
|
15
|
+
class_option :father, type: :string, default: ""
|
12
16
|
|
13
17
|
API_CONTROLLER_DIR_PATH = "app/controllers"
|
14
18
|
API_TEST_DIR_PATH = "spec/requests"
|
15
19
|
|
16
20
|
def create_service_file
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
create_model_files
|
22
|
+
|
23
|
+
# Create controller and specs
|
24
|
+
controller_path = "#{API_CONTROLLER_DIR_PATH}#{scope_path}/#{file_name.pluralize}_controller.rb"
|
25
|
+
controller_test_path = "#{API_TEST_DIR_PATH}#{scope_path}/#{file_name.pluralize}_controller_spec.rb"
|
26
|
+
|
27
|
+
template controller_template, controller_path
|
28
|
+
template spec_controller_template, controller_test_path
|
29
|
+
|
30
|
+
if options["scope"].blank? && options["father"].blank?
|
31
|
+
route "resources :#{file_name.pluralize}"
|
25
32
|
else
|
26
|
-
|
27
|
-
controller_path = "#{API_CONTROLLER_DIR_PATH}/#{scope_path}/#{file_name.pluralize}_controller.rb"
|
28
|
-
controller_test_path = "#{API_TEST_DIR_PATH}/#{scope_path}/#{file_name.pluralize}_controller_spec.rb"
|
29
|
-
template "child_api_controller.rb", controller_path
|
30
|
-
template "child_api_spec.rb", controller_test_path
|
33
|
+
log("You need to manually setup routes files for nested or scoped resource")
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
34
37
|
private
|
35
38
|
|
39
|
+
def scope_path
|
40
|
+
return "" if options["scope"].blank? && options["father"].blank?
|
41
|
+
|
42
|
+
if options["scope"].present? && options["father"].present?
|
43
|
+
"/" + option_to_path(options["scope"]) + "/" + option_to_path(options["father"])
|
44
|
+
else
|
45
|
+
"/" + option_to_path(options["scope"]) + option_to_path(options["father"])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def scope_namespacing(&block)
|
50
|
+
content = capture(&block)
|
51
|
+
content = wrap_with_scope(content) if options["scope"].present? || options["father"].present?
|
52
|
+
concat(content)
|
53
|
+
end
|
54
|
+
|
55
|
+
def module_namespace
|
56
|
+
if options["scope"].present? && options["father"].present?
|
57
|
+
options["scope"] + "::" + options["father"]
|
58
|
+
else
|
59
|
+
options["scope"] + options["father"]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def wrap_with_scope(content)
|
64
|
+
content = indent(content).chomp
|
65
|
+
"module #{module_namespace}\n#{content}\nend\n"
|
66
|
+
end
|
67
|
+
|
68
|
+
def controller_template
|
69
|
+
if options["eject"]
|
70
|
+
if options["father"].present?
|
71
|
+
"child_api_controller.rb"
|
72
|
+
else
|
73
|
+
"rest_api_controller.rb"
|
74
|
+
end
|
75
|
+
elsif options["father"].present?
|
76
|
+
"implicit_child_resource_controller.rb"
|
77
|
+
else
|
78
|
+
"implicit_resource_controller.rb"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def spec_controller_template
|
83
|
+
if options["father"].present?
|
84
|
+
"child_api_spec.rb"
|
85
|
+
else
|
86
|
+
"rest_api_spec.rb"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def create_model_files
|
91
|
+
g = Rails::Generators::ModelGenerator.new([file_name, build_model_attributes])
|
92
|
+
g.destination_root = destination_root
|
93
|
+
g.invoke_all
|
94
|
+
end
|
95
|
+
|
36
96
|
def build_model_attributes
|
37
97
|
model_attributes = []
|
38
98
|
attributes.each do |attribute|
|
@@ -1,9 +1,10 @@
|
|
1
|
+
<% scope_namespacing do -%>
|
1
2
|
class <%= class_name.pluralize %>Controller < ApplicationController
|
2
|
-
before_action :set_<%= options['
|
3
|
+
before_action :set_<%= options['father'].downcase.singularize %>
|
3
4
|
before_action :set_<%= singular_name %>, only: %i[ show update destroy ]
|
4
5
|
|
5
6
|
def index
|
6
|
-
@<%= plural_name %> = @<%= options['
|
7
|
+
@<%= plural_name %> = @<%= options['father'].downcase.singularize %>.<%= plural_name %>
|
7
8
|
render json: @<%= plural_name %>, status: :ok
|
8
9
|
end
|
9
10
|
|
@@ -12,7 +13,7 @@ class <%= class_name.pluralize %>Controller < ApplicationController
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def create
|
15
|
-
@<%= singular_name %> = @<%= options['
|
16
|
+
@<%= singular_name %> = @<%= options['father'].downcase.singularize %>.<%= plural_name %>.create!(<%= singular_name %>_params)
|
16
17
|
render json: @<%= singular_name %>, status: :created
|
17
18
|
end
|
18
19
|
|
@@ -25,18 +26,18 @@ class <%= class_name.pluralize %>Controller < ApplicationController
|
|
25
26
|
@<%= singular_name %>.destroy!
|
26
27
|
end
|
27
28
|
|
28
|
-
|
29
29
|
private
|
30
30
|
|
31
|
-
def set_<%= options['
|
32
|
-
@<%= options['
|
31
|
+
def set_<%= options['father'].downcase.singularize %>
|
32
|
+
@<%= options['father'].downcase %> = <%= options['father'] %>.find(params[:<%= options['father'].downcase.singularize %>_id])
|
33
33
|
end
|
34
34
|
|
35
35
|
def set_<%= singular_name %>
|
36
|
-
@<%= singular_name %> = @<%= options['
|
36
|
+
@<%= singular_name %> = @<%= options['father'].downcase.singularize %>.<%= plural_name %>.find(params[:id])
|
37
37
|
end
|
38
38
|
|
39
39
|
def <%= singular_name %>_params
|
40
40
|
params.require(:<%= singular_name %>).permit(<%= attributes.map { |a| ':' + a.name }.join(', ') %>)
|
41
41
|
end
|
42
|
-
end
|
42
|
+
end
|
43
|
+
<% end -%>
|
@@ -1,14 +1,36 @@
|
|
1
|
-
require
|
1
|
+
require "rails_helper"
|
2
2
|
|
3
|
-
RSpec.describe "<%=class_name %>", type: :request do
|
3
|
+
RSpec.describe "<%= class_name %>", type: :request do
|
4
4
|
let(:valid_attributes) { attributes_for(:<%= singular_table_name %>) }
|
5
5
|
|
6
|
-
describe "
|
6
|
+
describe "GET /<%= plural_name %>" do
|
7
|
+
let(:<%= options['father'].downcase.singularize %>) { create(:<%= options['father'].downcase.singularize %>) }
|
8
|
+
let(:<%= singular_table_name %>) { create(:<%=singular_table_name %>, <%= options['father'].downcase %>: <%= options['father'].downcase %>) }
|
9
|
+
|
10
|
+
it "renders a successful response" do
|
11
|
+
get "<%= spec_routes[:index] %>"
|
12
|
+
expect(response).to be_successful
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
describe "GET /<%= singular_name %>" do
|
18
|
+
let(:<%= options['father'].downcase.singularize %>) { create(:<%= options['father'].downcase.singularize %>) }
|
19
|
+
let(:<%= singular_table_name %>) { create(:<%=singular_table_name %>, <%= options['father'].downcase.singularize %>: <%= options['father'].downcase %>)}
|
20
|
+
|
21
|
+
it "gets an <%= singular_name %>" do
|
22
|
+
get "<%= spec_routes[:show] %>"
|
23
|
+
expect(response).to be_successful
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
describe "POST /<%= plural_name %>" do
|
7
29
|
context "with valid parameters" do
|
8
|
-
|
9
|
-
|
30
|
+
let(:<%= options['father'].downcase.singularize %>) { create(:<%= options['father'].downcase.singularize %>) }
|
31
|
+
it "creates a new <%= singular_name %>" do
|
10
32
|
expect do
|
11
|
-
post "
|
33
|
+
post "<%= spec_routes[:create] %>",
|
12
34
|
params: { <%= singular_name %>: valid_attributes }
|
13
35
|
end.to change(<%= class_name %>, :count).by(1)
|
14
36
|
end
|
@@ -16,44 +38,25 @@ RSpec.describe "<%=class_name %>", type: :request do
|
|
16
38
|
end
|
17
39
|
|
18
40
|
describe "PATCH /<%= plural_name %>" do
|
19
|
-
let(:<%= options['
|
20
|
-
let(:<%= singular_table_name %>) { create(:<%=singular_table_name %>, <%= options['
|
41
|
+
let(:<%= options['father'].downcase.singularize %>) { create(:<%= options['father'].downcase.singularize %>) }
|
42
|
+
let(:<%= singular_table_name %>) { create(:<%=singular_table_name %>, <%= options['father'].downcase.singularize %>: <%= options['father'].downcase.singularize %>)}
|
21
43
|
|
22
|
-
it "updates an <%=singular_name %>" do
|
23
|
-
patch "
|
44
|
+
it "updates an <%= singular_name %>" do
|
45
|
+
patch "<%= spec_routes[:update] %>",
|
24
46
|
params: { <%= singular_name %>: valid_attributes }
|
25
47
|
expect(response).to have_http_status(:success)
|
26
48
|
end
|
27
49
|
end
|
28
50
|
|
29
51
|
describe "DELETE /<%= singular_name %>" do
|
30
|
-
let(:<%= options['
|
52
|
+
let(:<%= options['father'].downcase.singularize %>) { create(:<%= options['father'].downcase.singularize %>) }
|
31
53
|
|
32
|
-
it "deletes an <%=singular_name %>" do
|
33
|
-
<%= singular_table_name %> = create(:<%=singular_table_name %>, <%= options['
|
54
|
+
it "deletes an <%= singular_name %>" do
|
55
|
+
<%= singular_table_name %> = create(:<%=singular_table_name %>, <%= options['father'].downcase.singularize %>: <%= options['father'].downcase.singularize %>)
|
34
56
|
expect do
|
35
|
-
delete "
|
57
|
+
delete "<%= spec_routes[:delete] %>"
|
36
58
|
end.to change(<%= class_name %>, :count).by(-1)
|
37
59
|
end
|
38
60
|
end
|
39
61
|
|
40
|
-
|
41
|
-
let(:<%= options['scope'].downcase %>) {create(:<%= options['scope'].downcase %>)}
|
42
|
-
let(:<%= singular_table_name %>) { create(:<%=singular_table_name %>, <%= options['scope'].downcase %>: <%= options['scope'].downcase %>)}
|
43
|
-
|
44
|
-
it "gets an <%=singular_name %>" do
|
45
|
-
get "/<%= options['scope'].downcase.pluralize %>/#{<%= options['scope'].downcase %>.id}/<%= plural_name %>/#{<%= singular_name %>.id}"
|
46
|
-
expect(response).to be_successful
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe "GET /<%= plural_name %>" do
|
51
|
-
let(:<%= options['scope'].downcase %>) {create(:<%= options['scope'].downcase %>)}
|
52
|
-
let(:<%= singular_table_name %>) { create(:<%=singular_table_name %>, <%= options['scope'].downcase %>: <%= options['scope'].downcase %>) }
|
53
|
-
|
54
|
-
it "renders a successful response" do
|
55
|
-
get "/<%= options['scope'].downcase.pluralize %>/#{<%= options['scope'].downcase %>.id}/<%= plural_name %>"
|
56
|
-
expect(response).to be_successful
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
62
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
|
+
<% scope_namespacing do -%>
|
1
2
|
class <%= class_name.pluralize %>Controller < ApplicationController
|
2
|
-
before_action :set_<%= singular_name %>, only: %i[
|
3
|
+
before_action :set_<%= singular_name %>, only: %i[show update destroy]
|
3
4
|
|
4
5
|
def index
|
5
6
|
@<%= singular_name %> = <%= class_name %>.all
|
@@ -34,3 +35,4 @@ class <%= class_name.pluralize %>Controller < ApplicationController
|
|
34
35
|
params.require(:<%= singular_name %>).permit(<%= attributes.map { |a| ':' + a.name }.join(', ') %>)
|
35
36
|
end
|
36
37
|
end
|
38
|
+
<% end -%>
|
@@ -7,14 +7,14 @@ RSpec.describe "<%= class_name %>", type: :request do
|
|
7
7
|
describe "GET /<%= plural_name %>" do
|
8
8
|
it "returns http success" do
|
9
9
|
create(:<%= singular_table_name %>)
|
10
|
-
get "
|
10
|
+
get "<%= spec_routes[:index] %>"
|
11
11
|
expect(response).to have_http_status(:success)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
describe "GET /<%= plural_name %>/:id" do
|
16
16
|
it "returns http success" do
|
17
|
-
get "
|
17
|
+
get "<%= spec_routes[:show] %>"
|
18
18
|
expect(response).to have_http_status(:success)
|
19
19
|
end
|
20
20
|
end
|
@@ -22,7 +22,7 @@ RSpec.describe "<%= class_name %>", type: :request do
|
|
22
22
|
describe "POST /<%= plural_name %>" do
|
23
23
|
it "creates a new item" do
|
24
24
|
expect do
|
25
|
-
post "
|
25
|
+
post "<%= spec_routes[:create] %>",
|
26
26
|
params: { <%= singular_name %>: valid_attributes }
|
27
27
|
end.to change(<%= class_name %>, :count).by(1)
|
28
28
|
end
|
@@ -30,7 +30,7 @@ RSpec.describe "<%= class_name %>", type: :request do
|
|
30
30
|
|
31
31
|
describe "PATCH /<%= plural_name %>/:id" do
|
32
32
|
it "return http success" do
|
33
|
-
patch "
|
33
|
+
patch "<%= spec_routes[:update] %>",
|
34
34
|
params: { <%= singular_name %>: valid_attributes }
|
35
35
|
expect(response).to have_http_status(:success)
|
36
36
|
end
|
@@ -40,7 +40,7 @@ RSpec.describe "<%= class_name %>", type: :request do
|
|
40
40
|
it "deletes an <%= plural_name %>" do
|
41
41
|
item = create(:<%= singular_name %>)
|
42
42
|
expect do
|
43
|
-
delete "
|
43
|
+
delete "<%= spec_routes[:delete] %>"
|
44
44
|
end.to change(<%= class_name %>, :count).by(-1)
|
45
45
|
end
|
46
46
|
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RestApiGenerator
|
4
|
+
class ChildResourceController < RestApiGenerator.parent_controller.constantize
|
5
|
+
include Orderable
|
6
|
+
|
7
|
+
before_action :set_parent_resource
|
8
|
+
before_action :set_resource, only: [:show, :update, :destroy]
|
9
|
+
|
10
|
+
def index
|
11
|
+
@resources = resources
|
12
|
+
@resources = @resources.filter_resource(params_for_filter) if resource_class.include?(Filterable)
|
13
|
+
@resources = @resources.order(ordering_params(params[:sort])) if params[:sort]
|
14
|
+
render json: @resources, status: :ok
|
15
|
+
end
|
16
|
+
|
17
|
+
def show
|
18
|
+
render json: @resource, status: :ok
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
@resource = resources.create!(resource_created_params)
|
23
|
+
render json: @resource, status: :created
|
24
|
+
end
|
25
|
+
|
26
|
+
def update
|
27
|
+
@resource.update!(resource_updated_params)
|
28
|
+
render json: @resource, status: :ok
|
29
|
+
end
|
30
|
+
|
31
|
+
def destroy
|
32
|
+
@resource.destroy!
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def resources
|
38
|
+
@parent_resource.send(resource_class.to_s.downcase.pluralize)
|
39
|
+
end
|
40
|
+
|
41
|
+
def parent_resource_class
|
42
|
+
parent_resource_by_controller_name
|
43
|
+
end
|
44
|
+
|
45
|
+
def resource_class
|
46
|
+
resource_by_controller_name
|
47
|
+
end
|
48
|
+
|
49
|
+
# Params
|
50
|
+
def resource_created_params
|
51
|
+
resource_params
|
52
|
+
end
|
53
|
+
|
54
|
+
def resource_updated_params
|
55
|
+
resource_params
|
56
|
+
end
|
57
|
+
|
58
|
+
def resource_params
|
59
|
+
params.require(resource_class.model_name.singular.to_sym).permit(resource_attributes)
|
60
|
+
end
|
61
|
+
|
62
|
+
def resource_attributes
|
63
|
+
resource_class.attribute_names.map(&:to_sym)
|
64
|
+
end
|
65
|
+
|
66
|
+
def params_for_filter
|
67
|
+
params.slice(*resource_class.filter_scopes)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Before actions
|
71
|
+
def set_parent_resource
|
72
|
+
@parent_resource = parent_resource_class.find(parent_record_id)
|
73
|
+
end
|
74
|
+
|
75
|
+
def set_resource
|
76
|
+
@resource = resources.find(record_id)
|
77
|
+
end
|
78
|
+
|
79
|
+
# UsersController => User
|
80
|
+
def resource_by_controller_name(controller_name = self.class.to_s)
|
81
|
+
controller_name.split(Regexp.union(["Controller", "::"]))[-1].singularize.constantize
|
82
|
+
end
|
83
|
+
|
84
|
+
# Users::DevicesController => User
|
85
|
+
def parent_resource_by_controller_name(controller_name = self.class.to_s)
|
86
|
+
controller_name.split(Regexp.union(["Controller", "::"]))[-2].singularize.constantize
|
87
|
+
end
|
88
|
+
|
89
|
+
def parent_record_id
|
90
|
+
params.dig("#{parent_resource_class.to_s.downcase.singularize}_id")
|
91
|
+
end
|
92
|
+
|
93
|
+
def record_id
|
94
|
+
params.permit(:id)[:id]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
module RestApiGenerator
|
6
|
+
module Filterable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
@filter_scopes ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
attr_reader :filter_scopes
|
15
|
+
|
16
|
+
def filter_scope(name, *args)
|
17
|
+
scope name, *args
|
18
|
+
@filter_scopes << name.to_s.gsub("filter_by_", "").to_sym
|
19
|
+
end
|
20
|
+
|
21
|
+
def filter_resource(params)
|
22
|
+
results = where(nil)
|
23
|
+
params.each do |key, value|
|
24
|
+
results = results.public_send("filter_by_#{key}", value) if value.present?
|
25
|
+
end
|
26
|
+
results
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support"
|
4
|
+
require "active_support/concern"
|
5
|
+
|
6
|
+
module RestApiGenerator
|
7
|
+
module Orderable
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
SORT_ORDER = { " " => :asc, "+" => :asc, "-" => :desc }
|
11
|
+
|
12
|
+
# Returns params for order in active record order syntax
|
13
|
+
# GET /api/v1/transactions?sort=-amount
|
14
|
+
#
|
15
|
+
# ordering_params(params) # => { amount: :desc }
|
16
|
+
def ordering_params(order_params)
|
17
|
+
ordering = {}
|
18
|
+
if order_params
|
19
|
+
sorted_params = order_params.split(",")
|
20
|
+
sorted_params.each do |attr|
|
21
|
+
sort_sign = /\A[ +-]/.match?(attr) ? attr.slice!(0) : "+"
|
22
|
+
if resource_class.attribute_names.include?(attr)
|
23
|
+
ordering[attr] = SORT_ORDER[sort_sign]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
ordering
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RestApiGenerator
|
4
|
+
class ResourceController < RestApiGenerator.parent_controller.constantize
|
5
|
+
include Orderable
|
6
|
+
|
7
|
+
before_action :set_resource, only: [:show, :update, :destroy]
|
8
|
+
|
9
|
+
def index
|
10
|
+
@resources = resource_class.all
|
11
|
+
@resources = @resources.filter_resource(params_for_filter) if resource_class.include?(Filterable)
|
12
|
+
@resources = @resources.order(ordering_params(params[:sort])) if params[:sort]
|
13
|
+
render json: @resources, status: :ok
|
14
|
+
end
|
15
|
+
|
16
|
+
def show
|
17
|
+
render json: @resource, status: :ok
|
18
|
+
end
|
19
|
+
|
20
|
+
def create
|
21
|
+
@resource = resource_class.create!(resource_created_params)
|
22
|
+
render json: @resource, status: :created
|
23
|
+
end
|
24
|
+
|
25
|
+
def update
|
26
|
+
@resource.update!(resource_updated_params)
|
27
|
+
render json: @resource, status: :ok
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy
|
31
|
+
@resource.destroy!
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def params_for_filter
|
37
|
+
params.slice(*resource_class.filter_scopes)
|
38
|
+
end
|
39
|
+
|
40
|
+
def resource_class
|
41
|
+
resource_by_controller_name
|
42
|
+
end
|
43
|
+
|
44
|
+
def resource_created_params
|
45
|
+
resource_params
|
46
|
+
end
|
47
|
+
|
48
|
+
def resource_updated_params
|
49
|
+
resource_params
|
50
|
+
end
|
51
|
+
|
52
|
+
def resource_params
|
53
|
+
params.require(resource_class.model_name.singular.to_sym).permit(resource_attributes)
|
54
|
+
end
|
55
|
+
|
56
|
+
def resource_attributes
|
57
|
+
resource_class.attribute_names.map(&:to_sym)
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_resource
|
61
|
+
@resource = resource_class.find(record_id)
|
62
|
+
end
|
63
|
+
|
64
|
+
# UsersController => User
|
65
|
+
def resource_by_controller_name(controller_name = self.class.to_s)
|
66
|
+
controller_name.split(Regexp.union(["Controller", "::"]))[-1].singularize.constantize
|
67
|
+
end
|
68
|
+
|
69
|
+
def record_id
|
70
|
+
params.permit(:id)[:id]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/rest_api_generator.rb
CHANGED
@@ -1,11 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "rails"
|
3
4
|
require_relative "rest_api_generator/version"
|
5
|
+
require_relative "rest_api_generator/application_controller"
|
4
6
|
require_relative "rest_api_generator/error_handler"
|
5
7
|
require_relative "rest_api_generator/custom_error"
|
6
8
|
require_relative "rest_api_generator/helpers/render"
|
9
|
+
require_relative "rest_api_generator/filterable"
|
10
|
+
require_relative "rest_api_generator/orderable"
|
7
11
|
|
8
12
|
module RestApiGenerator
|
9
13
|
class Error < StandardError; end
|
10
|
-
|
14
|
+
|
15
|
+
def self.parent_controller
|
16
|
+
"RestApiGenerator::ApplicationController"
|
17
|
+
end
|
11
18
|
end
|
19
|
+
|
20
|
+
require_relative "rest_api_generator/resource_controller"
|
21
|
+
require_relative "rest_api_generator/child_resource_controller"
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
require_relative "lib/rest_api_generator/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rest-api-generator"
|
8
|
+
spec.version = RestApiGenerator::VERSION
|
9
|
+
spec.authors = ["PedroAugustoRamalhoDuarte"]
|
10
|
+
spec.email = ["pedro_aduarte@aluno.unb.br"]
|
11
|
+
|
12
|
+
spec.summary = "Build a Ruby on Rails REST API faster"
|
13
|
+
spec.description = "This gem helps you to build a Ruby on Rails REST API faster, using a scaffold-like generator that follows the best practices."
|
14
|
+
spec.homepage = "https://github.com/SwitchDreams/rest-api-generator"
|
15
|
+
spec.license = "MIT"
|
16
|
+
spec.required_ruby_version = ">= 2.6.0"
|
17
|
+
|
18
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org/"
|
19
|
+
|
20
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
21
|
+
spec.metadata["source_code_uri"] = "https://github.com/SwitchDreams/rest-api-generator"
|
22
|
+
spec.metadata["changelog_uri"] = "https://github.com/SwitchDreams/rest-api-generator"
|
23
|
+
|
24
|
+
spec.files = Dir["{bin,sig,lib,public}/**/*", "MIT-LICENSE", "Rakefile", "README.md", "rest-api-generator.gemspec",
|
25
|
+
"Gemfile", "Gemfile.lock"]
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
# For more information and examples about making a new gem, check out our
|
31
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
32
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
33
|
+
|
34
|
+
spec.add_dependency "rails", ">= 5.0"
|
35
|
+
|
36
|
+
spec.add_development_dependency 'ammeter', '~> 1.1.5'
|
37
|
+
spec.add_development_dependency 'rspec-rails', '~> 6.0.0'
|
38
|
+
spec.add_development_dependency 'sqlite3'
|
39
|
+
spec.add_development_dependency 'database_cleaner'
|
40
|
+
|
41
|
+
end
|