diff --git a/Gemfile.lock b/Gemfile.lock index 78e4c5938..eb2fcbdfe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -11,7 +11,7 @@ GEM specs: action_policy (0.7.6) ruby-next-core (>= 1.0) - action_text-trix (2.1.16) + action_text-trix (2.1.17) railties actioncable (8.1.2) actionpack (= 8.1.2) @@ -199,7 +199,7 @@ GEM ruby2_keywords drb (2.2.3) dry-cli (1.4.1) - erb (6.0.1) + erb (6.0.2) erubi (1.13.1) et-orbi (1.4.0) tzinfo @@ -260,8 +260,9 @@ GEM mini_magick (>= 4.9.5, < 6) ruby-vips (>= 2.0.17, < 3) io-console (0.8.2) - irb (1.16.0) + irb (1.17.0) pp (>= 0.6.0) + prism (>= 1.3.0) rdoc (>= 4.0.0) reline (>= 0.4.2) jbuilder (2.14.1) @@ -272,7 +273,7 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - json (2.18.1) + json (2.19.2) language_server-protocol (3.17.0.5) launchy (3.1.1) addressable (~> 2.8) @@ -287,7 +288,7 @@ GEM ffi-compiler (~> 1.0) rake (~> 13.0) logger (1.7.0) - loofah (2.25.0) + loofah (2.25.1) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.9.0) @@ -307,7 +308,8 @@ GEM mini_magick (5.3.1) logger mini_mime (1.1.5) - minitest (6.0.1) + minitest (6.0.2) + drb (~> 2.0) prism (~> 1.5) msgpack (1.8.0) multi_xml (0.8.1) @@ -323,21 +325,21 @@ GEM net-smtp (0.5.1) net-protocol nio4r (2.7.5) - nokogiri (1.19.1-aarch64-linux-gnu) + nokogiri (1.19.2-aarch64-linux-gnu) racc (~> 1.4) - nokogiri (1.19.1-aarch64-linux-musl) + nokogiri (1.19.2-aarch64-linux-musl) racc (~> 1.4) - nokogiri (1.19.1-arm-linux-gnu) + nokogiri (1.19.2-arm-linux-gnu) racc (~> 1.4) - nokogiri (1.19.1-arm-linux-musl) + nokogiri (1.19.2-arm-linux-musl) racc (~> 1.4) - nokogiri (1.19.1-arm64-darwin) + nokogiri (1.19.2-arm64-darwin) racc (~> 1.4) - nokogiri (1.19.1-x86_64-darwin) + nokogiri (1.19.2-x86_64-darwin) racc (~> 1.4) - nokogiri (1.19.1-x86_64-linux-gnu) + nokogiri (1.19.2-x86_64-linux-gnu) racc (~> 1.4) - nokogiri (1.19.1-x86_64-linux-musl) + nokogiri (1.19.2-x86_64-linux-musl) racc (~> 1.4) opentelemetry-api (1.7.0) opentelemetry-common (0.23.0) @@ -581,8 +583,8 @@ GEM activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.2) - loofah (~> 2.21) + rails-html-sanitizer (1.7.0) + loofah (~> 2.25) nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) railties (8.1.2) actionpack (= 8.1.2) @@ -598,7 +600,7 @@ GEM rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) - rdoc (7.1.0) + rdoc (7.2.0) erb psych (>= 4.0.0) tsort @@ -747,7 +749,7 @@ GEM will_paginate (3.1.8) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.7.4) + zeitwerk (2.7.5) PLATFORMS aarch64-linux-gnu @@ -825,7 +827,7 @@ DEPENDENCIES CHECKSUMS action_policy (0.7.6) sha256=a80156671e6b7784a2f1fa3a5f347da27c7e13abe7b1c9aab81772839794002d - action_text-trix (2.1.16) sha256=f645a2c21821b8449fd1d6770708f4031c91a2eedf9ef476e9be93c64e703a8a + action_text-trix (2.1.17) sha256=b44691639d77e67169dc054ceacd1edc04d44dc3e4c6a427aa155a2beb4cc951 actioncable (8.1.2) sha256=dc31efc34cca9cdefc5c691ddb8b4b214c0ea5cd1372108cbc1377767fb91969 actionmailbox (8.1.2) sha256=058b2fb1980e5d5a894f675475fcfa45c62631103d5a2596d9610ec81581889b actionmailer (8.1.2) sha256=f4c1d2060f653bfe908aa7fdc5a61c0e5279670de992146582f2e36f8b9175e9 @@ -885,7 +887,7 @@ CHECKSUMS draper (4.0.6) sha256=e96990bffd4d98806913972f5ae2e6a7e8a5fb5433f17b80fbed7ba99d3c9236 drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373 dry-cli (1.4.1) sha256=b8015bb76c708aa8705a36faf694973e75eeeffca39b89c8e172dc6f66a7d874 - erb (6.0.1) sha256=28ecdd99c5472aebd5674d6061e3c6b0a45c049578b071e5a52c2a7f13c197e5 + erb (6.0.2) sha256=9fe6264d44f79422c87490a1558479bd0e7dad4dd0e317656e67ea3077b5242b erubi (1.13.1) sha256=a082103b0885dbc5ecf1172fede897f9ebdb745a4b97a5e8dc63953db1ee4ad9 et-orbi (1.4.0) sha256=6c7e3c90779821f9e3b324c5e96fda9767f72995d6ae435b96678a4f3e2de8bc execjs (2.10.0) sha256=6bcb8be8f0052ff9d370b65d1c080f2406656e150452a0abdb185a133048450d @@ -917,18 +919,18 @@ CHECKSUMS i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5 image_processing (1.14.0) sha256=754cc169c9c262980889bec6bfd325ed1dafad34f85242b5a07b60af004742fb io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc - irb (1.16.0) sha256=2abe56c9ac947cdcb2f150572904ba798c1e93c890c256f8429981a7675b0806 + irb (1.17.0) sha256=168c4ddb93d8a361a045c41d92b2952c7a118fa73f23fe14e55609eb7a863aae jbuilder (2.14.1) sha256=4eb26376ff60ef100cb4fd6fd7533cd271f9998327e86adf20fd8c0e69fabb42 jmespath (1.6.2) sha256=238d774a58723d6c090494c8879b5e9918c19485f7e840f2c1c7532cf84ebcb1 jquery-rails (4.6.1) sha256=619f3496cdcdeaae1fd6dafa52dbac3fc45b745d4e09712da4184a16b3a8d9c0 - json (2.18.1) sha256=fe112755501b8d0466b5ada6cf50c8c3f41e897fa128ac5d263ec09eedc9f986 + json (2.19.2) sha256=e7e1bd318b2c37c4ceee2444841c86539bc462e81f40d134cf97826cb14e83cf language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc launchy (3.1.1) sha256=72b847b5cc961589dde2c395af0108c86ff0119f42d4648d25b5440ebb10059e lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87 listen (3.10.0) sha256=c6e182db62143aeccc2e1960033bebe7445309c7272061979bb098d03760c9d2 llhttp-ffi (0.5.1) sha256=9a25a7fc19311f691a78c9c0ac0fbf4675adbd0cca74310228fdf841018fa7bc logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203 - loofah (2.25.0) sha256=df5ed7ac3bac6a4ec802df3877ee5cc86d027299f8952e6243b3dac446b060e6 + loofah (2.25.1) sha256=d436c73dbd0c1147b16c4a41db097942d217303e1f7728704b37e4df9f6d2e04 mail (2.9.0) sha256=6fa6673ecd71c60c2d996260f9ee3dd387d4673b8169b502134659ece6d34941 marcel (1.0.4) sha256=0d5649feb64b8f19f3d3468b96c680bae9746335d02194270287868a661516a4 matrix (0.4.3) sha256=a0d5ab7ddcc1973ff690ab361b67f359acbb16958d1dc072b8b956a286564c5b @@ -937,7 +939,7 @@ CHECKSUMS method_source (1.1.0) sha256=181301c9c45b731b4769bc81e8860e72f9161ad7d66dd99103c9ab84f560f5c5 mini_magick (5.3.1) sha256=29395dfd76badcabb6403ee5aff6f681e867074f8f28ce08d78661e9e4a351c4 mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef - minitest (6.0.1) sha256=7854c74f48e2e975969062833adc4013f249a4b212f5e7b9d5c040bf838d54bb + minitest (6.0.2) sha256=db6e57956f6ecc6134683b4c87467d6dd792323c7f0eea7b93f66bd284adbc3d msgpack (1.8.0) sha256=e64ce0212000d016809f5048b48eb3a65ffb169db22238fb4b72472fecb2d732 multi_xml (0.8.1) sha256=addba0290bac34e9088bfe73dc4878530297a82a7bbd66cb44dcd0a4b86edf5a mutex_m (0.3.0) sha256=cfcb04ac16b69c4813777022fdceda24e9f798e48092a2b817eb4c0a782b0751 @@ -946,14 +948,14 @@ CHECKSUMS net-protocol (0.2.2) sha256=aa73e0cba6a125369de9837b8d8ef82a61849360eba0521900e2c3713aa162a8 net-smtp (0.5.1) sha256=ed96a0af63c524fceb4b29b0d352195c30d82dd916a42f03c62a3a70e5b70736 nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1 - nokogiri (1.19.1-aarch64-linux-gnu) sha256=cfdb0eafd9a554a88f12ebcc688d2b9005f9fce42b00b970e3dc199587b27f32 - nokogiri (1.19.1-aarch64-linux-musl) sha256=1e2150ab43c3b373aba76cd1190af7b9e92103564063e48c474f7600923620b5 - nokogiri (1.19.1-arm-linux-gnu) sha256=0a39ed59abe3bf279fab9dd4c6db6fe8af01af0608f6e1f08b8ffa4e5d407fa3 - nokogiri (1.19.1-arm-linux-musl) sha256=3a18e559ee499b064aac6562d98daab3d39ba6cbb4074a1542781b2f556db47d - nokogiri (1.19.1-arm64-darwin) sha256=dfe2d337e6700eac47290407c289d56bcf85805d128c1b5a6434ddb79731cb9e - nokogiri (1.19.1-x86_64-darwin) sha256=7093896778cc03efb74b85f915a775862730e887f2e58d6921e3fa3d981e68bf - nokogiri (1.19.1-x86_64-linux-gnu) sha256=1a4902842a186b4f901078e692d12257678e6133858d0566152fe29cdb98456a - nokogiri (1.19.1-x86_64-linux-musl) sha256=4267f38ad4fc7e52a2e7ee28ed494e8f9d8eb4f4b3320901d55981c7b995fc23 + nokogiri (1.19.2-aarch64-linux-gnu) sha256=c34d5c8208025587554608e98fd88ab125b29c80f9352b821964e9a5d5cfbd19 + nokogiri (1.19.2-aarch64-linux-musl) sha256=7f6b4b0202d507326841a4f790294bf75098aef50c7173443812e3ac5cb06515 + nokogiri (1.19.2-arm-linux-gnu) sha256=b7fa1139016f3dc850bda1260988f0d749934a939d04ef2da13bec060d7d5081 + nokogiri (1.19.2-arm-linux-musl) sha256=61114d44f6742ff72194a1b3020967201e2eb982814778d130f6471c11f9828c + nokogiri (1.19.2-arm64-darwin) sha256=58d8ea2e31a967b843b70487a44c14c8ba1866daa1b9da9be9dbdf1b43dee205 + nokogiri (1.19.2-x86_64-darwin) sha256=7d9af11fda72dfaa2961d8c4d5380ca0b51bc389dc5f8d4b859b9644f195e7a4 + nokogiri (1.19.2-x86_64-linux-gnu) sha256=fa8feca882b73e871a9845f3817a72e9734c8e974bdc4fbad6e4bc6e8076b94f + nokogiri (1.19.2-x86_64-linux-musl) sha256=93128448e61a9383a30baef041bf1f5817e22f297a1d400521e90294445069a8 opentelemetry-api (1.7.0) sha256=ccfd264ea6f2db5bf4185e3c07a1297977b44a944e2ce65457c4fe63a697214f opentelemetry-common (0.23.0) sha256=da721190479d57bae0ad2207468f47f3e2c3b9a91024b5bc32c9d280183eb32c opentelemetry-exporter-otlp (0.31.1) sha256=5358be17d7849cbcc4f49e1fc24105edc780a6f96c8e57b64192ab9a8e47474a @@ -1036,13 +1038,13 @@ CHECKSUMS rackup (2.3.1) sha256=6c79c26753778e90983761d677a48937ee3192b3ffef6bc963c0950f94688868 rails (8.1.2) sha256=5069061b23dfa8706b9f0159ae8b9d35727359103178a26962b868a680ba7d95 rails-dom-testing (2.3.0) sha256=8acc7953a7b911ca44588bf08737bc16719f431a1cc3091a292bca7317925c1d - rails-html-sanitizer (1.6.2) sha256=35fce2ca8242da8775c83b6ba9c1bcaad6751d9eb73c1abaa8403475ab89a560 + rails-html-sanitizer (1.7.0) sha256=28b145cceaf9cc214a9874feaa183c3acba036c9592b19886e0e45efc62b1e89 railties (8.1.2) sha256=1289ece76b4f7668fc46d07e55cc992b5b8751f2ad85548b7da351b8c59f8055 rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c rb-fsevent (0.11.2) sha256=43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe rb-inotify (0.11.1) sha256=a0a700441239b0ff18eb65e3866236cd78613d6b9f78fea1f9ac47a85e47be6e - rdoc (7.1.0) sha256=494899df0706c178596ca6e1d50f1b7eb285a9b2aae715be5abd742734f17363 + rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192 regexp_parser (2.11.3) sha256=ca13f381a173b7a93450e53459075c9b76a10433caadcb2f1180f2c741fc55a4 reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835 request_store (1.7.0) sha256=e1b75d5346a315f452242a68c937ef8e48b215b9453a77a6c0acdca2934c88cb @@ -1102,7 +1104,7 @@ CHECKSUMS websocket-extensions (0.1.5) sha256=1c6ba63092cda343eb53fc657110c71c754c56484aad42578495227d717a8241 will_paginate (3.1.8) sha256=681ed5670a39ee8a5e0752f217416dbcd437633910b0696399755adad4e89d0e xpath (3.2.0) sha256=6dfda79d91bb3b949b947ecc5919f042ef2f399b904013eb3ef6d20dd3a4082e - zeitwerk (2.7.4) sha256=2bef90f356bdafe9a6c2bd32bcd804f83a4f9b8bc27f3600fff051eb3edcec8b + zeitwerk (2.7.5) sha256=d8da92128c09ea6ec62c949011b00ed4a20242b255293dd66bf41545398f73dd RUBY VERSION ruby 4.0.1 diff --git a/app/controllers/concerns/mentionable_scopable.rb b/app/controllers/concerns/mentionable_scopable.rb new file mode 100644 index 000000000..ebb38e4c0 --- /dev/null +++ b/app/controllers/concerns/mentionable_scopable.rb @@ -0,0 +1,14 @@ +module MentionableScopable + extend ActiveSupport::Concern + + private + + def authorized_scope_mentions(grouped) + grouped.transform_values do |records| + next [] if records.empty? + + model_class = records.first.class.name.constantize + authorized_scope(model_class.where(id: records.map(&:id))).to_a.select(&:persisted?) + end.compact.reject { |_type, records| records.empty? } + end +end diff --git a/app/controllers/resources_controller.rb b/app/controllers/resources_controller.rb index a519531a7..7c11056a3 100644 --- a/app/controllers/resources_controller.rb +++ b/app/controllers/resources_controller.rb @@ -1,5 +1,6 @@ class ResourcesController < ApplicationController - include ExternallyRedirectable, AhoyTracking, TagAssignable + include ExternallyRedirectable, AhoyTracking, TagAssignable, MentionableScopable + skip_before_action :authenticate_user!, only: [ :index, :show ] def index @@ -59,7 +60,8 @@ def show ).find(resource_id_param).decorate authorize! @resource track_view(@resource) - @mentions = @resource.all_mentions_grouped + @mentioners = authorized_scope_mentions(@resource.mentioner_records_grouped) + @mentionees = authorized_scope_mentions(@resource.mentionee_records_grouped) end def create diff --git a/app/controllers/workshops_controller.rb b/app/controllers/workshops_controller.rb index 81bbfd389..dbf88073e 100644 --- a/app/controllers/workshops_controller.rb +++ b/app/controllers/workshops_controller.rb @@ -1,5 +1,6 @@ class WorkshopsController < ApplicationController - include AhoyTracking, TagAssignable + include AhoyTracking, TagAssignable, MentionableScopable + skip_before_action :authenticate_user!, only: [ :index, :show ] def index @@ -187,7 +188,8 @@ def set_show .includes(:windows_type, :created_by, primary_asset: [ :file_attachment ]) .order(created_at: :desc) @sectors = @workshop.sectorable_items.map { |item| item.sector if item.sector.published? }.compact if @workshop.sectorable_items.any? - @mentions = @workshop.all_mentions_grouped + @mentioners = authorized_scope_mentions(@workshop.mentioner_records_grouped) + @mentionees = authorized_scope_mentions(@workshop.mentionee_records_grouped) end diff --git a/app/models/concerns/mentioner.rb b/app/models/concerns/mentionable.rb similarity index 62% rename from app/models/concerns/mentioner.rb rename to app/models/concerns/mentionable.rb index f34a4a2b2..d15653fd2 100644 --- a/app/models/concerns/mentioner.rb +++ b/app/models/concerns/mentionable.rb @@ -1,18 +1,18 @@ -module Mentioner +module Mentionable extend ActiveSupport::Concern included do end class_methods do + # Override this method in models to specify which rich text fields to check + # Default to empty array - models must override this def mentionable_rich_text_fields - # Override this method in models to specify which rich text fields to check - # Default to empty array - models must override this [] end end - def all_mentions_grouped + def mentionee_records_grouped rich_text_fields = self.class.mentionable_rich_text_fields result = {} @@ -39,4 +39,16 @@ def all_mentions_grouped result end + + def mentioner_records_grouped + records = ActionTextMention + .where(mentionable_type: self.class.name, mentionable_id: id) + .includes(action_text_rich_text: :record) + .map(&:action_text_rich_text) + .map(&:record) + .select(&:persisted?) + .uniq + + records.group_by { |record| record.class.name } + end end diff --git a/app/models/resource.rb b/app/models/resource.rb index 0981c9fe0..c1a1b241f 100644 --- a/app/models/resource.rb +++ b/app/models/resource.rb @@ -2,7 +2,7 @@ class Resource < ApplicationRecord include Featureable, Publishable, TagFilterable, Trendable, WindowsTypeFilterable, RichTextSearchable include Rails.application.routes.url_helpers include ActionText::Attachable - include Mentioner + include Mentionable # Define rich text fields for mentions functionality def self.mentionable_rich_text_fields diff --git a/app/models/workshop.rb b/app/models/workshop.rb index 04ba5201a..d59a4e8e7 100644 --- a/app/models/workshop.rb +++ b/app/models/workshop.rb @@ -5,7 +5,7 @@ class Workshop < ApplicationRecord include Rails.application.routes.url_helpers include ActionText::Attachable include ActiveModel::Dirty - include Mentioner + include Mentionable # Define rich text fields for mentions functionality def self.mentionable_rich_text_fields diff --git a/app/views/resources/show.html.erb b/app/views/resources/show.html.erb index 21f85a663..a0f45a6d2 100644 --- a/app/views/resources/show.html.erb +++ b/app/views/resources/show.html.erb @@ -18,7 +18,7 @@ download: true if @resource.downloadable_asset&.file&.attached? %> -
+
<%= title_with_badges(@resource, font_size: "text-3xl") %> @@ -51,5 +51,6 @@
- <%= render "show_mentions" %> + <%= render "shared/show_mentions_list", mentions: @mentioners, heading: "Mentioned by" %> + <%= render "shared/show_mentions_list", mentions: @mentionees, heading: "Mentions in this Resource" %>
diff --git a/app/views/resources/_show_mentions.html.erb b/app/views/shared/_show_mentions_list.html.erb similarity index 73% rename from app/views/resources/_show_mentions.html.erb rename to app/views/shared/_show_mentions_list.html.erb index 0510930da..2f4daa963 100644 --- a/app/views/resources/_show_mentions.html.erb +++ b/app/views/shared/_show_mentions_list.html.erb @@ -1,15 +1,15 @@ -<% if @mentions.any? %> -
+<% if mentions.any? %> +
-

