rockstart 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +100 -0
  4. data/Rakefile +19 -0
  5. data/lib/generators/rockstart/USAGE +13 -0
  6. data/lib/generators/rockstart/devise/USAGE +9 -0
  7. data/lib/generators/rockstart/devise/devise_generator.rb +258 -0
  8. data/lib/generators/rockstart/devise/templates/controllers/passwords_controller.rb +56 -0
  9. data/lib/generators/rockstart/devise/templates/controllers/registrations_controller.rb +88 -0
  10. data/lib/generators/rockstart/devise/templates/controllers/sessions_controller.rb +32 -0
  11. data/lib/generators/rockstart/devise/templates/create_user_migration.rb.tt +11 -0
  12. data/lib/generators/rockstart/devise/templates/models/user.rb +42 -0
  13. data/lib/generators/rockstart/devise/templates/spec/factories/users.rb +17 -0
  14. data/lib/generators/rockstart/devise/templates/spec/models/user_spec.rb +64 -0
  15. data/lib/generators/rockstart/devise/templates/spec/requests/users/passwords_spec.rb +202 -0
  16. data/lib/generators/rockstart/devise/templates/spec/requests/users/registrations_spec.rb +445 -0
  17. data/lib/generators/rockstart/devise/templates/spec/requests/users/sessions_spec.rb +171 -0
  18. data/lib/generators/rockstart/devise/templates/spec/support/devise_request_spec_helper.rb +29 -0
  19. data/lib/generators/rockstart/devise/templates/translations.en.yml +4 -0
  20. data/lib/generators/rockstart/docker/USAGE +10 -0
  21. data/lib/generators/rockstart/docker/docker_generator.rb +86 -0
  22. data/lib/generators/rockstart/docker/templates/app/Dockerfile-app +47 -0
  23. data/lib/generators/rockstart/docker/templates/docker-compose.test.yml +29 -0
  24. data/lib/generators/rockstart/docker/templates/docker-compose.yml +47 -0
  25. data/lib/generators/rockstart/docker/templates/dockerignore +16 -0
  26. data/lib/generators/rockstart/docker/templates/dotenv.docker.tt +4 -0
  27. data/lib/generators/rockstart/docker/templates/localhost_domains.ext.tt +7 -0
  28. data/lib/generators/rockstart/docker/templates/setup-localhost.tt +27 -0
  29. data/lib/generators/rockstart/docker/templates/web/Dockerfile-web +15 -0
  30. data/lib/generators/rockstart/docker/templates/web/nginx.conf +62 -0
  31. data/lib/generators/rockstart/frontend_helpers/USAGE +8 -0
  32. data/lib/generators/rockstart/frontend_helpers/frontend_helpers_generator.rb +65 -0
  33. data/lib/generators/rockstart/frontend_helpers/templates/application_urls.rb +26 -0
  34. data/lib/generators/rockstart/frontend_helpers/templates/application_urls_helper.rb +20 -0
  35. data/lib/generators/rockstart/frontend_helpers/templates/titles.en.yml.tt +5 -0
  36. data/lib/generators/rockstart/logging/USAGE +8 -0
  37. data/lib/generators/rockstart/logging/logging_generator.rb +12 -0
  38. data/lib/generators/rockstart/logging/templates/rockstart/lograge_initializer.rb +50 -0
  39. data/lib/generators/rockstart/postgres/USAGE +8 -0
  40. data/lib/generators/rockstart/postgres/postgres_generator.rb +32 -0
  41. data/lib/generators/rockstart/postgres/templates/config/database.yml.tt +18 -0
  42. data/lib/generators/rockstart/postgres/templates/migration.rb.tt +7 -0
  43. data/lib/generators/rockstart/pundit/USAGE +8 -0
  44. data/lib/generators/rockstart/pundit/pundit_generator.rb +32 -0
  45. data/lib/generators/rockstart/pundit/templates/app/controllers/concerns/pundit_error_handling.rb +29 -0
  46. data/lib/generators/rockstart/pundit/templates/app/policies/application_policy.rb +71 -0
  47. data/lib/generators/rockstart/pundit/templates/app/policies/user_policy.rb +47 -0
  48. data/lib/generators/rockstart/pundit/templates/config/locales/pundit.en.yml +6 -0
  49. data/lib/generators/rockstart/pundit/templates/lib/templates/pundit/policy/policy.rb +36 -0
  50. data/lib/generators/rockstart/pundit/templates/lib/templates/rspec/policy/policy_spec.rb +58 -0
  51. data/lib/generators/rockstart/pundit/templates/spec/policies/user_policy_spec.rb +95 -0
  52. data/lib/generators/rockstart/pundit/templates/spec/support/pundit_matchers.rb +7 -0
  53. data/lib/generators/rockstart/quality/USAGE +10 -0
  54. data/lib/generators/rockstart/quality/quality_generator.rb +28 -0
  55. data/lib/generators/rockstart/quality/templates/quality.rake +4 -0
  56. data/lib/generators/rockstart/quality/templates/rubocop.rake +4 -0
  57. data/lib/generators/rockstart/quality/templates/rubocop.yml +45 -0
  58. data/lib/generators/rockstart/rockstart_generator.rb +77 -0
  59. data/lib/generators/rockstart/rspec/USAGE +8 -0
  60. data/lib/generators/rockstart/rspec/rspec_generator.rb +70 -0
  61. data/lib/generators/rockstart/rspec/templates/dotenv.development +1 -0
  62. data/lib/generators/rockstart/rspec/templates/dotenv.test +1 -0
  63. data/lib/generators/rockstart/rspec/templates/rspec_templates/model/model_spec.rb +13 -0
  64. data/lib/generators/rockstart/rspec/templates/support/factory_bot.rb +6 -0
  65. data/lib/generators/rockstart/rspec/templates/support/shoulda_matchers.rb +9 -0
  66. data/lib/generators/rockstart/rspec/templates/support/test_helpers.rb +9 -0
  67. data/lib/generators/rockstart/scaffold_templates/USAGE +8 -0
  68. data/lib/generators/rockstart/scaffold_templates/scaffold_templates_generator.rb +39 -0
  69. data/lib/generators/rockstart/scaffold_templates/templates/api_controller.rb.tt +96 -0
  70. data/lib/generators/rockstart/scaffold_templates/templates/controller.rb.tt +126 -0
  71. data/lib/generators/rockstart/scaffold_templates/templates/rspec/scaffold/api_request_spec.rb +139 -0
  72. data/lib/generators/rockstart/scaffold_templates/templates/rspec/scaffold/request_spec.rb +408 -0
  73. data/lib/generators/rockstart/security/USAGE +13 -0
  74. data/lib/generators/rockstart/security/security_generator.rb +108 -0
  75. data/lib/generators/rockstart/security/templates/brakeman.rake +6 -0
  76. data/lib/generators/rockstart/security/templates/bundler_audit.rake +4 -0
  77. data/lib/generators/rockstart/security/templates/cache_support.rb +18 -0
  78. data/lib/generators/rockstart/security/templates/content_security_policy_initializer.rb.tt +56 -0
  79. data/lib/generators/rockstart/security/templates/content_security_spec.rb.tt +83 -0
  80. data/lib/generators/rockstart/security/templates/csp_violations_controller.rb +39 -0
  81. data/lib/generators/rockstart/security/templates/rack_attack.rb +98 -0
  82. data/lib/generators/rockstart/security/templates/security.rake +9 -0
  83. data/lib/generators/rockstart/security/templates/session_store_initializer.rb.tt +7 -0
  84. data/lib/generators/rockstart/smtp_mailer/USAGE +8 -0
  85. data/lib/generators/rockstart/smtp_mailer/smtp_mailer_generator.rb +30 -0
  86. data/lib/generators/rockstart/smtp_mailer/templates/config/initializers/action_mailer.rb +10 -0
  87. data/lib/generators/rockstart/tailwindcss/USAGE +8 -0
  88. data/lib/generators/rockstart/tailwindcss/tailwindcss_generator.rb +30 -0
  89. data/lib/generators/rockstart/tailwindcss/templates/application.css +3 -0
  90. data/lib/generators/rockstart/tailwindcss/templates/postcss.config.js +32 -0
  91. data/lib/rockstart/base_generator.rb +32 -0
  92. data/lib/rockstart/env.rb +16 -0
  93. data/lib/rockstart/railtie.rb +6 -0
  94. data/lib/rockstart/version.rb +5 -0
  95. data/lib/rockstart.rb +9 -0
  96. data/lib/tasks/rockstart_tasks.rake +5 -0
  97. metadata +187 -0
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RockstartGenerator < Rails::Generators::Base
4
+ desc "The quickest way for getting Rails Ready to Rock!"
5
+
6
+ class_option :devise, type: :boolean,
7
+ desc: "Include Devise support",
8
+ default: true
9
+
10
+ class_option :postgres, type: :boolean,
11
+ desc: "Include Postgres support",
12
+ default: Rockstart::Env.postgres_db?
13
+
14
+ class_option :pundit, type: :boolean,
15
+ desc: "Include Pundit support",
16
+ default: true
17
+
18
+ def generate_logging
19
+ generate "rockstart:logging"
20
+ end
21
+
22
+ def generate_rspec
23
+ generate "rockstart:rspec"
24
+ end
25
+
26
+ def generate_postgres
27
+ return unless options[:postgres]
28
+
29
+ generate "rockstart:postgres"
30
+ end
31
+
32
+ def generate_smtp_mailer
33
+ generate "rockstart:smtp_mailer"
34
+ end
35
+
36
+ def generate_scaffold_templates
37
+ generate "rockstart:scaffold_templates", devise_option, pundit_option
38
+ end
39
+
40
+ def generate_devise
41
+ return unless options[:devise]
42
+
43
+ generate "rockstart:devise", pundit_option
44
+ end
45
+
46
+ def generate_pundit
47
+ return unless options[:pundit]
48
+
49
+ generate "rockstart:pundit"
50
+ end
51
+
52
+ def generate_security
53
+ generate "rockstart:security"
54
+ end
55
+
56
+ def generate_docker
57
+ generate "rockstart:docker", postgres_option, devise_option
58
+ end
59
+
60
+ def generate_quality
61
+ generate "rockstart:quality"
62
+ end
63
+
64
+ private
65
+
66
+ def devise_option
67
+ options[:devise] ? "--devise" : "--no-devise"
68
+ end
69
+
70
+ def postgres_option
71
+ options[:postgres] ? "--postgres" : "--no-postgres"
72
+ end
73
+
74
+ def pundit_option
75
+ options[:pundit] ? "--pundit" : "--no-pundit"
76
+ end
77
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Installs RSpec with test libraries
3
+
4
+ Example:
5
+ rails generate rockstart:rspec
6
+
7
+ This will create:
8
+ - installs rspec-rails
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Rockstart::RspecGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("templates", __dir__)
5
+
6
+ def add_gems
7
+ gem "dotenv-rails", groups: %i[development test]
8
+ gem "factory_bot_rails", group: %i[development test]
9
+ gem "faker", group: %i[development test]
10
+ gem "rspec-rails", "~> 4.0.0", group: %i[development test]
11
+ gem "shoulda-matchers", group: :test
12
+ gem "simplecov", group: :test
13
+ end
14
+
15
+ def install_rspec_rails
16
+ Bundler.with_clean_env do
17
+ run "bundle install --quiet"
18
+
19
+ Dir.mktmpdir do |dir|
20
+ generate_rspec_install(dir)
21
+ template File.join(dir, ".rspec"), ".rspec"
22
+ directory File.join(dir, "spec"), "spec"
23
+ end
24
+ end
25
+ end
26
+
27
+ def add_dotenv_files
28
+ copy_file "dotenv.development", ".env.development"
29
+ copy_file "dotenv.test", ".env.test"
30
+ end
31
+
32
+ def add_rspec_support
33
+ directory "support", "spec/support"
34
+ end
35
+
36
+ def add_coverage_to_gitignore
37
+ append_file ".gitignore", "coverage/\n"
38
+ end
39
+
40
+ private
41
+
42
+ def generate_rspec_install(dir)
43
+ require "generators/rspec/install/install_generator"
44
+
45
+ initializer = ::Rspec::Generators::InstallGenerator.new(
46
+ report_stream: StringIO.new
47
+ )
48
+ initializer.destination_root = dir
49
+ initializer.invoke_all
50
+
51
+ prepend_simplecov_start(dir)
52
+ enable_support_directory(dir)
53
+ end
54
+
55
+ def prepend_simplecov_start(dir)
56
+ prepend_file File.join(dir, "spec", "spec_helper.rb"), <<~SIMPLECOV
57
+ # frozen_string_literal: true
58
+
59
+ require "simplecov"
60
+ SimpleCov.start("rails") do
61
+ add_filter "/lib/templates"
62
+ end
63
+
64
+ SIMPLECOV
65
+ end
66
+
67
+ def enable_support_directory(dir)
68
+ uncomment_lines File.join(dir, "spec", "rails_helper.rb"), /Dir.+spec.+support.+\.rb/
69
+ end
70
+ end
@@ -0,0 +1 @@
1
+ APP_HOST=www.example.com
@@ -0,0 +1 @@
1
+ APP_HOST=localhost:3000
@@ -0,0 +1,13 @@
1
+ require "rails_helper"
2
+
3
+ <% module_namespacing do -%>
4
+ RSpec.describe <%= class_name %>, <%= type_metatag(:model) %> do
5
+ <%- for attribute in attributes -%>
6
+ # <%= attribute.name %>:<%= attribute.type %>
7
+ it { is_expected.to have_db_column(:<%= attribute.name %>) }
8
+ <%- if %w(email name title).include?(attribute.name) -%>
9
+ it { is_expected.to validate_presence_of(:<%= attribute.name %>) }
10
+ <%- end -%>
11
+ <%- end -%>
12
+ end
13
+ <% end -%>
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.configure do |config|
4
+ # Allow direct use of FactoryBot methods
5
+ config.include FactoryBot::Syntax::Methods
6
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Configure shoulda-matchers
4
+ Shoulda::Matchers.configure do |config|
5
+ config.integrate do |with|
6
+ with.test_framework :rspec
7
+ with.library :rails
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.configure do |config|
4
+ # Allow direct use of t() and l() in specs
5
+ config.include AbstractController::Translation
6
+
7
+ # Allow have_selector matcher in request specs
8
+ config.include Capybara::RSpecMatchers, type: :request
9
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Overrides the default rails scaffold templates with pre-configured defaults
3
+
4
+ Example:
5
+ rails generate rockstart:scaffold_templates
6
+
7
+ This will create:
8
+ Overrides rails scaffold_controller generator templates
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Rockstart::ScaffoldTemplatesGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("templates", __dir__)
5
+
6
+ class_option :devise, type: :boolean,
7
+ desc: "Include Devise support",
8
+ default: true
9
+
10
+ class_option :pundit, type: :boolean,
11
+ desc: "Include Pundit support",
12
+ default: true
13
+
14
+ def copy_scaffold_templates
15
+ template "api_controller.rb.tt", "lib/templates/rails/scaffold_controller/api_controller.rb.tt"
16
+ template "controller.rb.tt", "lib/templates/rails/scaffold_controller/controller.rb.tt"
17
+ end
18
+
19
+ def copy_rspec_scaffold_templates
20
+ copy_file "rspec/scaffold/api_request_spec.rb",
21
+ "#{rspec_templates_dir}/scaffold/api_request_spec.rb"
22
+ copy_file "rspec/scaffold/request_spec.rb",
23
+ "#{rspec_templates_dir}/scaffold/request_spec.rb"
24
+ end
25
+
26
+ private
27
+
28
+ def devise?
29
+ options[:devise]
30
+ end
31
+
32
+ def pundit?
33
+ options[:pundit]
34
+ end
35
+
36
+ def rspec_templates_dir
37
+ @rspec_templates_dir ||= "lib/templates/rspec"
38
+ end
39
+ end
@@ -0,0 +1,96 @@
1
+ <%% if namespaced? -%>
2
+ require_dependency "<%%= namespaced_path %>/application_controller"
3
+
4
+ <%% end -%>
5
+ <%% module_namespacing do -%>
6
+ class <%%= controller_class_name %>Controller < ApplicationController
7
+ <%- if devise? -%>
8
+ before_action :authenticate_user!
9
+ <%- end -%>
10
+ before_action :assign_<%%= singular_table_name %>, only: [:show, :update, :destroy]
11
+ <%- if pundit? -%>
12
+ after_action :verify_authorized
13
+ after_action :verify_policy_scoped, except: [:new, :create]
14
+ <%- end -%>
15
+
16
+ # GET <%%= route_url %>
17
+ def index
18
+ <%- if pundit? -%>
19
+ authorize <%%= class_name %>
20
+ @<%%= plural_table_name %> = policy_scope(<%%= class_name %>)
21
+ <%- else -%>
22
+ @<%%= plural_table_name %> = <%%= orm_class.all(class_name) %>
23
+ <%- end -%>
24
+
25
+ render json: <%%= "@#{plural_table_name}" %>
26
+ end
27
+
28
+ # GET <%%= route_url %>/1
29
+ def show
30
+ <%- if pundit? -%>
31
+ authorize @<%%= singular_table_name %>
32
+
33
+ <%- end -%>
34
+ render json: <%%= "@#{singular_table_name}" %>
35
+ end
36
+
37
+ # POST <%%= route_url %>
38
+ def create
39
+ @<%%= singular_table_name %> = <%%= orm_class.build(class_name, "#{singular_table_name}_params") %>
40
+ <%- if pundit? -%>
41
+ authorize @<%%= singular_table_name %>
42
+ <%- end -%>
43
+
44
+ if @<%%= orm_instance.save %>
45
+ render json: <%%= "@#{singular_table_name}" %>, status: :created, location: <%%= "@#{singular_table_name}" %>
46
+ else
47
+ render json: <%%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity
48
+ end
49
+ end
50
+
51
+ # PATCH/PUT <%%= route_url %>/1
52
+ def update
53
+ <%- if pundit? -%>
54
+ authorize @<%%= singular_table_name %>
55
+
56
+ <%- end -%>
57
+ if @<%%= orm_instance.update("#{singular_table_name}_params") %>
58
+ render json: <%%= "@#{singular_table_name}" %>
59
+ else
60
+ render json: <%%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity
61
+ end
62
+ end
63
+
64
+ # DELETE <%%= route_url %>/1
65
+ def destroy
66
+ <%- if pundit? -%>
67
+ authorize @<%%= singular_table_name %>
68
+
69
+ <%- end -%>
70
+ @<%%= orm_instance.destroy %>
71
+ end
72
+
73
+ private
74
+ # Use callbacks to share common setup or constraints between actions.
75
+ def assign_<%%= singular_table_name %>
76
+ <%- if pundit? -%>
77
+ @<%%= singular_table_name %> = <%%= orm_class.find("policy_scope(#{class_name})", "params[:id]") %>
78
+ <%- else -%>
79
+ @<%%= singular_table_name %> = <%%= orm_class.find(class_name, "params[:id]") %>
80
+ <%- end -%>
81
+ end
82
+
83
+ # Only allow a trusted parameter "white list" through.
84
+ def <%%= "#{singular_table_name}_params" %>
85
+ <%- if pundit? -%>
86
+ permitted_attributes(@<%%= singular_table_name %> || <%%= class_name %>)
87
+ <%- else -%>
88
+ <%%- if attributes_names.empty? -%>
89
+ params.fetch(:<%%= singular_table_name %>, {})
90
+ <%%- else -%>
91
+ params.require(:<%%= singular_table_name %>).permit(<%%= permitted_params %>)
92
+ <%%- end -%>
93
+ <%- end -%>
94
+ end
95
+ end
96
+ <%% end -%>
@@ -0,0 +1,126 @@
1
+ <%% if namespaced? -%>
2
+ require_dependency "<%%= namespaced_path %>/application_controller"
3
+
4
+ <%% end -%>
5
+ <%% module_namespacing do -%>
6
+ class <%%= controller_class_name %>Controller < ApplicationController
7
+ <%- if pundit? -%>
8
+ include PunditErrorHandling
9
+
10
+ <%- end -%>
11
+ <%- if devise? -%>
12
+ before_action :authenticate_user!
13
+ <%- end -%>
14
+ before_action :assign_<%%= singular_table_name %>, only: [:show, :edit, :update, :destroy]
15
+ <%- if pundit? -%>
16
+ after_action :verify_authorized
17
+ after_action :verify_policy_scoped, except: [:new, :create]
18
+ <%- end -%>
19
+
20
+ # GET <%%= route_url %>
21
+ def index
22
+ <%- if pundit? -%>
23
+ authorize <%%= class_name %>
24
+ @<%%= plural_table_name %> = policy_scope(<%%= class_name %>)
25
+ <%- else -%>
26
+ @<%%= plural_table_name %> = <%%= orm_class.all(class_name) %>
27
+ <%- end -%>
28
+ end
29
+
30
+ # GET <%%= route_url %>/1
31
+ def show
32
+ <%- if pundit? -%>
33
+ authorize @<%%= singular_table_name %>
34
+ <%- end -%>
35
+ end
36
+
37
+ # GET <%%= route_url %>/new
38
+ def new
39
+ @<%%= singular_table_name %> = <%%= orm_class.build(class_name) %>
40
+ <%- if pundit? -%>
41
+ authorize @<%%= singular_table_name %>
42
+ <%- end -%>
43
+ end
44
+
45
+ # GET <%%= route_url %>/1/edit
46
+ def edit
47
+ <%- if pundit? -%>
48
+ authorize @<%%= singular_table_name %>
49
+ <%- end -%>
50
+ end
51
+
52
+ # POST <%%= route_url %>
53
+ def create
54
+ @<%%= singular_table_name %> = <%%= orm_class.build(class_name, "#{singular_table_name}_params") %>
55
+ <%- if pundit? -%>
56
+ authorize @<%%= singular_table_name %>
57
+ <%- end -%>
58
+
59
+ if @<%%= orm_instance.save %>
60
+ redirect_to <%%= redirect_resource_name %>, notice: <%%= "'#{human_name} was successfully created.'" %>
61
+ else
62
+ render :new
63
+ end
64
+ end
65
+
66
+ # PATCH/PUT <%%= route_url %>/1
67
+ def update
68
+ <%- if pundit? -%>
69
+ authorize @<%%= singular_table_name %>
70
+
71
+ <%- end -%>
72
+ if @<%%= orm_instance.update("#{singular_table_name}_params") %>
73
+ redirect_to <%%= redirect_resource_name %>, notice: <%%= "'#{human_name} was successfully updated.'" %>
74
+ else
75
+ render :edit
76
+ end
77
+ end
78
+
79
+ # DELETE <%%= route_url %>/1
80
+ def destroy
81
+ <%- if pundit? -%>
82
+ authorize @<%%= singular_table_name %>
83
+
84
+ <%- end -%>
85
+ @<%%= orm_instance.destroy %>
86
+ redirect_to <%%= index_helper %>_url, notice: <%%= "'#{human_name} was successfully destroyed.'" %>
87
+ end
88
+
89
+ <%- if pundit? -%>
90
+ protected
91
+
92
+ def authentication_failed_redirect_path_for(_resource)
93
+ if @<%%= singular_table_name %> && policy(@<%%= singular_table_name %>).show?
94
+ @<%%= singular_table_name %>
95
+ elsif policy(<%%= class_name %>).index?
96
+ <%%= index_helper %>_url
97
+ else
98
+ super
99
+ end
100
+ end
101
+
102
+ <%- end -%>
103
+ private
104
+ # Use callbacks to share common setup or constraints between actions.
105
+ def assign_<%%= singular_table_name %>
106
+ <%- if pundit? -%>
107
+ @<%%= singular_table_name %> = <%%= orm_class.find("policy_scope(#{class_name})", "params[:id]") %>
108
+ <%- else -%>
109
+ @<%%= singular_table_name %> = <%%= orm_class.find(class_name, "params[:id]") %>
110
+ <%- end -%>
111
+ end
112
+
113
+ # Only allow a trusted parameter "white list" through.
114
+ def <%%= "#{singular_table_name}_params" %>
115
+ <%- if pundit? -%>
116
+ permitted_attributes(@<%%= singular_table_name %> || <%%= class_name %>)
117
+ <%- else -%>
118
+ <%%- if attributes_names.empty? -%>
119
+ params.fetch(:<%%= singular_table_name %>, {})
120
+ <%%- else -%>
121
+ params.require(:<%%= singular_table_name %>).permit(<%%= permitted_params %>)
122
+ <%%- end -%>
123
+ <%- end -%>
124
+ end
125
+ end
126
+ <%% end -%>
@@ -0,0 +1,139 @@
1
+ <%- resource_path = name.underscore.pluralize -%>
2
+ <%- permitted_params = attributes.map { |a| ":#{a.name}" }.join(", ") -%>
3
+ # frozen_string_literal: true
4
+
5
+ require "rails_helper"
6
+
7
+ <% module_namespacing do -%>
8
+ RSpec.describe "/<%= controller_class_name %>", <%= type_metatag(:request) %> do
9
+ # This should return the minimal set of values that should be in the headers
10
+ # in order to pass any filters (e.g. authentication) defined in
11
+ # <%= controller_class_name %>Controller, or in your router and rack
12
+ # middleware. Be sure to keep this updated too.
13
+ let(:valid_headers) do
14
+ {}
15
+ end
16
+
17
+ <% unless options[:singleton] -%>
18
+ describe "GET /<%= resource_path %>" do
19
+ it "renders a successful response" do
20
+ create(:<%= file_name %>)
21
+ get <%= index_helper %>_url, headers: valid_headers, as: :json
22
+ expect(response).to be_successful
23
+ end
24
+ end
25
+ <% end -%>
26
+
27
+ describe "GET /<%= resource_path %>/:id" do
28
+ it "renders a successful response" do
29
+ <%= file_name %> = create(:<%= file_name %>)
30
+ get <%= show_helper.tr('@', '') %>, as: :json
31
+ expect(response).to be_successful
32
+ end
33
+ end
34
+
35
+ describe "POST /<%= resource_path %>" do
36
+ context "with valid parameters" do
37
+ let(:valid_attributes) do
38
+ <%- if attributes.any? -%>
39
+ attributes_for(:<%= ns_file_name %>).slice(<%= permitted_params %>)
40
+ <%- else -%>
41
+ skip("Add a hash of attributes valid for your model")
42
+ <%- end -%>
43
+ end
44
+
45
+ it "creates a new <%= class_name %>" do
46
+ expect do
47
+ post <%= index_helper %>_url,
48
+ params: { <%= ns_file_name %>: valid_attributes }, headers: valid_headers, as: :json
49
+ end.to change(<%= class_name %>, :count).by(1)
50
+ end
51
+
52
+ it "renders a JSON response with the new <%= ns_file_name %>" do
53
+ post <%= index_helper %>_url,
54
+ params: { <%= ns_file_name %>: valid_attributes }, headers: valid_headers, as: :json
55
+ expect(response).to have_http_status(:created)
56
+ expect(response.content_type).to match(a_string_including("application/json"))
57
+ end
58
+ end
59
+
60
+ context "with invalid parameters" do
61
+ let(:invalid_attributes) do
62
+ skip("Add a hash of attributes invalid for your model")
63
+ end
64
+
65
+ it "does not create a new <%= class_name %>" do
66
+ expect do
67
+ post <%= index_helper %>_url,
68
+ params: { <%= ns_file_name %>: invalid_attributes }, as: :json
69
+ end.to change(<%= class_name %>, :count).by(0)
70
+ end
71
+
72
+ it "renders a JSON response with errors for the new <%= ns_file_name %>" do
73
+ post <%= index_helper %>_url,
74
+ params: { <%= ns_file_name %>: invalid_attributes }, headers: valid_headers, as: :json
75
+ expect(response).to have_http_status(:unprocessable_entity)
76
+ expect(response.content_type).to eq("application/json")
77
+ end
78
+ end
79
+ end
80
+
81
+ describe "PATCH /<%= resource_path %>/:id" do
82
+ context "with valid parameters" do
83
+ let(:new_attributes) do
84
+ <%- if attributes.any? -%>
85
+ attributes_for(:<%= ns_file_name %>).slice(<%= permitted_params %>)
86
+ <%- else -%>
87
+ skip("Add a hash of attributes valid for your model")
88
+ <%- end -%>
89
+ end
90
+
91
+ it "updates the requested <%= ns_file_name %>" do
92
+ <%= file_name %> = create(:<%= file_name %>)
93
+ patch <%= show_helper.tr('@', '') %>,
94
+ params: { <%= singular_table_name %>: invalid_attributes }, headers: valid_headers, as: :json
95
+
96
+ <%= file_name %>.reload
97
+ <%- if attributes.any? -%>
98
+ <%- attributes.each do |attribute| -%>
99
+ expect(<%= file_name %>.<%= attribute.name %>).to eq(new_attributes[:<%= attribute.name %>])
100
+ <%- end -%>
101
+ <%- else -%>
102
+ skip("Add assertions for updated state")
103
+ <%- end -%>
104
+ end
105
+
106
+ it "renders a JSON response with the <%= ns_file_name %>" do
107
+ <%= file_name %> = create(:<%= file_name %>)
108
+ patch <%= show_helper.tr('@', '') %>,
109
+ params: { <%= singular_table_name %>: invalid_attributes }, headers: valid_headers, as: :json
110
+ expect(response).to have_http_status(:ok)
111
+ expect(response.content_type).to eq("application/json")
112
+ end
113
+ end
114
+
115
+ context "with invalid parameters" do
116
+ let(:invalid_attributes) do
117
+ skip("Add a hash of attributes invalid for your model")
118
+ end
119
+
120
+ it "renders a JSON response with errors for the <%= ns_file_name %>" do
121
+ <%= file_name %> = create(:<%= file_name %>)
122
+ patch <%= show_helper.tr('@', '') %>,
123
+ params: { <%= singular_table_name %>: invalid_attributes }, headers: valid_headers, as: :json
124
+ expect(response).to have_http_status(:unprocessable_entity)
125
+ expect(response.content_type).to eq("application/json")
126
+ end
127
+ end
128
+ end
129
+
130
+ describe "DELETE /<%= resource_path %>/:id" do
131
+ it "destroys the requested <%= ns_file_name %>" do
132
+ <%= file_name %> = create(:<%= file_name %>)
133
+ expect do
134
+ delete <%= show_helper.tr('@', '') %>, headers: valid_headers, as: :json
135
+ end.to change(<%= class_name %>, :count).by(-1)
136
+ end
137
+ end
138
+ end
139
+ <% end -%>