b4um_generators 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 (87) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +28 -0
  4. data/CHANGELOG.md +5 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.de.md +821 -0
  7. data/README.md +815 -0
  8. data/Rakefile +12 -0
  9. data/b4um_generators.gemspec +30 -0
  10. data/bin/console +11 -0
  11. data/bin/setup +8 -0
  12. data/lib/b4um_generators/version.rb +5 -0
  13. data/lib/b4um_generators.rb +8 -0
  14. data/lib/generators/b4um/bento/bento_generator.rb +81 -0
  15. data/lib/generators/b4um/bento/templates/_alternating.html.erb.tt +15 -0
  16. data/lib/generators/b4um/bento/templates/_bento.html.erb.tt +26 -0
  17. data/lib/generators/b4um/bento/templates/_grid.html.erb.tt +13 -0
  18. data/lib/generators/b4um/bento/templates/_list.html.erb.tt +15 -0
  19. data/lib/generators/b4um/comments/comments_generator.rb +259 -0
  20. data/lib/generators/b4um/comments/templates/_comments.html.erb.tt +63 -0
  21. data/lib/generators/b4um/comments/templates/comment.rb.tt +5 -0
  22. data/lib/generators/b4um/comments/templates/comments_controller.rb.tt +45 -0
  23. data/lib/generators/b4um/comments/templates/create_comments.rb.tt +14 -0
  24. data/lib/generators/b4um/controller/controller_generator.rb +397 -0
  25. data/lib/generators/b4um/help/help_generator.rb +755 -0
  26. data/lib/generators/b4um/infinite_scroll/infinite_scroll_generator.rb +199 -0
  27. data/lib/generators/b4um/infinite_scroll/templates/infinite_scroll_controller.js +61 -0
  28. data/lib/generators/b4um/install/install_generator.rb +492 -0
  29. data/lib/generators/b4um/install/templates/_cookie_consent.html.erb +27 -0
  30. data/lib/generators/b4um/install/templates/_footer.html.erb +17 -0
  31. data/lib/generators/b4um/install/templates/_hero.html.erb +33 -0
  32. data/lib/generators/b4um/install/templates/_navigation.html.erb +31 -0
  33. data/lib/generators/b4um/install/templates/_sitemap.html.erb +48 -0
  34. data/lib/generators/b4um/install/templates/_theme_switcher.html.erb +57 -0
  35. data/lib/generators/b4um/install/templates/b4um/badges.css +43 -0
  36. data/lib/generators/b4um/install/templates/b4um/base.css +42 -0
  37. data/lib/generators/b4um/install/templates/b4um/callouts.css +58 -0
  38. data/lib/generators/b4um/install/templates/b4um/cards.css +401 -0
  39. data/lib/generators/b4um/install/templates/b4um/comments.css +52 -0
  40. data/lib/generators/b4um/install/templates/b4um/cookie-consent.css +83 -0
  41. data/lib/generators/b4um/install/templates/b4um/empty-state.css +26 -0
  42. data/lib/generators/b4um/install/templates/b4um/flash.css +86 -0
  43. data/lib/generators/b4um/install/templates/b4um/footer.css +338 -0
  44. data/lib/generators/b4um/install/templates/b4um/forms.css +924 -0
  45. data/lib/generators/b4um/install/templates/b4um/hero.css +149 -0
  46. data/lib/generators/b4um/install/templates/b4um/layout.css +166 -0
  47. data/lib/generators/b4um/install/templates/b4um/lightbox.css +268 -0
  48. data/lib/generators/b4um/install/templates/b4um/navigation.css +257 -0
  49. data/lib/generators/b4um/install/templates/b4um/pagination.css +85 -0
  50. data/lib/generators/b4um/install/templates/b4um/resources.css +121 -0
  51. data/lib/generators/b4um/install/templates/b4um/search.css +41 -0
  52. data/lib/generators/b4um/install/templates/b4um/tables.css +67 -0
  53. data/lib/generators/b4um/install/templates/b4um/theme-switcher.css +178 -0
  54. data/lib/generators/b4um/install/templates/b4um/theme.css +132 -0
  55. data/lib/generators/b4um/install/templates/b4um.css +20 -0
  56. data/lib/generators/b4um/install/templates/b4um.yml +12 -0
  57. data/lib/generators/b4um/install/templates/b4um_helper.rb +27 -0
  58. data/lib/generators/b4um/install/templates/cookie_consent_controller.js +76 -0
  59. data/lib/generators/b4um/install/templates/dismissible_controller.js +7 -0
  60. data/lib/generators/b4um/install/templates/image_lightbox_controller.js +414 -0
  61. data/lib/generators/b4um/install/templates/image_preview_controller.js +85 -0
  62. data/lib/generators/b4um/install/templates/navigation_controller.js +25 -0
  63. data/lib/generators/b4um/install/templates/navigation_helper.rb +26 -0
  64. data/lib/generators/b4um/install/templates/sitemap_controller.js +35 -0
  65. data/lib/generators/b4um/install/templates/theme_controller.js +122 -0
  66. data/lib/generators/b4um/pagination/pagination_generator.rb +179 -0
  67. data/lib/generators/b4um/pagination/templates/_pagination.html.erb.tt +48 -0
  68. data/lib/generators/b4um/pagination/templates/pagination.rb +36 -0
  69. data/lib/generators/b4um/scaffold/scaffold_generator.rb +333 -0
  70. data/lib/generators/b4um/scaffold/templates/_bento.html.erb.tt +26 -0
  71. data/lib/generators/b4um/scaffold/templates/_form.html.erb.tt +218 -0
  72. data/lib/generators/b4um/scaffold/templates/_resource.html.erb.tt +144 -0
  73. data/lib/generators/b4um/scaffold/templates/_table.html.erb.tt +40 -0
  74. data/lib/generators/b4um/scaffold/templates/edit.html.erb.tt +21 -0
  75. data/lib/generators/b4um/scaffold/templates/index.html.erb.tt +24 -0
  76. data/lib/generators/b4um/scaffold/templates/new.html.erb.tt +17 -0
  77. data/lib/generators/b4um/scaffold/templates/show.html.erb.tt +31 -0
  78. data/lib/generators/b4um/search/search_generator.rb +165 -0
  79. data/lib/generators/b4um/search/templates/search.rb +34 -0
  80. data/lib/generators/b4um/search/templates/search_form.html.erb.tt +15 -0
  81. data/lib/generators/b4um/table/table_generator.rb +63 -0
  82. data/lib/generators/b4um/table/templates/_table.html.erb.tt +40 -0
  83. data/lib/generators/b4um/trix/templates/b4um_rich_text_helper.rb +58 -0
  84. data/lib/generators/b4um/trix/templates/b4um_trix.js +551 -0
  85. data/lib/generators/b4um/trix/trix_generator.rb +383 -0
  86. data/sig/b4um_generators.rbs +4 -0
  87. metadata +148 -0
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/b4um_generators/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "b4um_generators"
7
+ spec.version = B4umGenerators::VERSION
8
+ spec.authors = ["Alexander Baum"]
9
+ spec.email = ["info@b4um.com"]
10
+
11
+ spec.summary = "Rails generators for b4um applications"
12
+ spec.description = "Reusable Rails generators, templates and application defaults for b4um projects."
13
+ spec.homepage = "https://www.b4um.com"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 3.1.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["rubygems_mfa_required"] = "true"
19
+
20
+ spec.files = Dir.chdir(__dir__) do
21
+ `git ls-files -z`.split("\x0").reject do |file|
22
+ file.start_with?("test/", "spec/", "features/", ".git", "Gemfile")
23
+ end
24
+ end
25
+
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |file| File.basename(file) }
28
+ spec.require_paths = ["lib"]
29
+ spec.add_dependency "railties", ">= 8.0", "< 9.0"
30
+ end
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "b4um_generators"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ require "irb"
11
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module B4umGenerators
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "b4um_generators/version"
4
+
5
+ module B4umGenerators
6
+ class Error < StandardError; end
7
+ # Your code goes here...
8
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/named_base"
5
+
6
+ module B4um
7
+ module Generators
8
+ class BentoGenerator < Rails::Generators::NamedBase
9
+ source_root File.expand_path("templates", __dir__)
10
+
11
+ class_option :layout,
12
+ type: :string,
13
+ default: "grid",
14
+ enum: %w[bento grid list alternating],
15
+ desc: "Layout: bento, grid, list, or alternating"
16
+
17
+ class << self
18
+ def desc(_description = nil)
19
+ "Generates a B4UM Bento partial for an existing model."
20
+ end
21
+ end
22
+
23
+ def validate_model
24
+ return if File.exist?(model_path)
25
+
26
+ raise Thor::Error,
27
+ "Model not found: app/models/#{file_name}.rb"
28
+ end
29
+
30
+ def validate_resource_partial
31
+ return if File.exist?(resource_partial_path)
32
+
33
+ raise Thor::Error,
34
+ "Resource partial not found: app/views/#{plural_table_name}/_#{file_name}.html.erb"
35
+ end
36
+
37
+ def create_bento_partial
38
+ template(
39
+ template_name,
40
+ File.join(
41
+ "app/views",
42
+ plural_table_name,
43
+ "_bento.html.erb"
44
+ )
45
+ )
46
+ end
47
+
48
+ private
49
+
50
+ def model_path
51
+ File.join(
52
+ destination_root,
53
+ "app/models",
54
+ "#{file_name}.rb"
55
+ )
56
+ end
57
+
58
+ def resource_partial_path
59
+ File.join(
60
+ destination_root,
61
+ "app/views",
62
+ plural_table_name,
63
+ "_#{file_name}.html.erb"
64
+ )
65
+ end
66
+
67
+ def template_name
68
+ case options[:layout]
69
+ when "grid"
70
+ "_grid.html.erb.tt"
71
+ when "list"
72
+ "_list.html.erb.tt"
73
+ when "alternating"
74
+ "_alternating.html.erb.tt"
75
+ else
76
+ "_bento.html.erb.tt"
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,15 @@
1
+ <div id="<%= plural_table_name %>" class="b4um-alternating">
2
+ <%% <%= plural_table_name %>.each_with_index do |<%= file_name %>, index| %>
3
+ <article class="b4um-alternating__item <%%= "b4um-alternating__item--reverse" if index.odd? %>">
4
+ <div class="b4um-alternating__content">
5
+ <%%= render <%= file_name %>, compact: true %>
6
+ </div>
7
+
8
+ <div class="b4um-alternating__actions">
9
+ <%%= link_to "Show",
10
+ <%= file_name %>,
11
+ class: "button button--secondary" %>
12
+ </div>
13
+ </article>
14
+ <%% end %>
15
+ </div>
@@ -0,0 +1,26 @@
1
+ <div id="<%= plural_table_name %>" class="b4um-grid">
2
+ <%% <%= plural_table_name %>.each_with_index do |<%= file_name %>, index| %>
3
+ <%% card_class =
4
+ case index % 5
5
+ when 0
6
+ "b4um-card b4um-card--wide"
7
+ when 1
8
+ "b4um-card b4um-card--soft"
9
+ when 3
10
+ "b4um-card b4um-card--large"
11
+ else
12
+ "b4um-card"
13
+ end
14
+ %>
15
+
16
+ <article class="<%%= card_class %>">
17
+ <%%= render <%= file_name %>, compact: true %>
18
+
19
+ <div class="b4um-card__actions">
20
+ <%%= link_to "Show",
21
+ <%= file_name %>,
22
+ class: "button button--secondary" %>
23
+ </div>
24
+ </article>
25
+ <%% end %>
26
+ </div>
@@ -0,0 +1,13 @@
1
+ <div id="<%= plural_table_name %>" class="b4um-card-grid">
2
+ <%% <%= plural_table_name %>.each do |<%= file_name %>| %>
3
+ <article class="b4um-card">
4
+ <%%= render <%= file_name %>, compact: true %>
5
+
6
+ <div class="b4um-card__actions">
7
+ <%%= link_to "Show",
8
+ <%= file_name %>,
9
+ class: "button button--secondary" %>
10
+ </div>
11
+ </article>
12
+ <%% end %>
13
+ </div>
@@ -0,0 +1,15 @@
1
+ <div id="<%= plural_table_name %>" class="b4um-list">
2
+ <%% <%= plural_table_name %>.each do |<%= file_name %>| %>
3
+ <article class="b4um-list__item">
4
+ <div class="b4um-list__content">
5
+ <%%= render <%= file_name %>, compact: true %>
6
+ </div>
7
+
8
+ <div class="b4um-list__actions">
9
+ <%%= link_to "Show",
10
+ <%= file_name %>,
11
+ class: "button button--secondary" %>
12
+ </div>
13
+ </article>
14
+ <%% end %>
15
+ </div>
@@ -0,0 +1,259 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/migration"
5
+
6
+ module B4um
7
+ module Generators
8
+ class CommentsGenerator < Rails::Generators::Base
9
+ include Rails::Generators::Migration
10
+
11
+ source_root File.expand_path("templates", __dir__)
12
+
13
+ desc "Installs polymorphic comments for B4UM resources."
14
+
15
+ argument :commentable,
16
+ type: :string,
17
+ required: true,
18
+ banner: "MODEL"
19
+
20
+ def self.next_migration_number(_dirname)
21
+ if @previous_migration_number
22
+ @previous_migration_number += 1
23
+ else
24
+ @previous_migration_number =
25
+ Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
26
+ end
27
+
28
+ @previous_migration_number.to_s
29
+ end
30
+
31
+ def validate_commentable_model
32
+ model_path = File.join(
33
+ destination_root,
34
+ "app/models",
35
+ "#{commentable.to_s.underscore}.rb"
36
+ )
37
+
38
+ return if File.exist?(model_path)
39
+
40
+ raise Thor::Error,
41
+ "Commentable model not found: app/models/#{commentable.to_s.underscore}.rb"
42
+ end
43
+
44
+ def create_comment_model
45
+ model_path = File.join(
46
+ destination_root,
47
+ "app/models/comment.rb"
48
+ )
49
+
50
+ return if File.exist?(model_path)
51
+
52
+ template(
53
+ "comment.rb.tt",
54
+ "app/models/comment.rb"
55
+ )
56
+ end
57
+
58
+ def add_comments_association
59
+ model_name = commentable.to_s.underscore
60
+ model_path = File.join(
61
+ "app/models",
62
+ "#{model_name}.rb"
63
+ )
64
+
65
+ full_model_path = File.join(
66
+ destination_root,
67
+ model_path
68
+ )
69
+
70
+ model = File.read(full_model_path)
71
+
72
+ return if model.include?(
73
+ "has_many :comments,"
74
+ )
75
+
76
+ association = [
77
+ " has_many :comments,",
78
+ " as: :commentable,",
79
+ " dependent: :destroy",
80
+ ""
81
+ ].join("\n")
82
+
83
+ inject_into_class(
84
+ model_path,
85
+ commentable.to_s.classify,
86
+ association
87
+ )
88
+ end
89
+
90
+ def create_comments_migration
91
+ existing_migration = Dir.glob(
92
+ File.join(
93
+ destination_root,
94
+ "db/migrate/*_create_comments.rb"
95
+ )
96
+ )
97
+
98
+ return if existing_migration.any?
99
+
100
+ migration_template(
101
+ "create_comments.rb.tt",
102
+ "db/migrate/create_comments.rb"
103
+ )
104
+ end
105
+
106
+ def create_comments_controller
107
+ controller_path = "app/controllers/comments_controller.rb"
108
+ full_controller_path = File.join(destination_root, controller_path)
109
+
110
+ unless File.exist?(full_controller_path)
111
+ template(
112
+ "comments_controller.rb.tt",
113
+ controller_path
114
+ )
115
+
116
+ return
117
+ end
118
+
119
+ controller = File.read(full_controller_path)
120
+
121
+ unless controller.include?("COMMENTABLES = {")
122
+ upgraded = upgrade_legacy_comments_controller?(
123
+ controller_path,
124
+ controller
125
+ )
126
+
127
+ unless upgraded
128
+ raise Thor::Error,
129
+ "Cannot modify existing CommentsController: " \
130
+ "its structure is not recognized by the B4UM generator."
131
+ end
132
+ end
133
+
134
+ controller = File.read(full_controller_path)
135
+
136
+ param_name = "#{commentable.to_s.underscore}_id"
137
+ class_name = commentable.to_s.classify
138
+
139
+ return if controller.include?(
140
+ %("#{param_name}" => #{class_name})
141
+ )
142
+
143
+ inject_into_file(
144
+ controller_path,
145
+ after: " COMMENTABLES = {\n"
146
+ ) do
147
+ %( "#{param_name}" => #{class_name},\n)
148
+ end
149
+ end
150
+
151
+ def create_comments_partial
152
+ partial_path = File.join(
153
+ destination_root,
154
+ "app/views/comments/_comments.html.erb"
155
+ )
156
+
157
+ return if File.exist?(partial_path)
158
+
159
+ template(
160
+ "_comments.html.erb.tt",
161
+ "app/views/comments/_comments.html.erb"
162
+ )
163
+ end
164
+
165
+ def add_comments_routes
166
+ routes_path = "config/routes.rb"
167
+ full_routes_path = File.join(destination_root, routes_path)
168
+
169
+ routes = File.read(full_routes_path)
170
+ resource_name = commentable.to_s.underscore.pluralize
171
+
172
+ return if routes.include?(
173
+ "resources :#{resource_name} do\n resources :comments"
174
+ )
175
+
176
+ gsub_file(
177
+ routes_path,
178
+ " resources :#{resource_name}\n",
179
+ [
180
+ " resources :#{resource_name} do",
181
+ " resources :comments, only: %i[create destroy]",
182
+ " end",
183
+ ""
184
+ ].join("\n")
185
+ )
186
+ end
187
+
188
+ def add_comments_to_show_view
189
+ model_name = commentable.to_s.underscore
190
+ show_path = File.join(
191
+ "app/views",
192
+ model_name.pluralize,
193
+ "show.html.erb"
194
+ )
195
+ full_show_path = File.join(destination_root, show_path)
196
+
197
+ return unless File.exist?(full_show_path)
198
+
199
+ show_view = File.read(full_show_path)
200
+ render_line =
201
+ %(<%= render "comments/comments", commentable: @#{model_name} %>)
202
+
203
+ return if show_view.include?(render_line)
204
+
205
+ append_to_file(
206
+ show_path,
207
+ "\n#{render_line}\n"
208
+ )
209
+ end
210
+
211
+ private
212
+
213
+ def upgrade_legacy_comments_controller?(controller_path, controller)
214
+ match = controller.match(
215
+ /@commentable = ([A-Z]\w*(?:::\w+)*)\.find\(\s*params\[:(\w+_id)\]\s*\)/
216
+ )
217
+
218
+ return false unless match
219
+
220
+ legacy_class = match[1]
221
+ legacy_param = match[2]
222
+
223
+ commentables = [
224
+ "",
225
+ " COMMENTABLES = {",
226
+ %( "#{legacy_param}" => #{legacy_class}),
227
+ " }.freeze",
228
+ ""
229
+ ].join("\n")
230
+
231
+ inject_into_file(
232
+ controller_path,
233
+ commentables,
234
+ after: "class CommentsController < ApplicationController\n"
235
+ )
236
+
237
+ set_commentable = [
238
+ " def set_commentable",
239
+ " param_name, commentable_class = COMMENTABLES.find do |key, _klass|",
240
+ " params[key].present?",
241
+ " end",
242
+ "",
243
+ " raise ActiveRecord::RecordNotFound unless param_name",
244
+ "",
245
+ " @commentable = commentable_class.find(params[param_name])",
246
+ " end"
247
+ ].join("\n")
248
+
249
+ gsub_file(
250
+ controller_path,
251
+ / def set_commentable\n.*?^ end$/m,
252
+ set_commentable
253
+ )
254
+
255
+ true
256
+ end
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,63 @@
1
+ <section class="b4um-comments">
2
+ <div class="page-header">
3
+ <h2>Comments</h2>
4
+ </div>
5
+
6
+ <div class="b4um-grid">
7
+ <div class="b4um-card b4um-card--full">
8
+ <%% if commentable.comments.any? %>
9
+ <div class="b4um-comments__list">
10
+ <%% commentable.comments.order(created_at: :desc).each do |comment| %>
11
+ <article class="b4um-comments__item">
12
+ <div class="b4um-comments__body">
13
+ <%%= simple_format(comment.body) %>
14
+ </div>
15
+
16
+ <div class="b4um-comments__meta">
17
+ <%%= l(comment.created_at, format: :short) %>
18
+ </div>
19
+
20
+ <div class="b4um-comments__actions">
21
+ <%%= button_to "Delete",
22
+ [commentable, comment],
23
+ method: :delete,
24
+ class: "button button--danger",
25
+ form: {
26
+ data: {
27
+ turbo_confirm: "Are you sure?"
28
+ }
29
+ } %>
30
+ </div>
31
+ </article>
32
+ <%% end %>
33
+ </div>
34
+ <%% else %>
35
+ <p class="b4um-comments__empty">
36
+ No comments yet.
37
+ </p>
38
+ <%% end %>
39
+
40
+ <div class="b4um-comments__form">
41
+ <h3>Add comment</h3>
42
+
43
+ <%%= form_with model: [commentable, Comment.new],
44
+ class: "form" do |form| %>
45
+ <div class="form-field form-field--textarea">
46
+ <%%= form.text_area :body,
47
+ class: "form-textarea",
48
+ placeholder: " ",
49
+ required: true %>
50
+ <%%= form.label :body,
51
+ "Comment",
52
+ class: "form-label" %>
53
+ </div>
54
+
55
+ <div class="form-actions">
56
+ <%%= form.submit "Add comment",
57
+ class: "form-submit" %>
58
+ </div>
59
+ <%% end %>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </section>
@@ -0,0 +1,5 @@
1
+ class Comment < ApplicationRecord
2
+ belongs_to :commentable, polymorphic: true
3
+
4
+ validates :body, presence: true
5
+ end
@@ -0,0 +1,45 @@
1
+ class CommentsController < ApplicationController
2
+ COMMENTABLES = {
3
+ "<%= commentable.to_s.underscore %>_id" => <%= commentable.to_s.classify %>
4
+ }.freeze
5
+
6
+ before_action :set_commentable
7
+
8
+ def create
9
+ @comment = @commentable.comments.build(comment_params)
10
+
11
+ if @comment.save
12
+ redirect_to @commentable,
13
+ notice: "Comment was successfully created.",
14
+ status: :see_other
15
+ else
16
+ redirect_to @commentable,
17
+ alert: @comment.errors.full_messages.to_sentence,
18
+ status: :see_other
19
+ end
20
+ end
21
+
22
+ def destroy
23
+ comment = @commentable.comments.find(params[:id])
24
+ comment.destroy!
25
+
26
+ flash[:deleted] = "Comment was successfully destroyed."
27
+ redirect_to @commentable, status: :see_other
28
+ end
29
+
30
+ private
31
+
32
+ def set_commentable
33
+ param_name, commentable_class = COMMENTABLES.find do |key, _klass|
34
+ params[key].present?
35
+ end
36
+
37
+ raise ActiveRecord::RecordNotFound unless param_name
38
+
39
+ @commentable = commentable_class.find(params[param_name])
40
+ end
41
+
42
+ def comment_params
43
+ params.expect(comment: [:body])
44
+ end
45
+ end
@@ -0,0 +1,14 @@
1
+ class CreateComments < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :comments do |t|
4
+ t.text :body, null: false
5
+
6
+ t.references :commentable,
7
+ polymorphic: true,
8
+ null: false,
9
+ index: true
10
+
11
+ t.timestamps
12
+ end
13
+ end
14
+ end