diff --git a/lib/generators/jsonapi/resource_generator.rb b/lib/generators/jsonapi/resource_generator.rb index 4b21df6..8d8a7c4 100644 --- a/lib/generators/jsonapi/resource_generator.rb +++ b/lib/generators/jsonapi/resource_generator.rb @@ -4,16 +4,16 @@ class ResourceGenerator < ::Rails::Generators::NamedBase argument :attributes, type: :array, default: [], banner: "field[:type][:index] field[:type][:index]" - class_option :'omit-comments', - type: :boolean, - default: false, - aliases: ['--omit-comments', '-c'], - desc: 'Generate without documentation comments' - class_option :'actions', - type: :array, - default: nil, - aliases: ['--actions', '-a'], - desc: 'Array of controller actions to support, e.g. "index show destroy"' + class_option :omit_comments, + type: :boolean, + default: true, + aliases: %w[-c], + desc: 'Generate without documentation comments' + class_option :actions, + type: :array, + default: nil, + aliases: %w[-a], + desc: 'Array of controller actions to support, e.g. "index show destroy"' desc "This generator creates a resource file at app/resources, as well as corresponding controller/specs/route/etc" def copy_resource_file @@ -56,7 +56,7 @@ def generate_controller end def generate_serializer - to = File.join('app/serializers', class_path, "serializable_#{file_name}.rb") + to = File.join('app/serializers', class_path, "#{serializable_file_name}.rb") template('serializer.rb.erb', to) end @@ -74,7 +74,7 @@ def docs_controller? end def generate_swagger - code = " jsonapi_resource '/v1/#{type}'" + code = " jsonapi_resource '/v1/#{url}'" code << ", only: [#{actions.map { |a| ":#{a}" }.join(', ')}]" if actions.length < 5 code << "\n" inject_into_file 'app/controllers/docs_controller.rb', before: /^end/ do @@ -88,7 +88,7 @@ def generate_spec_payload end def generate_strong_resource - code = " strong_resource :#{file_name} do\n" + code = " strong_resource :#{singular_table_name} do\n" attributes.each do |a| type = a.type type = :string if type == :text @@ -106,44 +106,42 @@ def generate_route code = " resources :#{type}" code << ", only: [#{actions.map { |a| ":#{a}" }.join(', ')}]" if actions.length < 5 code << "\n" - inject_into_file 'config/routes.rb', after: "scope path: '/v1' do\n" do + + unless type == url + code = code.gsub("resources :#{type}", "resources :#{file_name.pluralize}") + url.split('/')[0..-2].reverse.each do |namespace| + code = " namespace :#{namespace} do\n#{indent(code).chomp}\n end\n" + end + end + + inject_into_file 'config/routes.rb', after: /scope path: (['"])\/v1(['"]) do\n/ do code end end def generate_tests if actions?('index') - to = File.join "spec/api/v1/#{file_name.pluralize}", - class_path, - "index_spec.rb" + to = File.join "spec/api/v1", url, "index_spec.rb" template('index_request_spec.rb.erb', to) end if actions?('show') - to = File.join "spec/api/v1/#{file_name.pluralize}", - class_path, - "show_spec.rb" + to = File.join "spec/api/v1", url, "show_spec.rb" template('show_request_spec.rb.erb', to) end if actions?('create') - to = File.join "spec/api/v1/#{file_name.pluralize}", - class_path, - "create_spec.rb" + to = File.join "spec/api/v1", url, "create_spec.rb" template('create_request_spec.rb.erb', to) end if actions?('update') - to = File.join "spec/api/v1/#{file_name.pluralize}", - class_path, - "update_spec.rb" + to = File.join "spec/api/v1", url, "update_spec.rb" template('update_request_spec.rb.erb', to) end if actions?('destroy') - to = File.join "spec/api/v1/#{file_name.pluralize}", - class_path, - "destroy_spec.rb" + to = File.join "spec/api/v1", url, "destroy_spec.rb" template('destroy_request_spec.rb.erb', to) end end @@ -187,12 +185,24 @@ def api_namespace end end + def serializable_file_name + "serializable_#{file_name}" + end + + def serializable_class_name + (class_path + [serializable_file_name]).map!(&:camelize).join("::") + end + def model_klass class_name.safe_constantize end def type - model_klass.name.underscore.pluralize + model_klass.model_name.plural + end + + def url + model_klass.model_name.collection end end end diff --git a/lib/generators/jsonapi/templates/controller.rb.erb b/lib/generators/jsonapi/templates/controller.rb.erb index 3cf7207..5067bbe 100644 --- a/lib/generators/jsonapi/templates/controller.rb.erb +++ b/lib/generators/jsonapi/templates/controller.rb.erb @@ -10,7 +10,7 @@ class <%= model_klass.name.pluralize %>Controller < ApplicationController # Reference a strong resource payload defined in # config/initializers/strong_resources.rb <%- end -%> - strong_resource :<%= file_name %> + strong_resource :<%= singular_table_name %> <%- end -%> <%- if actions?('create', 'update') -%> <%- unless omit_comments? -%> diff --git a/lib/generators/jsonapi/templates/create_request_spec.rb.erb b/lib/generators/jsonapi/templates/create_request_spec.rb.erb index c1c1556..a87f6f6 100644 --- a/lib/generators/jsonapi/templates/create_request_spec.rb.erb +++ b/lib/generators/jsonapi/templates/create_request_spec.rb.erb @@ -1,8 +1,8 @@ require 'rails_helper' -RSpec.describe "<%= type %>#create", type: :request do +RSpec.describe "<%= url %>#create", type: :request do subject(:make_request) do - jsonapi_post "/<%= api_namespace %>/v1/<%= type %>", payload + jsonapi_post "/<%= api_namespace %>/v1/<%= url %>", payload end describe 'basic create' do @@ -10,9 +10,7 @@ RSpec.describe "<%= type %>#create", type: :request do { data: { type: '<%= type %>', - attributes: { - # ... your attrs here - } + attributes: attributes_for(:<%= singular_table_name %>) } } end @@ -23,7 +21,7 @@ RSpec.describe "<%= type %>#create", type: :request do }.to change { <%= model_klass %>.count }.by(1) <%= file_name %> = <%= model_klass %>.last - assert_payload(:<%= file_name %>, <%= file_name %>, json_item) + assert_payload(:<%= singular_table_name %>, <%= file_name %>, json_item) end end end diff --git a/lib/generators/jsonapi/templates/destroy_request_spec.rb.erb b/lib/generators/jsonapi/templates/destroy_request_spec.rb.erb index 0d375a1..f81d20d 100644 --- a/lib/generators/jsonapi/templates/destroy_request_spec.rb.erb +++ b/lib/generators/jsonapi/templates/destroy_request_spec.rb.erb @@ -1,12 +1,12 @@ require 'rails_helper' -RSpec.describe "<%= type %>#destroy", type: :request do +RSpec.describe "<%= url %>#destroy", type: :request do subject(:make_request) do - jsonapi_delete "/<%= api_namespace %>/v1/<%= type %>/#{<%= file_name %>.id}" + jsonapi_delete "/<%= api_namespace %>/v1/<%= url %>/#{<%= singular_table_name %>.id}" end describe 'basic destroy' do - let!(:<%= file_name %>) { create(:<%= file_name %>) } + let!(:<%= singular_table_name %>) { create(:<%= singular_table_name %>) } it 'updates the resource' do expect { diff --git a/lib/generators/jsonapi/templates/index_request_spec.rb.erb b/lib/generators/jsonapi/templates/index_request_spec.rb.erb index a9303e2..855a0d3 100644 --- a/lib/generators/jsonapi/templates/index_request_spec.rb.erb +++ b/lib/generators/jsonapi/templates/index_request_spec.rb.erb @@ -1,22 +1,22 @@ require 'rails_helper' -RSpec.describe "<%= file_name.pluralize %>#index", type: :request do +RSpec.describe "<%= url %>#index", type: :request do let(:params) { {} } subject(:make_request) do - jsonapi_get "/<%= api_namespace %>/v1/<%= file_name.pluralize %>", + jsonapi_get "/<%= api_namespace %>/v1/<%= url %>", params: params end describe 'basic fetch' do - let!(:<%= file_name %>1) { create(:<%= file_name %>) } - let!(:<%= file_name %>2) { create(:<%= file_name %>) } + let!(:<%= singular_table_name %>1) { create(:<%= singular_table_name %>) } + let!(:<%= singular_table_name %>2) { create(:<%= singular_table_name %>) } it 'serializes the list correctly' do make_request - expect(json_ids(true)).to match_array([<%= file_name %>1.id, <%= file_name %>2.id]) - assert_payload(:<%= file_name %>, <%= file_name %>1, json_items[0]) - assert_payload(:<%= file_name %>, <%= file_name %>2, json_items[1]) + expect(json_ids(true)).to match_array([<%= singular_table_name %>1.id, <%= singular_table_name %>2.id]) + assert_payload(:<%= singular_table_name %>, <%= singular_table_name %>1, json_items[0]) + assert_payload(:<%= singular_table_name %>, <%= singular_table_name %>2, json_items[1]) end end end diff --git a/lib/generators/jsonapi/templates/payload.rb.erb b/lib/generators/jsonapi/templates/payload.rb.erb index 78b3697..66f1ef6 100644 --- a/lib/generators/jsonapi/templates/payload.rb.erb +++ b/lib/generators/jsonapi/templates/payload.rb.erb @@ -29,7 +29,7 @@ # # For more information, see https://jsonapi-suite.github.io/jsonapi_spec_helpers/ <%- end -%> -JsonapiSpecHelpers::Payload.register(:<%= file_name %>) do +JsonapiSpecHelpers::Payload.register(:<%= singular_table_name %>) do <%- attributes.each do |a| -%> <%- type = a.type == :boolean ? [TrueClass, FalseClass] : a.type.to_s.classify -%> <%- type = String if a.type == :text -%> diff --git a/lib/generators/jsonapi/templates/serializer.rb.erb b/lib/generators/jsonapi/templates/serializer.rb.erb index 9525b5d..4832365 100644 --- a/lib/generators/jsonapi/templates/serializer.rb.erb +++ b/lib/generators/jsonapi/templates/serializer.rb.erb @@ -3,7 +3,7 @@ # We use jsonapi-rb, which is similar to active_model_serializers. <%- end -%> <% module_namespacing do -%> -class Serializable<%= class_name %> < JSONAPI::Serializable::Resource +class <%= serializable_class_name %> < JSONAPI::Serializable::Resource type :<%= type %> <%- unless omit_comments? -%> diff --git a/lib/generators/jsonapi/templates/show_request_spec.rb.erb b/lib/generators/jsonapi/templates/show_request_spec.rb.erb index f1e089c..05cf71e 100644 --- a/lib/generators/jsonapi/templates/show_request_spec.rb.erb +++ b/lib/generators/jsonapi/templates/show_request_spec.rb.erb @@ -1,19 +1,19 @@ require 'rails_helper' -RSpec.describe "<%= file_name.pluralize %>#show", type: :request do +RSpec.describe "<%= url %>#show", type: :request do let(:params) { {} } subject(:make_request) do - jsonapi_get "/<%= api_namespace %>/v1/<%= file_name.pluralize %>/#{<%= file_name %>.id}", + jsonapi_get "/<%= api_namespace %>/v1/<%= url %>/#{<%= singular_table_name %>.id}", params: params end describe 'basic fetch' do - let!(:<%= file_name %>) { create(:<%= file_name %>) } + let!(:<%= singular_table_name %>) { create(:<%= singular_table_name %>) } it 'serializes the resource correctly' do make_request - assert_payload(:<%= file_name %>, <%= file_name %>, json_item) + assert_payload(:<%= singular_table_name %>, <%= singular_table_name %>, json_item) end end end diff --git a/lib/generators/jsonapi/templates/update_request_spec.rb.erb b/lib/generators/jsonapi/templates/update_request_spec.rb.erb index 846f546..d938359 100644 --- a/lib/generators/jsonapi/templates/update_request_spec.rb.erb +++ b/lib/generators/jsonapi/templates/update_request_spec.rb.erb @@ -1,31 +1,29 @@ require 'rails_helper' -RSpec.describe "<%= type %>#update", type: :request do +RSpec.describe "<%= url %>#update", type: :request do subject(:make_request) do - jsonapi_put "/<%= api_namespace %>/v1/<%= type %>/#{<%= file_name %>.id}", payload + jsonapi_put "/<%= api_namespace %>/v1/<%= url %>/#{<%= singular_table_name %>.id}", payload end describe 'basic update' do - let!(:<%= file_name %>) { create(:<%= file_name %>) } + let!(:<%= singular_table_name %>) { create(:<%= singular_table_name %>) } let(:payload) do { data: { - id: <%= file_name %>.id.to_s, + id: <%= singular_table_name %>.id.to_s, type: '<%= type %>', - attributes: { - # ... your attrs here - } + attributes: attributes_for(:<%= singular_table_name %>) } } end # Replace 'xit' with 'it' after adding attributes - xit 'updates the resource' do + it 'updates the resource' do expect { make_request - }.to change { <%= file_name %>.reload.attributes } - assert_payload(:<%= file_name %>, <%= file_name %>, json_item) + }.to change { <%= singular_table_name %>.reload.attributes } + assert_payload(:<%= singular_table_name %>, <%= singular_table_name %>, json_item) # ... assert updates attributes ... end diff --git a/lib/jsonapi_compliable/base.rb b/lib/jsonapi_compliable/base.rb index 55d380b..178cfe0 100644 --- a/lib/jsonapi_compliable/base.rb +++ b/lib/jsonapi_compliable/base.rb @@ -84,7 +84,7 @@ def jsonapi(foo = 'bar', resource: nil, &blk) # # # # ...will only sideload comments # - # @param [Hash, Array, Symbol] whitelist + # @param hash [Hash, Array, Symbol] # @see Query#include_hash def sideload_whitelist(hash) self._sideload_whitelist = JSONAPI::IncludeDirective.new(hash).to_hash