diff --git a/Capfile b/Capfile index 5cc098a9..3677dac1 100644 --- a/Capfile +++ b/Capfile @@ -12,10 +12,6 @@ require 'capistrano/rails/migrations' # Load custom tasks from `lib/capistrano/tasks` if you have any defined Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } -task :use_rvm do - require 'capistrano/rvm' -end - task :use_rbenv do require 'capistrano/rbenv' # require 'capistrano/rbenv_install' diff --git a/Gemfile b/Gemfile index a495fa6a..f31cec26 100644 --- a/Gemfile +++ b/Gemfile @@ -74,7 +74,6 @@ group :development do gem 'capistrano-rails', '~> 1.4', require: false gem 'capistrano-rbenv', '~> 2.0' # required gem 'capistrano-rbenv-install', '~> 1.2.0' - gem 'capistrano-rvm', require: false # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'listen', '>= 3.0.5', '< 3.9' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring diff --git a/Gemfile.lock b/Gemfile.lock index 504f466e..4432d0b0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -98,9 +98,6 @@ GEM capistrano-rbenv-install (1.2.0) capistrano (>= 3.0) capistrano-rbenv (>= 2.0) - capistrano-rvm (0.1.2) - capistrano (~> 3.0) - sshkit (~> 1.2) capybara (3.39.2) addressable matrix @@ -366,7 +363,6 @@ DEPENDENCIES capistrano-rails (~> 1.4) capistrano-rbenv (~> 2.0) capistrano-rbenv-install (~> 1.2.0) - capistrano-rvm capybara (>= 2.15) capybara-selenium (~> 0.0.6) coffee-rails (~> 5.0) diff --git a/app/controllers/publications_controller.rb b/app/controllers/publications_controller.rb index a3235757..48337993 100644 --- a/app/controllers/publications_controller.rb +++ b/app/controllers/publications_controller.rb @@ -1,5 +1,30 @@ # frozen_string_literal: true +# == Schema Information +# +# Controller: PublicationsController +# +# Overview: +# The PublicationsController handles the CRUD operations for various types of +# publications like Artwork, Book, BookChapter, and so on. It is designed to +# handle submissions from both admin and regular users. +# +# Responsibilities: +# - Filtering requests based on the logged-in user type (Admin or regular user) +# - Managing CRUD operations for multiple publication types +# - Sending notifications via PublicationMailer upon successful publication submission +# - Redirecting based on various conditions such as user session and max submissions +# +# Special Behaviors: +# - Utilizes dynamic setting of instance variables and object types +# - Makes extensive use of helpers for finding records +# +# Filters: +# - set_object: Sets the object based on the controller name and params[:id]. +# - signed_in: Checks if the user is signed in before granting access to certain actions. +# - check_max_submissions: Checks if the maximum submission limit is reached for a given user. +# + class PublicationsController < ApplicationController before_action :set_object, only: %i[show edit update destroy] before_action :signed_in, only: %i[index show edit update destroy] diff --git a/app/helpers/mailer_helper.rb b/app/helpers/mailer_helper.rb index 95fdfbea..e3747e33 100644 --- a/app/helpers/mailer_helper.rb +++ b/app/helpers/mailer_helper.rb @@ -1,8 +1,37 @@ # frozen_string_literal: true +# MailerHelper Module +# ==================== +# +# The MailerHelper module provides utility methods to assist in email generation. +# It includes functionalities from PublicationsHelper to create a list of author names +# formatted as a single string. +# +# Included Modules: +# - PublicationsHelper: Provides helper methods for dealing with publications. +# +# Methods: +# - all_authors_email(publication): Returns a comma-separated string of all authors' +# names associated with a given publication. +# +# Example Usage: +# ``` +# publication = Publication.find(1) +# authors_string = all_authors_email(publication) +# ``` +# +# Note: This helper is intended to be used within the context of Rails' ActionMailer. + module MailerHelper include PublicationsHelper + + # Returns a comma-separated string of all authors' names associated with the given publication. + # + # @param publication [Publication] The publication whose authors' names are to be returned. + # @return [String] A comma-separated string of author names. def all_authors_email(publication) + return '' if publication.blank? || publication.author_first_name.nil? || publication.author_last_name.nil? + author_list = '' size = [0, (publication.author_first_name.count - 1)].max (0..size).each do |i| diff --git a/app/helpers/publications_helper.rb b/app/helpers/publications_helper.rb index adbb761e..e9291fac 100644 --- a/app/helpers/publications_helper.rb +++ b/app/helpers/publications_helper.rb @@ -1,6 +1,30 @@ # frozen_string_literal: true +# PublicationsHelper Module +# +# This helper module provides utility functions for handling publications, particularly for formatting and creating +# publication details such as authors, citations, and other publication attributes. +# +# Methods: +# - all_authors(publication) : Constructs a string of all authors for a given publication +# - author_citation(publication) : Constructs a citation style string for authors +# - authors_array(publication) : Returns an array of truncated author names for a given publication +# - author_name(publication, position): Returns the name of an author at a specific position +# - author_name_citation(publication, position): Returns the citation style name of an author at a specific position +# - author_comma(publication, position): Returns the name of an author at a specific position with a comma between the last and first name +# - publications_id(id) : Returns the full URL for a given publication ID +# - create_citation(publication) : Constructs a full citation string for a given publication +# - author_or_artist_label : Returns either 'Artist' or 'Author' based on the context +# +# Private Methods: +# - preprocess_attr(publication, *attrs) : Utility method to preprocess attributes for a given publication +# + module PublicationsHelper + # Constructs a string of all authors for a given publication. + # + # @param [Object] publication + # @return [String] A string of all authors separated by commas def all_authors(publication) author_list = '' size = [0, (publication.author_first_name.count - 1)].max @@ -15,6 +39,10 @@ def all_authors(publication) author_list end + # Constructs a citation-style string for authors. + # + # @param [Object] publication + # @return [String] A string representation of authors in citation format def author_citation(publication) return '' if publication.blank? || publication.author_first_name.nil? || publication.author_last_name.nil? @@ -39,6 +67,10 @@ def author_citation(publication) author_list end + # Returns an array of truncated author names for a given publication. + # + # @param [Object] publication + # @return [Array] An array of author names truncated to 12 characters def authors_array(publication) return [] if publication.blank? || publication.author_first_name.nil? || publication.author_last_name.nil? @@ -50,22 +82,45 @@ def authors_array(publication) author_array end + # Returns the full name of an author at a specific position. + # + # @param [Object] publication + # @param [Integer] position The index of the author in the list + # @return [String] Full name of the author def author_name(publication, position) "#{publication.author_first_name[position]} #{publication.author_last_name[position]}" end + # Returns the name of an author at a specific position in citation format. + # + # @param [Object] publication + # @param [Integer] position The index of the author in the list + # @return [String] Full name of the author in citation format def author_name_citation(publication, position) "#{publication.author_last_name[position]}, #{publication.author_first_name[position]}" end + # Returns the name of an author at a specific position with a comma in between the last name and first name. + # + # @param [Object] publication + # @param [Integer] position The index of the author in the list + # @return [String] Full name of the author with a comma def author_comma(publication, position) "#{publication.author_last_name[position]}, #{publication.author_first_name[position]}" end + # Returns the full URL for a given publication ID. + # + # @param [Integer] id The ID of the publication + # @return [String] The full URL for the publication def publications_id(id) "#{publications_path}/#{id}" end + # Constructs a full citation string for a given publication. + # + # @param [Object] publication + # @return [String] A string representing the full citation def create_citation(publication) return if publication.nil? @@ -102,12 +157,20 @@ def create_citation(publication) return_string end + # Returns either 'Artist' or 'Author' based on the controller context. + # + # @return [String] Either 'Artist' or 'Author' def author_or_artist_label params['controller'] == 'artworks' ? 'Artist' : 'Author' end private + # Utility method to preprocess attributes for a given publication. + # + # @param [Object] publication + # @param [Array] attrs List of attribute names to preprocess + # @return [String, nil] Preprocessed attribute value or nil if not found def preprocess_attr(publication, *attrs) attrs.each do |attr| if publication.respond_to?(attr) && publication.send(attr).present? diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index d84cb6e7..4d41886f 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -1,6 +1,37 @@ # frozen_string_literal: true +# ApplicationMailer Class +# ======================== +# +# The ApplicationMailer serves as the base class for all other mailers in the application. +# It sets default settings that are common to all mailers. For instance, it sets the default +# sender email address. +# +# Inherited From: +# - ActionMailer::Base: Inherits all the functionalities provided by ActionMailer. +# +# Constants: +# - None +# +# Methods: +# - None (Methods would be specific to individual mailers inheriting from this class) +# +# Environment Variables: +# - MAIL_SENDER: The default "from" email address. +# +# Example Usage: +# ``` +# class MyMailer < ApplicationMailer +# def welcome_email(user) +# @user = user +# mail(to: @user.email, subject: 'Welcome to My Site') +# end +# end +# ``` +# +# Note: Each specific mailer should inherit from this class to utilize the default settings. + class ApplicationMailer < ActionMailer::Base - default from: 'from@example.com' + default from: ENV.fetch('MAIL_SENDER') layout 'mailer' end diff --git a/app/mailers/publication_mailer.rb b/app/mailers/publication_mailer.rb index b536913f..120075de 100644 --- a/app/mailers/publication_mailer.rb +++ b/app/mailers/publication_mailer.rb @@ -1,13 +1,58 @@ # frozen_string_literal: true +# PublicationMailer +# ================= +# This mailer class is responsible for sending email notifications related to +# publications. It extends the ApplicationMailer, inheriting its default settings, and +# utilizes the MailerHelper for additional utility functions. +# +# Responsibilities: +# - Send confirmation email notifications when a publication is submitted. +# - Derive the sender's email and name from an environment variable, ensuring it's formatted correctly. +# +# Usage: +# Call the `publication_submit` method, providing it with the submitter and the publication. +# This sends an email to the submitter confirming the submission of their publication. +# The email also gets BCC'd to the default sender email for tracking purposes. +# +# Example: +# ``` +# PublicationMailer.publication_submit(submitter, publication).deliver_now +# ``` +# +# Environment Variables: +# - MAIL_SENDER: Contains the default sender's email address (and optionally the sender's name). + class PublicationMailer < ApplicationMailer helper MailerHelper - default from: -> { ENV.fetch('MAIL_SENDER', nil) } + + SUBJECT = 'Publication received for Artists, Authors, Editors & Composers' def publication_submit(submitter, publication) @submitter = submitter @publication = publication - receivers = "#{submitter.email_address}, #{ENV.fetch('MAIL_SENDER', nil)}" - mail(to: receivers, subject: 'Publication received for Artists, Authors, Editors & Composers') + sender_name, sender_email = parse_default_sender + submitter_name = "#{submitter.first_name} #{submitter.last_name}" + + mail( + to: email_address_with_name(@submitter.email_address, submitter_name), + bcc: sender_email, + from: email_address_with_name(sender_email, sender_name), + subject: SUBJECT + ) + end + + private + + def parse_default_sender + default_sender = ENV.fetch('MAIL_SENDER') + raise ArgumentError, 'SMTP From address may not be blank' if default_sender.blank? + + match_data = default_sender.match(/(.+?) <(.+)>/) + if match_data + [match_data[1], match_data[2]] # [sender_name, sender_email] + else + ['', default_sender] + end end end diff --git a/app/views/publication_mailer/publication_submit.html.erb b/app/views/publication_mailer/publication_submit.html.erb index b9f14256..e48f9572 100644 --- a/app/views/publication_mailer/publication_submit.html.erb +++ b/app/views/publication_mailer/publication_submit.html.erb @@ -1,5 +1,6 @@
- Thank you for your submission of "<%= @publication.work_title %>" by: <%= all_authors_email(@publication) %>.
+ <% work_or_other_title = @publication.work_title || @publication.other_title || "-untitled work-" %>
+ Thank you for your submission of "<%= work_or_other_title %>" by: <%= all_authors_email(@publication) %>.
More information about this year's event is forthcoming. If you have any questions, please contact Melissa Norris at melissa.norris@uc.edu or (513) 556-1558.