rockstart 0.1.0

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.
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 -%>