Mentions in this Resource

+

<%= heading %>


- <% @mentions.each do |mentionable_type, mentionable_records| %> -
+ <% mentions.each do |mentionable_type, mentionable_records| %> +

<%= mentionable_type.pluralize %>

diff --git a/app/views/workshops/_show_associations.html.erb b/app/views/workshops/_show_associations.html.erb index fb329eb5c..94f95533c 100644 --- a/app/views/workshops/_show_associations.html.erb +++ b/app/views/workshops/_show_associations.html.erb @@ -1,5 +1,6 @@
- <%= render "show_mentions" %> + <%= render "shared/show_mentions_list", mentions: @mentioners, heading: "Mentioned by" %> + <%= render "shared/show_mentions_list", mentions: @mentionees, heading: "Mentions in this Workshop" %> <%# if @workshop_variations.any? %>
diff --git a/app/views/workshops/_show_mentions.html.erb b/app/views/workshops/_show_mentions.html.erb deleted file mode 100644 index 1409aa4d0..000000000 --- a/app/views/workshops/_show_mentions.html.erb +++ /dev/null @@ -1,29 +0,0 @@ -<% if @mentions.any? %> -
-
-
-
-

Mentions in this Workshop

-
-
-
-
- <% @mentions.each do |mentionable_type, mentionable_records| %> -
-

