From 8a9728fe9a1baab155a212e5142507b7789ceccd Mon Sep 17 00:00:00 2001 From: Lee Richmond Date: Wed, 24 May 2017 18:09:52 -0400 Subject: [PATCH] Add simple generator --- lib/generators/jsonapi/resource_generator.rb | 96 +++++++++++++++++++ .../templates/application_resource.rb.erb | 5 + .../jsonapi/templates/controller.rb.erb | 45 +++++++++ .../templates/create_request_spec.rb.erb | 25 +++++ .../templates/destroy_request_spec.rb.erb | 15 +++ .../templates/index_request_spec.rb.erb | 16 ++++ .../jsonapi/templates/payload.rb.erb | 2 + .../jsonapi/templates/resource.rb.erb | 6 ++ .../jsonapi/templates/serializer.rb.erb | 5 + .../templates/show_request_spec.rb.erb | 13 +++ .../templates/update_request_spec.rb.erb | 29 ++++++ 11 files changed, 257 insertions(+) create mode 100644 lib/generators/jsonapi/resource_generator.rb create mode 100644 lib/generators/jsonapi/templates/application_resource.rb.erb create mode 100644 lib/generators/jsonapi/templates/controller.rb.erb create mode 100644 lib/generators/jsonapi/templates/create_request_spec.rb.erb create mode 100644 lib/generators/jsonapi/templates/destroy_request_spec.rb.erb create mode 100644 lib/generators/jsonapi/templates/index_request_spec.rb.erb create mode 100644 lib/generators/jsonapi/templates/payload.rb.erb create mode 100644 lib/generators/jsonapi/templates/resource.rb.erb create mode 100644 lib/generators/jsonapi/templates/serializer.rb.erb create mode 100644 lib/generators/jsonapi/templates/show_request_spec.rb.erb create mode 100644 lib/generators/jsonapi/templates/update_request_spec.rb.erb diff --git a/lib/generators/jsonapi/resource_generator.rb b/lib/generators/jsonapi/resource_generator.rb new file mode 100644 index 0000000..1312312 --- /dev/null +++ b/lib/generators/jsonapi/resource_generator.rb @@ -0,0 +1,96 @@ +module Jsonapi + class ResourceGenerator < ::Rails::Generators::NamedBase + source_root File.expand_path('../templates', __FILE__) + + class_option :'no-controller', type: :boolean, default: false + class_option :'no-serializer', type: :boolean, default: false + class_option :'no-payload', type: :boolean, default: false + class_option :'no-strong-resources', type: :boolean, default: false + class_option :'no-test', type: :boolean, default: false + + desc "This generator creates a resource file at app/resources" + def copy_resource_file + unless @options['no-controller'] + to = File.join('app/controllers', class_path, "#{file_name.pluralize}_controller.rb") + template('controller.rb.erb', to) + end + + unless @options['no-serializer'] + to = File.join('app/serializers', class_path, "serializable_#{file_name}.rb") + template('serializer.rb.erb', to) + end + + unless 'ApplicationResource'.safe_constantize + to = File.join('app/resources', class_path, "application_resource.rb") + template('application_resource.rb.erb', to) + end + + unless @options['no-payload'] + to = File.join('spec/payloads', class_path, "#{file_name}.rb") + template('payload.rb.erb', to) + end + + unless @options['no-strong-resources'] + inject_into_file 'config/initializers/strong_resources.rb', after: "StrongResources.configure do\n" do <<-STR + strong_resource :#{file_name} do + # Your attributes go here, e.g. + # attribute :name, :string + end + + STR + end + end + + unless @options['no-route'] + inject_into_file 'config/routes.rb', after: "scope '/api' do\n scope '/v1' do\n" do <<-STR + resources :#{type} + STR + end + end + + unless @options['no-test'] + to = File.join "spec/api/v1/#{file_name.pluralize}", + class_path, + "index_spec.rb" + template('index_request_spec.rb.erb', to) + + to = File.join "spec/api/v1/#{file_name.pluralize}", + class_path, + "show_spec.rb" + template('show_request_spec.rb.erb', to) + + to = File.join "spec/api/v1/#{file_name.pluralize}", + class_path, + "create_spec.rb" + template('create_request_spec.rb.erb', to) + + to = File.join "spec/api/v1/#{file_name.pluralize}", + class_path, + "update_spec.rb" + template('update_request_spec.rb.erb', to) + + to = File.join "spec/api/v1/#{file_name.pluralize}", + class_path, + "destroy_spec.rb" + template('destroy_request_spec.rb.erb', to) + end + + to = File.join('app/resources', class_path, "#{file_name}_resource.rb") + template('resource.rb.erb', to) + end + + def do_thing + puts "DO THING" + end + + private + + def model_klass + class_name.safe_constantize + end + + def type + model_klass.name.underscore.pluralize + end + end +end diff --git a/lib/generators/jsonapi/templates/application_resource.rb.erb b/lib/generators/jsonapi/templates/application_resource.rb.erb new file mode 100644 index 0000000..dde80d2 --- /dev/null +++ b/lib/generators/jsonapi/templates/application_resource.rb.erb @@ -0,0 +1,5 @@ +require 'jsonapi_compliable/adapters/active_record' + +class ApplicationResource < JsonapiCompliable::Resource + use_adapter JsonapiCompliable::Adapters::ActiveRecord +end diff --git a/lib/generators/jsonapi/templates/controller.rb.erb b/lib/generators/jsonapi/templates/controller.rb.erb new file mode 100644 index 0000000..c237752 --- /dev/null +++ b/lib/generators/jsonapi/templates/controller.rb.erb @@ -0,0 +1,45 @@ +<% module_namespacing do -%> +class <%= model_klass.name.pluralize %>Controller < ApplicationController + jsonapi resource: <%= model_klass %>Resource + + strong_resource :<%= file_name %> + + before_action :apply_strong_params, only: [:create, :update] + + def index + <%= file_name.pluralize %> = <%= model_klass %>.all + render_jsonapi(<%= file_name.pluralize %>) + end + + def show + scope = jsonapi_scope(<%= model_klass %>.where(id: params[:id])) + render_jsonapi(scope.resolve.first, scope: false) + end + + def create + <%= file_name %>, success = jsonapi_create.to_a + + if success + render_jsonapi(<%= file_name %>, scope: false) + else + render_errors_for(<%= file_name %>) + end + end + + def update + <%= file_name %>, success = jsonapi_update.to_a + + if success + render_jsonapi(<%= file_name %>, scope: false) + else + render_errors_for(<%= file_name %>) + end + end + + def destroy + <%= file_name %> = <%= model_klass %>.find(params[:id]) + <%= file_name %>.destroy + return head(:no_content) + end +end +<% end -%> diff --git a/lib/generators/jsonapi/templates/create_request_spec.rb.erb b/lib/generators/jsonapi/templates/create_request_spec.rb.erb new file mode 100644 index 0000000..7191bf5 --- /dev/null +++ b/lib/generators/jsonapi/templates/create_request_spec.rb.erb @@ -0,0 +1,25 @@ +require 'rails_helper' + +RSpec.describe "<%= type %>#create", type: :request do + context 'basic create' do + let(:payload) do + { + data: { + type: '<%= type %>', + attributes: { + # ... your attrs here + } + } + } + end + + it 'creates the resource' do + expect { + jsonapi_post "/api/v1/<%= type %>", payload + }.to change { <%= model_klass %>.count }.by(1) + <%= file_name %> = <%= model_klass %>.last + + assert_payload(:<%= file_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 new file mode 100644 index 0000000..7b6c378 --- /dev/null +++ b/lib/generators/jsonapi/templates/destroy_request_spec.rb.erb @@ -0,0 +1,15 @@ +require 'rails_helper' + +RSpec.describe "<%= type %>#destroy", type: :request do + context 'basic destroy' do + let!(:<%= file_name %>) { create(:<%= file_name %>) } + + it 'updates the resource' do + expect { + delete "/api/v1/<%= type %>/#{<%= file_name %>.id}" + }.to change { <%= model_klass %>.count }.by(-1) + + expect(response.status).to eq(204) + end + end +end diff --git a/lib/generators/jsonapi/templates/index_request_spec.rb.erb b/lib/generators/jsonapi/templates/index_request_spec.rb.erb new file mode 100644 index 0000000..8c8930e --- /dev/null +++ b/lib/generators/jsonapi/templates/index_request_spec.rb.erb @@ -0,0 +1,16 @@ +require 'rails_helper' + +RSpec.describe "<%= file_name.pluralize %>#index", type: :request do + context 'basic fetch' do + let!(:<%= file_name %>1) { create(:<%= file_name %>) } + let!(:<%= file_name %>2) { create(:<%= file_name %>) } + + it 'serializes the list correctly' do + get "/api/v1/<%= file_name.pluralize %>" + + 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]) + end + end +end diff --git a/lib/generators/jsonapi/templates/payload.rb.erb b/lib/generators/jsonapi/templates/payload.rb.erb new file mode 100644 index 0000000..e38f7a6 --- /dev/null +++ b/lib/generators/jsonapi/templates/payload.rb.erb @@ -0,0 +1,2 @@ +JsonapiSpecHelpers::Payload.register(:<%= file_name %>) do +end diff --git a/lib/generators/jsonapi/templates/resource.rb.erb b/lib/generators/jsonapi/templates/resource.rb.erb new file mode 100644 index 0000000..6fdbeda --- /dev/null +++ b/lib/generators/jsonapi/templates/resource.rb.erb @@ -0,0 +1,6 @@ +<% module_namespacing do -%> +class <%= class_name %>Resource < ApplicationResource + type :<%= type %> + model <%= model_klass %> +end +<% end -%> diff --git a/lib/generators/jsonapi/templates/serializer.rb.erb b/lib/generators/jsonapi/templates/serializer.rb.erb new file mode 100644 index 0000000..ca4c442 --- /dev/null +++ b/lib/generators/jsonapi/templates/serializer.rb.erb @@ -0,0 +1,5 @@ +<% module_namespacing do -%> +class Serializable<%= class_name %> < JSONAPI::Serializable::Resource + type :<%= type %> +end +<% end -%> diff --git a/lib/generators/jsonapi/templates/show_request_spec.rb.erb b/lib/generators/jsonapi/templates/show_request_spec.rb.erb new file mode 100644 index 0000000..91d3762 --- /dev/null +++ b/lib/generators/jsonapi/templates/show_request_spec.rb.erb @@ -0,0 +1,13 @@ +require 'rails_helper' + +RSpec.describe "<%= file_name.pluralize %>#show", type: :request do + context 'basic fetch' do + let!(:<%= file_name %>) { create(:<%= file_name %>) } + + it 'serializes the resource correctly' do + get "/api/v1/<%= file_name.pluralize %>/#{<%= file_name %>.id}" + + assert_payload(:<%= file_name %>, <%= file_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 new file mode 100644 index 0000000..8e5bef2 --- /dev/null +++ b/lib/generators/jsonapi/templates/update_request_spec.rb.erb @@ -0,0 +1,29 @@ +require 'rails_helper' + +RSpec.describe "<%= type %>#update", type: :request do + context 'basic update' do + let!(:<%= file_name %>) { create(:<%= file_name %>) } + + let(:payload) do + { + data: { + id: <%= file_name %>.id.to_s, + type: '<%= type %>', + attributes: { + # ... your attrs here + } + } + } + end + + # Replace 'xit' with 'it' after adding attributes + xit 'updates the resource' do + expect { + jsonapi_put "/api/v1/<%= type %>/#{<%= file_name %>.id}", payload + }.to change { <%= file_name %>.reload.attributes } + assert_payload(:<%= file_name %>, <%= file_name %>, json_item) + + # ... assert updates attributes ... + end + end +end