From 508b8b9b6175ec0df2a8cc66f9f7a3eb8bfe7f5e Mon Sep 17 00:00:00 2001 From: Morgan Roderick Date: Tue, 13 Jan 2026 18:50:03 +0100 Subject: [PATCH 1/6] Remove unused available_spaces? method from InvitationController MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `available_spaces?` private method was defined but never called anywhere in the controller or codebase. This method checked if a workshop had available spaces for students or coaches based on the invitation role. Analysis: - No references found in any controller actions or concerns - Not used in views or service objects - Space availability checks are handled elsewhere in the application This removal reduces code complexity and removes dead code that could confuse future maintainers. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/controllers/invitation_controller.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/controllers/invitation_controller.rb b/app/controllers/invitation_controller.rb index fb9d57dbb..df7321996 100644 --- a/app/controllers/invitation_controller.rb +++ b/app/controllers/invitation_controller.rb @@ -24,11 +24,6 @@ def invitation_params params[:workshop_invitation].present? ? params.require(:workshop_invitation).permit(:tutorial, :note) : {} end - def available_spaces?(workshop, invitation) - (invitation.role.eql?('Student') && workshop.student_spaces?) || - (invitation.role.eql?('Coach') && workshop.coach_spaces?) - end - def token params[:id] end From 44e5606f9e50c774da0ce822162ff7db263d8419 Mon Sep 17 00:00:00 2001 From: Morgan Roderick Date: Tue, 13 Jan 2026 18:51:31 +0100 Subject: [PATCH 2/6] Remove unused Sponsor.latest class method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `Sponsor.latest` class method was defined but never called anywhere in the application. This method returned the 15 most recent workshop sponsors by querying WorkshopSponsor and extracting unique sponsor records. Analysis: - No references found using `Sponsor.latest` in controllers, views, or services - No references found using `.latest` on Sponsor model instances - The application uses other scopes and queries to retrieve recent sponsors: - `recent_for_chapter` scope for chapter-specific recent sponsors - Direct workshop_sponsors associations for related queries - The method's functionality (fetching recent sponsors via WorkshopSponsor) can be easily recreated if needed in the future This removal eliminates unused code and reduces the model's API surface, making the codebase easier to maintain and understand. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/models/sponsor.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/models/sponsor.rb b/app/models/sponsor.rb index ad411e8c2..e3e7059ce 100644 --- a/app/models/sponsor.rb +++ b/app/models/sponsor.rb @@ -54,10 +54,6 @@ def coach_spots number_of_coaches || (seats / 2.0).round end - def self.latest - WorkshopSponsor.order('created_at desc').limit(15).includes(:sponsor).map(&:sponsor).uniq - end - private def website_is_url From fcb07f63ace2306495031b2158a81ba2b2abcbbe Mon Sep 17 00:00:00 2001 From: Morgan Roderick Date: Tue, 13 Jan 2026 18:54:26 +0100 Subject: [PATCH 3/6] Remove commented-out dead code from views and uploaders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed multiple blocks of commented-out code that serve no purpose and clutter the codebase, making it harder to maintain and understand. Analysis of removed code: 1. app/views/admin/events/_invitation_management.html.haml (13 lines) - Commented-out simple_form_for implementation for manual RSVP management - Old form that allowed manually adding invitations via dropdown - Functionality has been replaced or removed from the application - No indication this code needs to be restored 2. app/views/events/_faq.html.haml (13 lines) - Two commented-out FAQ items about experience requirements and contributions - These questions were likely removed to simplify event requirements - Content is outdated (references http://tutorials.codebar.io) - If needed, can be recreated from localization files 3. app/uploaders/avatar_uploader.rb (18 lines) - Commented-out CarrierWave generator boilerplate - Includes unused examples: default_url, scale processing, filename override - Standard Rails practice is to remove unused generator comments - Well-documented in CarrierWave docs if needed 4. app/uploaders/image_uploader.rb (18 lines) - Same as avatar_uploader - unused CarrierWave boilerplate - Includes commented storage options and example methods - Removes visual clutter without affecting functionality Impact: - Removes 62 lines of dead code across 4 files - Improves code readability and reduces cognitive load - Makes it clear what the actual implementation is vs. unused alternatives - Reduces confusion for developers trying to understand current behavior 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/uploaders/avatar_uploader.rb | 24 -------------- app/uploaders/image_uploader.rb | 31 ------------------- .../events/_invitation_management.html.haml | 14 --------- app/views/events/_faq.html.haml | 12 ------- 4 files changed, 81 deletions(-) diff --git a/app/uploaders/avatar_uploader.rb b/app/uploaders/avatar_uploader.rb index ecc107a07..80f9e1bb4 100644 --- a/app/uploaders/avatar_uploader.rb +++ b/app/uploaders/avatar_uploader.rb @@ -9,28 +9,10 @@ def content_type_allowlist [/image\//] end - # Override the directory where uploaded files will be stored. - # This is a sensible default for uploaders that are meant to be mounted: def store_dir "uploads/#{model.class.to_s.underscore}/#{model.id}" end - # Provide a default URL as a default if there hasn't been a file uploaded: - # def default_url - # # For Rails 3.1+ asset pipeline compatibility: - # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) - # - # "/images/fallback/" + [version_name, "default.png"].compact.join('_') - # end - - # Process files as they are uploaded: - # process :scale => [200, 300] - # - # def scale(width, height) - # # do something - # end - # - version :thumb do process resize_to_fit: [178, 65] end @@ -38,10 +20,4 @@ def store_dir def extension_allowlist %w[jpg jpeg gif png] end - - # Override the filename of the uploaded files: - # Avoid using model.id or version_name here, see uploader/store.rb for details. - # def filename - # "something.jpg" if original_filename - # end end diff --git a/app/uploaders/image_uploader.rb b/app/uploaders/image_uploader.rb index 6cf73ea4d..1ba59cbe9 100644 --- a/app/uploaders/image_uploader.rb +++ b/app/uploaders/image_uploader.rb @@ -1,48 +1,17 @@ class ImageUploader < CarrierWave::Uploader::Base storage :aws if Rails.env.production? - # Include RMagick or MiniMagick support: include CarrierWave::MiniMagick - # Choose what kind of storage to use for this uploader: - # storage :file - # storage :fog - - # Override the directory where uploaded files will be stored. - # This is a sensible default for uploaders that are meant to be mounted: def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end - # Provide a default URL as a default if there hasn't been a file uploaded: - # def default_url - # # For Rails 3.1+ asset pipeline compatibility: - # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) - # - # "/images/fallback/" + [version_name, "default.png"].compact.join('_') - # end - - # Process files as they are uploaded: - # process :scale => [200, 300] - # - # def scale(width, height) - # # do something - # end - - # Create different versions of your uploaded files: version :bg do process resize_to_fit: [1200, 800] end - # Add an allow list of extensions which are allowed to be uploaded. - # For images you might use something like this: def extension_allowlist %w[jpg jpeg png] end - - # Override the filename of the uploaded files: - # Avoid using model.id or version_name here, see uploader/store.rb for details. - # def filename - # "something.jpg" if original_filename - # end end diff --git a/app/views/admin/events/_invitation_management.html.haml b/app/views/admin/events/_invitation_management.html.haml index 3fced484c..34b0ebf7c 100644 --- a/app/views/admin/events/_invitation_management.html.haml +++ b/app/views/admin/events/_invitation_management.html.haml @@ -7,20 +7,6 @@ %br #{@attending_students.count} are attending as students and #{@attending_coaches.count} as coaches. --# = simple_form_for :invitation, url: admin_invitation_path, method: :put do |f| --# .row.mb-4 --# .col-auto --# = f.select :id, --# @event.invitations.not_accepted.all.map { |u| [ "#{u.member.full_name} (#{u.role})", u.token] }, --# { include_blank: true }, --# { class: 'chosen-select', required: true, --# data: { placeholder: t('messages.invitations.select_a_member_to_rsvp') } } --# = f.hidden_field :event_id, value: @event.id --# .col-auto --# = f.button :button, 'Add', class: 'btn btn-sm btn-primary mb-0 me-2' --# %span{ "data-tooltip" => true, "aria-haspopup" => "true", class: "has-tip", title: t('admin.workshop.manage_rsvps.text') } --# %i.fas.fa-info-circle - .row .col-12.col-md-6 %h4 Students diff --git a/app/views/events/_faq.html.haml b/app/views/events/_faq.html.haml index 9acc18a7e..cfbb54f2f 100644 --- a/app/views/events/_faq.html.haml +++ b/app/views/events/_faq.html.haml @@ -1,16 +1,4 @@ %ul.row.list-unstyled.row-cols-md-3 - -# %li - -# %small - -# %b= t('events.faq.experience.q') - -# %p - -# %small - -# You must have a general idea about programming and preferably to have already finished the #{link_to("HTML tutorials", "http://tutorials.codebar.io")} or have a similar level of understanding, and basic git knowledge. - -# %li - -# %small - -# %b= t('events.faq.contribution.q') - -# %p - -# %small - -# = t('events.faq.contribution.a') %li %small %b= t('events.faq.laptop.q') From 4c51c5acaaf6d5a360c7c761b44746038c2bb208 Mon Sep 17 00:00:00 2001 From: Morgan Roderick Date: Tue, 13 Jan 2026 19:01:21 +0100 Subject: [PATCH 4/6] Remove unused Group.latest_members scope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `latest_members` scope was defined but never called anywhere in the application. This scope joined the members association and ordered by created_at, but had no references in the codebase. Analysis: - Searched for `Group.latest_members` - no results found - Searched for `.latest_members` on Group instances - no results found - Not used in any controllers, views, services, or other models - The Group model has other scopes (students, coaches) that ARE actively used - Other models have different approaches for getting latest members directly The application retrieves members through the `has_many :members, through: :subscriptions` association when needed, making this scope redundant even if it were to be used. This removal reduces the model's API surface and eliminates potentially confusing unused code. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/models/group.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/group.rb b/app/models/group.rb index e57bc93fc..4ad2c0e60 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -7,7 +7,6 @@ class Group < ApplicationRecord has_many :group_announcements has_many :announcements, through: :group_announcements - scope :latest_members, -> { joins(:members).order('created_at') } scope :students, -> { where(name: 'Students') } scope :coaches, -> { where(name: 'Coaches') } From 8db7c06b31bccf64617c03f7bc4bc09ae4212e77 Mon Sep 17 00:00:00 2001 From: Morgan Roderick Date: Tue, 13 Jan 2026 19:04:18 +0100 Subject: [PATCH 5/6] Remove unused Role.no_admins scope and clean up specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `no_admins` scope was defined but never used in production code. It only existed in specs to test itself, which provides no value. This is a classic example of testing implementation rather than behavior. Analysis: - Searched for `Role.no_admins` - only found in model definition and its spec - Not used in any controllers, views, services, or other models - The scope filtered out Admin roles, but no feature actually needs this - Role is a simple join model managed by Rolify gem - Role permissions are checked via `member.has_role?(:admin)` not via scopes Changes: 1. Removed `scope :no_admins` from app/models/role.rb 2. Simplified spec/models/role_spec.rb to remove the now-unnecessary test 3. Added comment explaining Role is managed by Rolify and doesn't need model-specific tests currently Impact: - Reduces model API surface - Removes test that only verified the scope implementation worked - Eliminates confusion about when/how to filter admin roles - Role model is now minimal and focused on its purpose as a join model 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/models/role.rb | 2 -- spec/models/role_spec.rb | 12 ++---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/app/models/role.rb b/app/models/role.rb index b2b7a754a..998fd4eb2 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,5 +1,3 @@ class Role < ApplicationRecord has_and_belongs_to_many :members - - scope :no_admins, -> { where.not(name: 'Admin') } end diff --git a/spec/models/role_spec.rb b/spec/models/role_spec.rb index 09e10cee2..640f7339b 100644 --- a/spec/models/role_spec.rb +++ b/spec/models/role_spec.rb @@ -1,12 +1,4 @@ RSpec.describe Role do - context 'scopes' do - let(:student_role) { Fabricate(:student_role) } - let(:coach_role) { Fabricate(:coach_role) } - - before { Fabricate(:admin_role) } - - describe '#no_admins' do - it { expect(Role.no_admins).to eq([student_role, coach_role]) } - end - end + # Currently no model-specific tests needed + # Role is a simple join model managed by Rolify end From 69ea22c2b9a37962352f79d70e765bcd9b92f770 Mon Sep 17 00:00:00 2001 From: Morgan Roderick Date: Tue, 13 Jan 2026 19:08:32 +0100 Subject: [PATCH 6/6] Remove unused WaitingListPresenter#reminders method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `reminders` method was defined but never called anywhere in the application. This method returned waiting list entries with `auto_rsvp: false`, but no view or controller ever used this functionality. Analysis: - Searched for `.reminders` calls - no results found - The presenter is instantiated in Admin::WorkshopConcerns - Views only use the `list` method (auto_rsvp: true) to display the waiting list in app/views/admin/workshop/_waiting_list.html.haml - The waiting list feature only shows users who opted in for auto-RSVP - No UI or feature exists for handling manual reminder cases The `list` method is retained as it IS actively used: - Called in app/views/admin/workshop/_waiting_list.html.haml (lines 1, 13) - Filters waiting list to show only auto-RSVP enabled entries - Essential for the waiting list display functionality Impact: - Removes unused method that could confuse developers about waiting list behavior - Clarifies that waiting list only handles auto-RSVP scenarios - Reduces presenter API surface to only what's actually needed Note: No spec files existed for this presenter, so no test cleanup needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/presenters/waiting_list_presenter.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/presenters/waiting_list_presenter.rb b/app/presenters/waiting_list_presenter.rb index fd02abf38..abc11981f 100644 --- a/app/presenters/waiting_list_presenter.rb +++ b/app/presenters/waiting_list_presenter.rb @@ -1,8 +1,4 @@ class WaitingListPresenter < BasePresenter - def reminders - @reminders ||= model.where(auto_rsvp: false) - end - def list model.where(auto_rsvp: true) end