- <%= mentionable_type.pluralize %> -

-
- <% mentionable_records.each do |record| %> - <%= link_to polymorphic_path(record), - class: "btn btn-secondary-outline text-sm" do %> - <%= record.title&.to_s %> - <% end %> - <% end %> -
-
- <% end %> -
-
-
-<% end %> diff --git a/config/initializers/action_text_mention.rb b/config/initializers/action_text_mention.rb index 84f40bf0d..79d2cc8c5 100644 --- a/config/initializers/action_text_mention.rb +++ b/config/initializers/action_text_mention.rb @@ -1,39 +1,41 @@ -ActiveSupport.on_load(:action_text_rich_text) do +Rails.application.config.to_prepare do ActionText::RichText.class_eval do - MENTIONABLE_MODELS = [ Workshop, Resource, RichTextAsset ] + unless method_defined?(:update_mentions_for) + MENTIONABLE_MODELS = [ Workshop, Resource, RichTextAsset ] - has_many :action_text_mentions, - class_name: "ActionTextMention", - foreign_key: :action_text_rich_text_id, - dependent: :destroy + has_many :action_text_mentions, + class_name: "ActionTextMention", + foreign_key: :action_text_rich_text_id, + dependent: :destroy - def mentions_for(klass) - action_text_mentions.where(mentionable_type: klass.name).map(&:mentionable) - end + def mentions_for(klass) + action_text_mentions.where(mentionable_type: klass.name).map(&:mentionable) + end - def all_mentions - action_text_mentions.includes(:mentionable).map(&:mentionable) - end + def all_mentions + action_text_mentions.includes(:mentionable).map(&:mentionable) + end - def update_mentions_for(klass) - return unless body.present? - current_records = body.attachables.grep(klass).uniq - existing_records = action_text_mentions - .where(mentionable_type: klass.name) - .map(&:mentionable) + def update_mentions_for(klass) + return unless body.present? + current_records = body.attachables.grep(klass).uniq + existing_records = action_text_mentions + .where(mentionable_type: klass.name) + .map(&:mentionable) - (existing_records - current_records).each do |record| - action_text_mentions.find_by(mentionable: record)&.destroy - end + (existing_records - current_records).each do |record| + action_text_mentions.find_by(mentionable: record)&.destroy + end - (current_records - existing_records).each do |record| - action_text_mentions.build(mentionable: record) + (current_records - existing_records).each do |record| + action_text_mentions.create!(mentionable: record) + end end - end - before_save do - MENTIONABLE_MODELS.each do |klass| - update_mentions_for(klass) + before_save do + MENTIONABLE_MODELS.each do |klass| + update_mentions_for(klass) + end end end end diff --git a/spec/models/resource_mentioner_spec.rb b/spec/models/resource_mentioner_spec.rb index 242c8e019..6358b9a41 100644 --- a/spec/models/resource_mentioner_spec.rb +++ b/spec/models/resource_mentioner_spec.rb @@ -24,7 +24,7 @@ mentionable_id: other_resource.id ) - mentions = resource.all_mentions_grouped + mentions = resource.mentionee_records_grouped expect(mentions).to have_key("Workshop") expect(mentions).to have_key("Resource") expect(mentions["Workshop"]).to include(workshop) @@ -47,7 +47,7 @@ mentionable_id: workshop.id ) - mentions = resource.all_mentions_grouped + mentions = resource.mentionee_records_grouped expect(mentions).to have_key("Workshop") expect(mentions["Workshop"]).to include(workshop) end diff --git a/spec/models/workshop_mentioner_spec.rb b/spec/models/workshop_mentioner_spec.rb index 4a5d2f449..0250cac73 100644 --- a/spec/models/workshop_mentioner_spec.rb +++ b/spec/models/workshop_mentioner_spec.rb @@ -39,7 +39,7 @@ mentionable_id: resource.id ) - mentions = workshop.all_mentions_grouped + mentions = workshop.mentionee_records_grouped expect(mentions).to have_key("Workshop") expect(mentions).to have_key("Resource") expect(mentions["Workshop"]).to include(other_workshop) @@ -64,7 +64,7 @@ mentionable_id: other_workshop.id ) - mentions = workshop.all_mentions_grouped + mentions = workshop.mentionee_records_grouped expect(mentions["Workshop"]).to include(other_workshop) expect(mentions["Workshop"].count).to eq(1) # deduplicated end diff --git a/spec/support/shared_examples/mentioner.rb b/spec/support/shared_examples/mentioner.rb index 35dd75d3b..05dc23a45 100644 --- a/spec/support/shared_examples/mentioner.rb +++ b/spec/support/shared_examples/mentioner.rb @@ -16,10 +16,10 @@ end end - describe "#all_mentions_grouped" do + describe "#mentionee_records_grouped" do context "when model has no mentions" do it "returns empty hash" do - mentions = record.all_mentions_grouped + mentions = record.mentionee_records_grouped expect(mentions).to eq({}) end end @@ -49,13 +49,13 @@ end it "returns mentions grouped by type" do - mentions = record.all_mentions_grouped + mentions = record.mentionee_records_grouped expect(mentions).to have_key(other_record.class.name) expect(mentions[other_record.class.name]).to include(other_record) end it "deduplicates mentions of same record" do - mentions = record.all_mentions_grouped + mentions = record.mentionee_records_grouped expect(mentions[other_record.class.name]).to include(other_record) expect(mentions[other_record.class.name].count).to eq(1) end @@ -63,7 +63,7 @@ it "handles missing records gracefully" do other_record.destroy - mentions = record.all_mentions_grouped + mentions = record.mentionee_records_grouped expect(mentions[other_record.class.name] || []).not_to include(other_record) end end @@ -74,7 +74,7 @@ workshop = create(:workshop, title: "Test Workshop") workshop.update(rhino_misc1: nil, rhino_misc2: nil) - mentions = workshop.all_mentions_grouped + mentions = workshop.mentionee_records_grouped expect(mentions).to eq({}) else skip "nil test already verified." diff --git a/spec/views/resources/show.html.erb_spec.rb b/spec/views/resources/show.html.erb_spec.rb index ff9af1154..64dd9b4cd 100644 --- a/spec/views/resources/show.html.erb_spec.rb +++ b/spec/views/resources/show.html.erb_spec.rb @@ -9,7 +9,8 @@ allow(view).to receive(:current_user).and_return(admin) allow(view).to receive(:allowed_to?).and_return(true) assign(:resource, resource.decorate) - assign(:mentions, []) + assign(:mentioners, []) + assign(:mentionees, []) end context "when resource has an attached primary image" do diff --git a/spec/views/workshops/_show_associations.html.erb_spec.rb b/spec/views/workshops/_show_associations.html.erb_spec.rb index dee7ba31f..56e0f9e11 100644 --- a/spec/views/workshops/_show_associations.html.erb_spec.rb +++ b/spec/views/workshops/_show_associations.html.erb_spec.rb @@ -9,7 +9,8 @@ assign(:workshop_variations, []) assign(:quotes, []) assign(:leader_spotlights, []) - assign(:mentions, {}) + assign(:mentioners, {}) + assign(:mentionees, {}) end context "when user can manage WorkshopVariation" do