Skip to content
70 changes: 40 additions & 30 deletions lib/generators/jsonapi/resource_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
2 changes: 1 addition & 1 deletion lib/generators/jsonapi/templates/controller.rb.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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? -%>
Expand Down
10 changes: 4 additions & 6 deletions lib/generators/jsonapi/templates/create_request_spec.rb.erb
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
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
let(:payload) do
{
data: {
type: '<%= type %>',
attributes: {
# ... your attrs here
}
attributes: attributes_for(:<%= singular_table_name %>)
}
}
end
Expand All @@ -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
6 changes: 3 additions & 3 deletions lib/generators/jsonapi/templates/destroy_request_spec.rb.erb
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
14 changes: 7 additions & 7 deletions lib/generators/jsonapi/templates/index_request_spec.rb.erb
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion lib/generators/jsonapi/templates/payload.rb.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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 -%>
Expand Down
2 changes: 1 addition & 1 deletion lib/generators/jsonapi/templates/serializer.rb.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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? -%>
Expand Down
8 changes: 4 additions & 4 deletions lib/generators/jsonapi/templates/show_request_spec.rb.erb
Original file line number Diff line number Diff line change
@@ -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
18 changes: 8 additions & 10 deletions lib/generators/jsonapi/templates/update_request_spec.rb.erb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/jsonapi_compliable/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down