loading
Generated 2025-02-03T18:58:58+00:00

All Files ( 91.0% covered at 37.8 hits/line )

43 files in total.
878 relevant lines, 799 lines covered and 79 lines missed. ( 91.0% )
226 total branches, 186 branches covered and 40 branches missed. ( 82.3% )
File % covered Lines Relevant Lines Lines covered Lines missed Avg. Hits / Line Branch Coverage Branches Covered branches Missed branches
app/controllers/admin/admin_controller.rb 100.00 % 18 9 9 0 11.33 100.00 % 2 2 0
app/controllers/admin/bands_controller.rb 0.00 % 45 37 0 37 0.00 100.00 % 0 0 0
app/controllers/admin/impersonation_controller.rb 100.00 % 27 14 14 0 2.64 100.00 % 2 2 0
app/controllers/admin/users_controller.rb 100.00 % 62 29 29 0 5.48 90.00 % 10 9 1
app/controllers/application_controller.rb 85.33 % 155 75 64 11 85.95 71.88 % 32 23 9
app/controllers/bands_controller.rb 100.00 % 107 56 56 0 8.00 85.00 % 20 17 3
app/controllers/events_controller.rb 97.73 % 89 44 43 1 22.91 75.00 % 8 6 2
app/controllers/members_controller.rb 93.55 % 65 31 29 2 4.42 83.33 % 6 5 1
app/controllers/permissions_controller.rb 98.08 % 93 52 51 1 6.52 93.75 % 16 15 1
app/controllers/sessions_controller.rb 100.00 % 34 23 23 0 52.09 100.00 % 4 4 0
app/controllers/user_mails_controller.rb 100.00 % 38 19 19 0 6.00 100.00 % 6 6 0
app/controllers/users/registration_controller.rb 100.00 % 64 34 34 0 2.65 85.71 % 14 12 2
app/controllers/users_controller.rb 100.00 % 92 37 37 0 6.57 83.33 % 12 10 2
app/helpers/application_helper.rb 100.00 % 76 39 39 0 128.95 100.00 % 13 13 0
app/helpers/bands_helper.rb 100.00 % 2 1 1 0 1.00 100.00 % 0 0 0
app/helpers/events_helper.rb 100.00 % 26 17 17 0 73.24 100.00 % 9 9 0
app/helpers/members_helper.rb 100.00 % 2 1 1 0 1.00 100.00 % 0 0 0
app/helpers/permissions_helper.rb 100.00 % 23 14 14 0 60.00 100.00 % 0 0 0
app/helpers/sessions_helper.rb 100.00 % 2 1 1 0 1.00 100.00 % 0 0 0
app/helpers/users/registration_helper.rb 100.00 % 2 1 1 0 1.00 100.00 % 0 0 0
app/jobs/application_job.rb 100.00 % 7 1 1 0 1.00 100.00 % 0 0 0
app/jobs/send_mail_job.rb 66.67 % 9 6 4 2 0.67 100.00 % 0 0 0
app/lib/form_builders/nice_form_builder.rb 100.00 % 186 78 78 0 32.36 77.78 % 18 14 4
app/mailers/application_mailer.rb 100.00 % 3 2 2 0 8.00 100.00 % 0 0 0
app/mailers/test_mailer.rb 0.00 % 11 10 0 10 0.00 100.00 % 0 0 0
app/mailers/user_mailer.rb 87.50 % 42 16 14 2 3.13 50.00 % 2 1 1
app/models/application_record.rb 100.00 % 3 2 2 0 1.00 100.00 % 0 0 0
app/models/band.rb 94.12 % 27 17 16 1 1.00 50.00 % 2 1 1
app/models/band_member.rb 100.00 % 4 3 3 0 16.00 100.00 % 0 0 0
app/models/bands_audit.rb 100.00 % 5 3 3 0 3.00 100.00 % 0 0 0
app/models/concerns/auditable.rb 100.00 % 42 19 19 0 7.68 100.00 % 0 0 0
app/models/confirmation_token.rb 100.00 % 15 8 8 0 9.00 100.00 % 0 0 0
app/models/current.rb 100.00 % 34 19 19 0 348.47 75.00 % 4 3 1
app/models/event.rb 100.00 % 32 14 14 0 11.64 50.00 % 2 1 1
app/models/event_band.rb 100.00 % 4 3 3 0 1.00 100.00 % 0 0 0
app/models/events_audit.rb 100.00 % 4 3 3 0 8.00 100.00 % 0 0 0
app/models/member.rb 66.67 % 52 24 16 8 11.63 12.50 % 8 1 7
app/models/member_skill.rb 100.00 % 6 4 4 0 16.00 100.00 % 0 0 0
app/models/members_audit.rb 100.00 % 4 3 3 0 3.00 100.00 % 0 0 0
app/models/permission.rb 89.74 % 74 39 35 4 49.77 78.57 % 14 11 3
app/models/skill.rb 100.00 % 6 4 4 0 1.00 100.00 % 0 0 0
app/models/user.rb 100.00 % 115 43 43 0 86.33 100.00 % 18 18 0
app/models/user_mail.rb 100.00 % 45 23 23 0 1.74 75.00 % 4 3 1

Controllers ( 88.7% covered at 22.44 hits/line )

13 files in total.
460 relevant lines, 408 lines covered and 52 lines missed. ( 88.7% )
132 total branches, 111 branches covered and 21 branches missed. ( 84.09% )
File % covered Lines Relevant Lines Lines covered Lines missed Avg. Hits / Line Branch Coverage Branches Covered branches Missed branches
app/controllers/admin/admin_controller.rb 100.00 % 18 9 9 0 11.33 100.00 % 2 2 0
app/controllers/admin/bands_controller.rb 0.00 % 45 37 0 37 0.00 100.00 % 0 0 0
app/controllers/admin/impersonation_controller.rb 100.00 % 27 14 14 0 2.64 100.00 % 2 2 0
app/controllers/admin/users_controller.rb 100.00 % 62 29 29 0 5.48 90.00 % 10 9 1
app/controllers/application_controller.rb 85.33 % 155 75 64 11 85.95 71.88 % 32 23 9
app/controllers/bands_controller.rb 100.00 % 107 56 56 0 8.00 85.00 % 20 17 3
app/controllers/events_controller.rb 97.73 % 89 44 43 1 22.91 75.00 % 8 6 2
app/controllers/members_controller.rb 93.55 % 65 31 29 2 4.42 83.33 % 6 5 1
app/controllers/permissions_controller.rb 98.08 % 93 52 51 1 6.52 93.75 % 16 15 1
app/controllers/sessions_controller.rb 100.00 % 34 23 23 0 52.09 100.00 % 4 4 0
app/controllers/user_mails_controller.rb 100.00 % 38 19 19 0 6.00 100.00 % 6 6 0
app/controllers/users/registration_controller.rb 100.00 % 64 34 34 0 2.65 85.71 % 14 12 2
app/controllers/users_controller.rb 100.00 % 92 37 37 0 6.57 83.33 % 12 10 2

Channels ( 100.0% covered at 0.0 hits/line )

0 files in total.
0 relevant lines, 0 lines covered and 0 lines missed. ( 100.0% )
0 total branches, 0 branches covered and 0 branches missed. ( 100.0% )
File % covered Lines Relevant Lines Lines covered Lines missed Avg. Hits / Line Branch Coverage Branches Covered branches Missed branches

Models ( 94.37% covered at 56.94 hits/line )

17 files in total.
231 relevant lines, 218 lines covered and 13 lines missed. ( 94.37% )
52 total branches, 38 branches covered and 14 branches missed. ( 73.08% )
File % covered Lines Relevant Lines Lines covered Lines missed Avg. Hits / Line Branch Coverage Branches Covered branches Missed branches
app/models/application_record.rb 100.00 % 3 2 2 0 1.00 100.00 % 0 0 0
app/models/band.rb 94.12 % 27 17 16 1 1.00 50.00 % 2 1 1
app/models/band_member.rb 100.00 % 4 3 3 0 16.00 100.00 % 0 0 0
app/models/bands_audit.rb 100.00 % 5 3 3 0 3.00 100.00 % 0 0 0
app/models/concerns/auditable.rb 100.00 % 42 19 19 0 7.68 100.00 % 0 0 0
app/models/confirmation_token.rb 100.00 % 15 8 8 0 9.00 100.00 % 0 0 0
app/models/current.rb 100.00 % 34 19 19 0 348.47 75.00 % 4 3 1
app/models/event.rb 100.00 % 32 14 14 0 11.64 50.00 % 2 1 1
app/models/event_band.rb 100.00 % 4 3 3 0 1.00 100.00 % 0 0 0
app/models/events_audit.rb 100.00 % 4 3 3 0 8.00 100.00 % 0 0 0
app/models/member.rb 66.67 % 52 24 16 8 11.63 12.50 % 8 1 7
app/models/member_skill.rb 100.00 % 6 4 4 0 16.00 100.00 % 0 0 0
app/models/members_audit.rb 100.00 % 4 3 3 0 3.00 100.00 % 0 0 0
app/models/permission.rb 89.74 % 74 39 35 4 49.77 78.57 % 14 11 3
app/models/skill.rb 100.00 % 6 4 4 0 1.00 100.00 % 0 0 0
app/models/user.rb 100.00 % 115 43 43 0 86.33 100.00 % 18 18 0
app/models/user_mail.rb 100.00 % 45 23 23 0 1.74 75.00 % 4 3 1

Mailers ( 57.14% covered at 2.36 hits/line )

3 files in total.
28 relevant lines, 16 lines covered and 12 lines missed. ( 57.14% )
2 total branches, 1 branches covered and 1 branches missed. ( 50.0% )
File % covered Lines Relevant Lines Lines covered Lines missed Avg. Hits / Line Branch Coverage Branches Covered branches Missed branches
app/mailers/application_mailer.rb 100.00 % 3 2 2 0 8.00 100.00 % 0 0 0
app/mailers/test_mailer.rb 0.00 % 11 10 0 10 0.00 100.00 % 0 0 0
app/mailers/user_mailer.rb 87.50 % 42 16 14 2 3.13 50.00 % 2 1 1

Helpers ( 100.0% covered at 96.19 hits/line )

7 files in total.
74 relevant lines, 74 lines covered and 0 lines missed. ( 100.0% )
22 total branches, 22 branches covered and 0 branches missed. ( 100.0% )
File % covered Lines Relevant Lines Lines covered Lines missed Avg. Hits / Line Branch Coverage Branches Covered branches Missed branches
app/helpers/application_helper.rb 100.00 % 76 39 39 0 128.95 100.00 % 13 13 0
app/helpers/bands_helper.rb 100.00 % 2 1 1 0 1.00 100.00 % 0 0 0
app/helpers/events_helper.rb 100.00 % 26 17 17 0 73.24 100.00 % 9 9 0
app/helpers/members_helper.rb 100.00 % 2 1 1 0 1.00 100.00 % 0 0 0
app/helpers/permissions_helper.rb 100.00 % 23 14 14 0 60.00 100.00 % 0 0 0
app/helpers/sessions_helper.rb 100.00 % 2 1 1 0 1.00 100.00 % 0 0 0
app/helpers/users/registration_helper.rb 100.00 % 2 1 1 0 1.00 100.00 % 0 0 0

Jobs ( 71.43% covered at 0.71 hits/line )

2 files in total.
7 relevant lines, 5 lines covered and 2 lines missed. ( 71.43% )
0 total branches, 0 branches covered and 0 branches missed. ( 100.0% )
File % covered Lines Relevant Lines Lines covered Lines missed Avg. Hits / Line Branch Coverage Branches Covered branches Missed branches
app/jobs/application_job.rb 100.00 % 7 1 1 0 1.00 100.00 % 0 0 0
app/jobs/send_mail_job.rb 66.67 % 9 6 4 2 0.67 100.00 % 0 0 0

Libraries ( 100.0% covered at 32.36 hits/line )

1 files in total.
78 relevant lines, 78 lines covered and 0 lines missed. ( 100.0% )
18 total branches, 14 branches covered and 4 branches missed. ( 77.78% )
File % covered Lines Relevant Lines Lines covered Lines missed Avg. Hits / Line Branch Coverage Branches Covered branches Missed branches
app/lib/form_builders/nice_form_builder.rb 100.00 % 186 78 78 0 32.36 77.78 % 18 14 4

app/controllers/admin/admin_controller.rb

100.0% lines covered

100.0% branches covered

9 relevant lines. 9 lines covered and 0 lines missed.
2 total branches, 2 branches covered and 0 branches missed.
    
  1. 11 module Admin
  2. 11 class AdminController < ApplicationController
  3. 11 before_action :require_admin!, :set_admin_border
  4. 11 private
  5. 11 def require_admin!
  6. 18 else: 16 then: 2 unless Current.user.admin? || Current.impersonating?
  7. 2 render plain: "Admins only",
  8. status: :forbidden
  9. end
  10. end
  11. 11 def set_admin_border
  12. 16 @admin_border = true
  13. end
  14. end
  15. end

app/controllers/admin/bands_controller.rb

0.0% lines covered

100.0% branches covered

37 relevant lines. 0 lines covered and 37 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. module Admin
  2. class BandsController < AdminController
  3. before_action :set_band, except: %i[
  4. index
  5. ]
  6. def index
  7. @bands = Band.all
  8. end
  9. def show
  10. end
  11. def edit
  12. end
  13. def update
  14. updated = @band.update(edit_band_params)
  15. if updated
  16. redirect_to edit_admin_band_path(@band), notice: "Band updated"
  17. else
  18. flash[:alert] = @band.errors.full_messages
  19. render :edit, status: :unprocessable_entity
  20. end
  21. end
  22. def destroy
  23. @band.destroy!
  24. redirect_to admin_bands_path, notice: "Band deleted."
  25. end
  26. private
  27. def set_band
  28. @band = Band.find(params[:id])
  29. redirect_to admin_bands_path, alert: "Band not found" unless @band
  30. end
  31. def edit_band_params
  32. params.require(:band).permit(
  33. :name
  34. )
  35. end
  36. end
  37. end

app/controllers/admin/impersonation_controller.rb

100.0% lines covered

100.0% branches covered

14 relevant lines. 14 lines covered and 0 lines missed.
2 total branches, 2 branches covered and 0 branches missed.
    
  1. 5 module Admin
  2. 5 class ImpersonationController < AdminController
  3. 5 def create
  4. 3 target_user = User.find(params[:user_id])
  5. 3 session[:impersonation] = {
  6. original_user_id: Current.user.id,
  7. target_user_id: target_user.id,
  8. started_at: Time.current.utc
  9. }
  10. 3 redirect_to(events_path, notice: "Impersonating '#{target_user.username}'")
  11. end
  12. 5 def destroy
  13. 2 else: 1 then: 1 return redirect_to(admin_users_path, alert: "No active impersonation session") unless session[:impersonation]
  14. 1 target_user = User.find(session[:impersonation]["target_user_id"])
  15. 1 original_user = User.find(session[:impersonation]["original_user_id"])
  16. 1 username = target_user.username
  17. 1 session[:user_id] = original_user.id
  18. 1 session.delete(:impersonation)
  19. 1 redirect_to(admin_users_path, notice: "Ended impersonation of #{username}")
  20. end
  21. end
  22. end

app/controllers/admin/users_controller.rb

100.0% lines covered

90.0% branches covered

29 relevant lines. 29 lines covered and 0 lines missed.
10 total branches, 9 branches covered and 1 branches missed.
    
  1. 10 module Admin
  2. 10 class UsersController < AdminController
  3. 10 before_action :set_user, except: %i[
  4. index
  5. ]
  6. 10 def index
  7. 4 then: 2 else: 2 @user_type = params[:user_type]&.to_sym
  8. 4 then: 1 else: 3 if @user_type && !User.user_types[@user_type]
  9. 1 flash[:alert] = "Invalid user type"
  10. 1 redirect_to admin_users_path
  11. end
  12. 4 @user_types = User.user_types.keys
  13. @users =
  14. 4 then: 2 if @user_type
  15. 2 User.where(user_type: @user_type)
  16. else: 2 else
  17. 2 User.all
  18. end
  19. end
  20. 10 def show
  21. end
  22. 10 def edit
  23. end
  24. 10 def update
  25. 3 updated = @user.update(edit_user_params)
  26. 2 then: 1 if updated
  27. 1 redirect_to edit_admin_user_path(@user), notice: "User updated"
  28. else: 1 else
  29. 1 flash[:alert] = @user.errors.full_messages
  30. 1 render :edit, status: :unprocessable_entity
  31. end
  32. end
  33. 10 def destroy
  34. 1 @user.destroy!
  35. 1 redirect_to admin_users_path, notice: "User deleted."
  36. end
  37. 10 private
  38. 10 def set_user
  39. 7 @user = User.find_by(username: params[:username])
  40. 7 else: 7 then: 0 redirect_to admin_users_path, alert: "User not found" unless @user
  41. end
  42. 10 def edit_user_params
  43. 3 params.require(:user).permit(
  44. :username,
  45. :name,
  46. :email,
  47. :user_type
  48. )
  49. end
  50. end
  51. end

app/controllers/application_controller.rb

85.33% lines covered

71.88% branches covered

75 relevant lines. 64 lines covered and 11 lines missed.
32 total branches, 23 branches covered and 9 branches missed.
    
  1. # frozen_string_literal: true
  2. 16 class ApplicationController < ActionController::Base
  3. 16 before_action :set_current_user
  4. 16 before_action :require_login
  5. 16 helper_method :show_tabs, :nav_tabs, :my_pending_invites, :body_class, :set_current_user_by_session
  6. 16 def nav_tabs
  7. 389 else: 382 then: 7 return unless show_tabs
  8. 382 @nav_tabs ||= build_nav_tabs
  9. end
  10. 16 def my_pending_invites
  11. 198 then: 191 else: 7 else: 62 then: 136 return unless Current.user&.member?
  12. 62 @my_pending_invites ||= Permission.where(user_id: Current.user.id, status: "pending")
  13. end
  14. 16 def body_class
  15. 198 then: 7 else: 191 @admin_border ? "admin-background" : ""
  16. end
  17. 16 def show_tabs
  18. 580 @show_tabs ||= Current.user.present?
  19. end
  20. 16 private
  21. 16 def set_current_user
  22. 409 set_current_user_by_session(session)
  23. end
  24. 16 def set_current_user_by_session(session)
  25. 410 then: 2 if session[:impersonation]
  26. 2 else: 408 handle_impersonation(session)
  27. 408 then: 275 elsif session[:user_id]
  28. 275 set_regular_user(session[:user_id])
  29. else: 133 else
  30. 133 clear_current_user
  31. end
  32. end
  33. 16 def handle_impersonation(session)
  34. 2 impersonation = session[:impersonation]
  35. original_user_id =
  36. 2 impersonation["original_user_id"] ||
  37. impersonation[:original_user_id]
  38. target_user_id =
  39. 2 impersonation["target_user_id"] ||
  40. impersonation[:target_user_id]
  41. started_at =
  42. 2 impersonation["started_at"] ||
  43. impersonation[:started_at]
  44. 2 original_user = User.find_by(id: original_user_id)
  45. 2 target_user = User.find_by(id: target_user_id)
  46. 2 then: 2 if valid_impersonation?(original_user, target_user, started_at)
  47. 2 set_impersonated_user(original_user, target_user)
  48. else: 0 else
  49. end_impersonation(session)
  50. end
  51. end
  52. 16 def valid_impersonation?(original_user, target_user, started_at)
  53. failure_reasons = {
  54. 2 then: 2 else: 0 original_not_admin: !original_user&.admin?,
  55. no_target_user: !target_user,
  56. missing_time: !started_at,
  57. too_old: started_at && started_at.to_time < 12.hours.ago
  58. 8 }.select! { |k, v| !!v }.keys
  59. 2 then: 0 if failure_reasons.any?
  60. then: 0 else: 0 if request
  61. flash[:alert] = "Impersonation failed: #{failure_reasons.inspect}"
  62. end
  63. false
  64. else: 2 else
  65. 2 true
  66. end
  67. end
  68. 16 def set_impersonated_user(original_user, target_user)
  69. 2 Current.user = target_user
  70. 2 Current.impersonator = original_user
  71. end
  72. 16 def set_regular_user(user_id)
  73. 275 user = User.find_by(id: user_id)
  74. 275 then: 275 if user
  75. 275 Current.user = user
  76. 275 Current.impersonator = nil
  77. else: 0 else
  78. clear_current_user
  79. end
  80. end
  81. 16 def clear_current_user
  82. 133 Current.user = nil
  83. 133 Current.impersonator = nil
  84. end
  85. 16 def end_impersonation(session)
  86. session.delete(:impersonation)
  87. set_regular_user(session[:user_id])
  88. end
  89. 16 def require_login
  90. 409 then: 276 else: 133 then: 408 else: 1 return if Current.user&.confirmed? || allowed_path?
  91. 1 then: 0 if Current.user && !Current.user.confirmed?
  92. handle_unconfirmed_user
  93. else: 1 else
  94. 1 redirect_to_login
  95. end
  96. end
  97. 16 def allowed_path?
  98. [
  99. 133 login_path,
  100. logout_path,
  101. register_path,
  102. not_confirmed_path,
  103. resend_confirmation_path,
  104. confirm_registration_path,
  105. confirm_registration_submit_path
  106. ].include?(request.path)
  107. end
  108. 16 def handle_unconfirmed_user
  109. else: 0 then: 0 unless [not_confirmed_path, resend_confirmation_path].include?(request.path)
  110. flash[:alert] = "Your account is not confirmed"
  111. redirect_to not_confirmed_path
  112. end
  113. end
  114. 16 def redirect_to_login
  115. 1 flash[:alert] = "You must be logged in"
  116. 1 redirect_to login_url
  117. end
  118. 16 def build_nav_tabs
  119. tabs = [
  120. 191 {display_name: "Events", url: events_path},
  121. {display_name: "Bands", url: bands_path}
  122. ]
  123. 191 then: 129 else: 62 if Current.user.admin? || Current.user.organiser?
  124. 129 tabs << {display_name: "Sharing", url: permissions_path}
  125. end
  126. 191 tabs
  127. end
  128. end

app/controllers/bands_controller.rb

100.0% lines covered

85.0% branches covered

56 relevant lines. 56 lines covered and 0 lines missed.
20 total branches, 17 branches covered and 3 branches missed.
    
  1. 16 class BandsController < ApplicationController
  2. 16 include EventsHelper
  3. 16 before_action :set_band, only: %i[show edit update destroy]
  4. 16 before_action :set_view, only: %i[show edit update]
  5. 16 before_action :verify_organiser, only: %i[create]
  6. 16 before_action :verify_organiser_or_admin, only: %i[destroy]
  7. 16 def index
  8. 8 @bands = Current.user.bands
  9. 8 @bands = sort_bands(@bands, params[:sort])
  10. 8 then: 1 if @bands.count == 0
  11. 1 else: 7 redirect_to action: :new
  12. 7 then: 1 else: 6 elsif !Current.user.admin? && @bands.count == 1
  13. 1 redirect_to @bands.first
  14. end
  15. end
  16. 16 def edit
  17. end
  18. 16 def show
  19. end
  20. 16 def new
  21. 1 @band = Band.new
  22. end
  23. 16 def create
  24. 2 @band = Band.new(band_params)
  25. begin
  26. 2 Band.transaction do
  27. 2 @band.save!
  28. 2 Permission.create!(
  29. item_type: "Band",
  30. item_id: @band.id,
  31. user_id: Current.user.id,
  32. status: :owned,
  33. permission_type: :edit
  34. )
  35. end
  36. 1 redirect_to @band, notice: "Band was successfully created"
  37. rescue ActiveRecord::RecordInvalid
  38. 1 render :new, status: :unprocessable_entity
  39. end
  40. end
  41. 16 def update
  42. 2 then: 1 if @band.update(band_params)
  43. 1 redirect_to @band, notice: "Band was successfully updated."
  44. else: 1 else
  45. 1 render :edit
  46. end
  47. end
  48. 16 def destroy
  49. 4 Rails.logger.debug { "Attempting to destroy band: #{@band.inspect}" }
  50. 2 then: 1 if @band.destroy
  51. 2 Rails.logger.debug { "Band destroyed: #{@band.inspect}" }
  52. 1 redirect_to bands_url, notice: "Band was successfully destroyed."
  53. else: 1 else
  54. 2 Rails.logger.debug { "Band cannot be deleted: #{@band.errors.inspect}" }
  55. 1 redirect_to @band, alert: @band.errors.full_messages.to_sentence
  56. end
  57. end
  58. 16 private
  59. 16 def set_band
  60. 6 @band = Current.user.bands.find(params[:id])
  61. 6 @events = @band.events
  62. 6 .then { |rel| filter_by_period(rel, params[:period]) }
  63. 6 .then { |rel| sort_results(rel, params[:sort]) }
  64. end
  65. 16 def set_view
  66. 4 @views = %w[overview events shares]
  67. 4 @views_subtitles = [nil, "(#{@band.events.count})", nil]
  68. @view =
  69. 4 then: 0 @views.include?(params["view"]) ?
  70. else: 4 params["view"] :
  71. "overview"
  72. end
  73. 16 def verify_organiser
  74. 2 else: 2 then: 0 redirect_to bands_url unless Current.user.organiser?
  75. end
  76. 16 def verify_organiser_or_admin
  77. 2 else: 2 then: 0 redirect_to bands_url unless Current.user.organiser? || Current.user.admin?
  78. end
  79. 16 def sort_bands(bands, sort_param)
  80. 8 then: 4 else: 4 sort_by, sort_order = sort_param&.split
  81. 8 then: 3 if sort_by.present? && Band.column_names.include?(sort_by)
  82. 3 then: 2 else: 1 bands.order(sort_by => ((sort_order == "DESC") ? :desc : :asc))
  83. else: 5 else
  84. 5 bands.order(name: :asc)
  85. end
  86. end
  87. 16 def band_params
  88. 4 params.require(:band).permit(:name, :description, member_ids: [])
  89. end
  90. end

app/controllers/events_controller.rb

97.73% lines covered

75.0% branches covered

44 relevant lines. 43 lines covered and 1 lines missed.
8 total branches, 6 branches covered and 2 branches missed.
    
  1. 16 class EventsController < ApplicationController
  2. 16 include EventsHelper
  3. 16 before_action :set_event, only: %i[show edit update destroy]
  4. 16 before_action :set_bands, only: %i[new edit create update]
  5. 16 def index
  6. 149 @events = Current.user.events
  7. 149 .then { |rel| filter_by_period(rel, params[:period]) }
  8. 149 .then { |rel| filter_by_band(rel, params[:band_id]) }
  9. 149 .then { |rel| sort_results(rel, params[:sort]) }
  10. end
  11. 16 def new
  12. 1 @event = Event.new
  13. 1 then: 0 else: 1 @event.band_ids = [params[:band_id]] if params[:band_id].present?
  14. end
  15. 16 def show
  16. end
  17. 16 def edit
  18. end
  19. 16 def create
  20. 4 @event = Event.new(event_params)
  21. 3 then: 3 if @event.save
  22. 3 create_owner_permission(@event)
  23. 1 redirect_to @event, notice: "Event was successfully created"
  24. else: 0 else
  25. render :new, status: :unprocessable_entity
  26. end
  27. end
  28. 16 def update
  29. 10 then: 8 if @event.update(event_params)
  30. 8 redirect_to @event, notice: "Event was successfully updated."
  31. else: 1 else
  32. 1 render :edit, status: :unprocessable_entity
  33. end
  34. end
  35. 16 def destroy
  36. 2 @event.destroy!
  37. 1 redirect_to events_url, notice: "Event was successfully destroyed."
  38. rescue ActiveRecord::RecordNotDestroyed
  39. 1 redirect_to @event, alert: @event.errors.full_messages.to_sentence
  40. end
  41. 16 private
  42. 16 def set_event
  43. 15 @event = Current.user.events.find(params[:id])
  44. rescue ActiveRecord::RecordNotFound
  45. 2 redirect_to events_url, alert: "Event not found."
  46. end
  47. 16 def set_bands
  48. 15 @bands = Current.user.bands
  49. end
  50. 16 def event_params
  51. 14 permitted = params.require(:event).permit(
  52. :name,
  53. :description,
  54. :start_date,
  55. band_ids: []
  56. )
  57. 14 permitted_band_ids = @bands.pluck(:id)
  58. 14 permitted.tap do |params|
  59. 14 params[:band_ids] = params[:band_ids].to_a.compact_blank.map(&:to_i)
  60. 14 invalid_bands = params[:band_ids] - permitted_band_ids
  61. 14 then: 1 else: 13 if invalid_bands.any?
  62. 1 raise ArgumentError, "Invalid band_ids: #{invalid_bands}"
  63. end
  64. end
  65. end
  66. 16 def create_owner_permission(event)
  67. 3 event.permissions.create!(
  68. user: Current.user,
  69. status: :owned,
  70. permission_type: :edit
  71. )
  72. end
  73. end

app/controllers/members_controller.rb

93.55% lines covered

83.33% branches covered

31 relevant lines. 29 lines covered and 2 lines missed.
6 total branches, 5 branches covered and 1 branches missed.
    
  1. 9 class MembersController < ApplicationController
  2. 9 before_action :set_member, only: [:show, :edit, :update, :destroy]
  3. 9 def edit
  4. end
  5. 9 def show
  6. end
  7. 9 def index
  8. 1 @members = Member.all
  9. end
  10. 9 def new
  11. 1 @member = Member.new
  12. end
  13. 9 def create
  14. 2 @member = Member.new(member_params)
  15. 2 else: 1 then: 1 return render :new, status: :unprocessable_entity unless @member.save
  16. 1 @permission = Permission.create(
  17. item_type: "Member",
  18. item_id: @member.id,
  19. user: Current.user,
  20. status: :owned,
  21. permission_type: "edit"
  22. )
  23. 1 else: 1 then: 0 return render :new, status: :unprocessable_entity unless @permission.save
  24. 1 redirect_to @member, notice: "Member was successfully created."
  25. end
  26. 9 def update
  27. 2 Member.transaction do
  28. 2 @member.assign_attributes(member_params)
  29. 2 then: 1 if @member.save
  30. 1 redirect_to @member, notice: "Member was successfully updated." and return
  31. else: 1 else
  32. 1 logger.warn "members/update error: #{@member.errors.full_messages}"
  33. 1 render :edit, status: :unprocessable_entity and return
  34. end
  35. end
  36. rescue ActiveRecord::RecordInvalid => e
  37. logger.warn "members/update transaction error: #{e.message}"
  38. render :edit, status: :unprocessable_entity
  39. end
  40. 9 def destroy
  41. 1 @member.destroy!
  42. 1 redirect_to members_url, notice: "Member was successfully destroyed."
  43. end
  44. 9 private
  45. 9 def set_member
  46. 5 @member = Current.user.members.find(params[:id])
  47. end
  48. 9 def member_params
  49. 4 params.require(:member).permit(
  50. :name, :description, :skills_list, band_ids: []
  51. )
  52. end
  53. end

app/controllers/permissions_controller.rb

98.08% lines covered

93.75% branches covered

52 relevant lines. 51 lines covered and 1 lines missed.
16 total branches, 15 branches covered and 1 branches missed.
    
  1. 14 class PermissionsController < ApplicationController
  2. 14 include PermissionsHelper
  3. 14 before_action :set_permission, only: [:update, :destroy]
  4. 14 before_action :organiser_only, only: [:new, :create]
  5. 14 before_action :set_form_options, only: [:new, :create]
  6. 14 def index
  7. @permissions =
  8. 6 then: 1 if Current.user.admin?
  9. 1 Permission.all
  10. else: 5 else
  11. 5 Permission.where(
  12. "bestowing_user_id = :user_id OR user_id = :user_id",
  13. user_id: Current.user.id
  14. )
  15. end
  16. end
  17. 14 def new
  18. 1 @permission = Permission.new
  19. end
  20. 14 def create
  21. 3 params = permission_create_params
  22. 3 item_param = params.delete(:item)
  23. 3 @permission = Permission.new(params)
  24. 3 @permission.bestowing_user = Current.user
  25. 3 @permission.status = "pending"
  26. 3 @permission.item_type, @permission.item_id = item_param.split("_")
  27. 3 then: 2 else: 1 @permission.item_type&.capitalize!
  28. 3 then: 1 if @permission.save!
  29. 1 redirect_to permissions_path, notice: "Invitation created"
  30. else: 0 else
  31. render :new, status: :unprocessable_entity
  32. end
  33. end
  34. 14 def update
  35. 7 params = permission_update_params
  36. 7 then: 3 if !@permission.user || @permission.user != Current.user
  37. 3 else: 4 render plain: "Not your invite", status: :forbidden
  38. 4 then: 1 elsif !@permission.pending?
  39. 1 render plain: "Invite not pending", status: :bad_request
  40. else: 3 else
  41. 3 @permission.update(params)
  42. 2 then: 1 if @permission.accepted?
  43. 1 redirect_to @permission.item, notice: "Invitation accepted"
  44. else: 1 else
  45. 1 redirect_to permissions_path, alert: "Invitation rejected"
  46. end
  47. end
  48. rescue ArgumentError
  49. 1 render plain: "Not updated", status: :bad_request
  50. end
  51. 14 def destroy
  52. 3 then: 1 if Current.user.admin?
  53. 1 @permission.destroy!
  54. 1 redirect_to root_path, notice: "Invitation deleted"
  55. else: 2 else
  56. 2 render plain: "Only organisers can create permissions.", status: :forbidden
  57. end
  58. end
  59. 14 private
  60. 14 def organiser_only
  61. 6 else: 4 then: 2 unless Current.user.organiser?
  62. 2 render plain: "Organisers only", status: :forbidden
  63. end
  64. end
  65. 14 def set_form_options
  66. 4 @users = potential_users
  67. 4 @items = potential_items(Current.user)
  68. 4 @permission_types = %w[view edit]
  69. end
  70. 14 def set_permission
  71. 10 @permission = Permission.find(params[:id])
  72. end
  73. 14 def permission_create_params
  74. 3 params.require(:permission).permit(:user_id, :item, :permission_type)
  75. end
  76. 14 def permission_update_params
  77. 7 params.require(:permission).permit(:status)
  78. end
  79. end

app/controllers/sessions_controller.rb

100.0% lines covered

100.0% branches covered

23 relevant lines. 23 lines covered and 0 lines missed.
4 total branches, 4 branches covered and 0 branches missed.
    
  1. 16 class SessionsController < ApplicationController
  2. 16 def new
  3. 4 then: 2 else: 2 redirect_to events_path if Current.user
  4. 4 @user = User.new
  5. end
  6. 16 def create
  7. 137 username, password = login_params.values_at(:username, :password)
  8. 136 logger.debug("Login attempt from #{username}")
  9. 136 user = User.find_or_create_by(username: username)
  10. 136 then: 135 if user.authenticate(password)
  11. 135 session[:user_id] = user.id
  12. 135 logger.debug("Login success: #{username}")
  13. 135 redirect_to events_path, notice: "Logged in successfully."
  14. else: 1 else
  15. 1 @user = User.new
  16. 1 @user.username = username
  17. 1 logger.debug "Login failed: #{user.inspect}"
  18. 1 flash[:alert] = "Invalid username or password"
  19. 1 render :new, status: :unprocessable_entity
  20. end
  21. end
  22. 16 def destroy
  23. 1 session[:user_id] = nil
  24. 1 redirect_to login_path, notice: "Logged out successfully."
  25. end
  26. 16 private
  27. 16 def login_params
  28. 137 params.require(:user).permit(:username, :password)
  29. end
  30. end

app/controllers/user_mails_controller.rb

100.0% lines covered

100.0% branches covered

19 relevant lines. 19 lines covered and 0 lines missed.
6 total branches, 6 branches covered and 0 branches missed.
    
  1. 10 class UserMailsController < ApplicationController
  2. 10 before_action :set_mail, only: :show
  3. 10 before_action :can_view_mail, only: :show
  4. 10 def show
  5. end
  6. 10 def index
  7. @mails =
  8. 3 then: 1 if Current.user.admin?
  9. 1 UserMail.order(updated_at: :desc)
  10. else: 2 else
  11. 2 UserMail.where(user_id: Current.user.id).order(updated_at: :desc)
  12. end
  13. end
  14. 10 def create
  15. 2 @mail = UserMailer.send_confirmation_registration(Current.user)
  16. 2 then: 1 if @mail.persisted?
  17. 1 redirect_to user_mails_path, notice: "Confirmation sent successfully"
  18. else: 1 else
  19. 1 redirect_to user_mails_path, alert: "Failed to send confirmation"
  20. end
  21. end
  22. 10 private
  23. 10 def set_mail
  24. 5 @mail = UserMail.find(params[:id])
  25. end
  26. 10 def can_view_mail
  27. 5 then: 3 else: 2 return if @mail && (@mail.user_id == Current.user.id || Current.user.admin?)
  28. 2 redirect_to user_mails_path, alert: "Cannot view this mail"
  29. end
  30. end

app/controllers/users/registration_controller.rb

100.0% lines covered

85.71% branches covered

34 relevant lines. 34 lines covered and 0 lines missed.
14 total branches, 12 branches covered and 2 branches missed.
    
  1. 5 class Users::RegistrationController < ApplicationController
  2. 5 before_action :set_user, only: %i[
  3. edit
  4. update
  5. ]
  6. 5 def edit
  7. end
  8. 5 def update
  9. 1 else: 0 then: 1 UserMailer.send_confirmation_registration(@user) unless @user.confirmed?
  10. end
  11. 5 def new
  12. 4 @token = params[:token]
  13. 4 verifier = Rails.application.config.message_verifier
  14. begin
  15. 4 data = verifier.verify(@token)
  16. 3 @user = User.find(data["user_id"])
  17. 3 then: 1 else: 2 if @user.confirmed?
  18. 1 redirect_to account_path,
  19. notice: "Your account is already confirmed"
  20. end
  21. 3 then: 1 else: 2 then: 1 else: 2 if data["expires_at"]&.< Time.current.to_i
  22. 1 flash[:alert] = "Your confirmation link has expired: #{data}."
  23. 1 redirect_to register_path
  24. end
  25. rescue ActiveSupport::MessageVerifier::InvalidSignature
  26. 1 flash[:alert] = "Invalid confirmation link."
  27. 1 redirect_to register_path
  28. end
  29. end
  30. 5 def create
  31. 3 token = params[:token]
  32. 3 verifier = Rails.application.config.message_verifier
  33. begin
  34. 3 data = verifier.verify(token)
  35. 2 then: 2 else: 0 then: 1 if data["expires_at"]&.>= Time.current.to_i
  36. 1 @user = User.find(data["user_id"])
  37. 1 @user.update(confirmed: true)
  38. 1 flash[:notice] = "Your registration has been confirmed."
  39. 1 redirect_to login_path
  40. else: 1 else
  41. 1 flash[:alert] = "Your confirmation link has expired: #{data}."
  42. 1 redirect_to register_path
  43. end
  44. rescue ActiveSupport::MessageVerifier::InvalidSignature
  45. 1 flash[:alert] = "Invalid confirmation link."
  46. 1 redirect_to register_path
  47. end
  48. end
  49. 5 private
  50. 5 def set_user
  51. 2 @user = User.find(session[:user_id])
  52. 2 then: 1 else: 1 redirect_to account_path if @user.confirmed?
  53. end
  54. end

app/controllers/users_controller.rb

100.0% lines covered

83.33% branches covered

37 relevant lines. 37 lines covered and 0 lines missed.
12 total branches, 10 branches covered and 2 branches missed.
    
  1. 12 class UsersController < ApplicationController
  2. 12 before_action :check_admin_user, only: %i[
  3. create
  4. new
  5. ]
  6. 12 before_action :set_user, only: %i[
  7. edit
  8. update
  9. ]
  10. 12 before_action :check_not_logged_in, only: %i[
  11. create
  12. new
  13. ]
  14. 12 def new
  15. 1 @user = User.new
  16. end
  17. 12 def create
  18. 4 @user = User.new(create_user_params)
  19. 4 then: 1 else: 3 if @user.admin? && !@allow_admin_user
  20. 1 flash.now[:alert] = "No more admin users allowed"
  21. 1 return render :new, status: :unprocessable_entity
  22. end
  23. 3 then: 2 if @user.save
  24. 2 session[:user_id] = @user.id
  25. 2 redirect_to account_path, notice: "You registered successfully. Well done!"
  26. else: 1 else
  27. 1 render :new, status: :unprocessable_entity
  28. end
  29. end
  30. 12 def edit
  31. end
  32. 12 def update
  33. 4 then: 4 else: 0 if params[:user][:password].blank?
  34. 4 params[:user].delete(:password)
  35. 4 params[:user].delete(:password_confirmation)
  36. end
  37. 4 then: 2 if @user.update(update_user_params)
  38. 2 flash[:notice] = "Updated successfully"
  39. 2 redirect_to account_url
  40. else: 2 else
  41. 2 errors = @user.errors.full_messages.join(", ").downcase
  42. 2 render plain: "Could not update user: #{errors}",
  43. status: :forbidden
  44. end
  45. end
  46. 12 private
  47. 12 def create_user_params
  48. 4 params.require(:user).permit(
  49. :username,
  50. :name,
  51. :email,
  52. :password,
  53. :password_confirmation,
  54. :time_zone,
  55. :user_type
  56. )
  57. end
  58. 12 def update_user_params
  59. 4 params.require(:user).permit(
  60. :name,
  61. :email,
  62. :password,
  63. :password_confirmation,
  64. :time_zone
  65. )
  66. end
  67. 12 def set_user
  68. 6 @user = Current.user
  69. 6 else: 6 then: 0 redirect_to login_path unless @user
  70. end
  71. 12 def check_admin_user
  72. 6 @allow_admin_user = User.admin.count.zero?
  73. end
  74. 12 def check_not_logged_in
  75. 6 else: 5 then: 1 redirect_to account_path unless Current.user.nil?
  76. end
  77. end

app/helpers/application_helper.rb

100.0% lines covered

100.0% branches covered

39 relevant lines. 39 lines covered and 0 lines missed.
13 total branches, 13 branches covered and 0 branches missed.
    
  1. 1 module ApplicationHelper
  2. 1 def page_heading(str)
  3. 159 content_tag(:h1, str, class: "text-gray-900 text-xl")
  4. end
  5. 1 def filter_link(name, path, css_class, active)
  6. 449 link_to_if(!active, name, path, class: "#{css_class} hover:underline") do
  7. 149 content_tag(:span, name, class: "#{css_class} font-bold")
  8. end
  9. end
  10. 1 def table_header_sort(
  11. resource,
  12. column,
  13. display_text,
  14. default_sort_column = nil,
  15. default_sort_direction = "asc"
  16. )
  17. 271 then: 32 else: 239 current_sort_column, current_sort_direction = params[:sort]&.split
  18. 271 current_sort_column ||= default_sort_column
  19. 271 current_sort_direction ||= default_sort_direction
  20. 271 then: 9 if current_sort_column == column
  21. 9 then: 3 else: 6 new_sort_direction = (current_sort_direction == "asc") ? "desc" : "asc"
  22. 9 sort_icon = sort_direction_icon(current_sort_direction)
  23. else: 262 else
  24. 262 new_sort_direction = default_sort_direction
  25. end
  26. 271 params = {sort: "#{column} #{new_sort_direction}"}
  27. 271 then: 55 else: 216 params[:period] = request.params[:period] if request.params[:period]
  28. 271 new_params = request.query_parameters
  29. .except(:page, :sort)
  30. .merge(sort: "#{column} #{new_sort_direction}")
  31. 271 sort_url = url_for(new_params)
  32. 271 link_to "#{display_text}#{sort_icon}".html_safe, sort_url
  33. end
  34. 1 def flash_banner(key, msg = nil, &block)
  35. 152 content_tag :div, class: "#{key} banner" do
  36. 152 then: 6 else: 146 if block && msg.blank?
  37. 6 msg = capture(&block)
  38. end
  39. 152 concat(content_tag(:div, msg))
  40. 152 concat(hidden_checkbox_tag(key))
  41. 152 concat(close_button(key))
  42. end
  43. end
  44. 1 private
  45. 1 def sort_direction_icon(direction)
  46. 9 when: 3 case direction
  47. 3 when: 1 when "asc" then " <span>â–¼</span>"
  48. 1 else: 5 when "desc" then " <span>â–²</span>"
  49. 5 else ""
  50. end
  51. end
  52. 1 def hidden_checkbox_tag(key)
  53. 152 tag.input type: "checkbox", class: "hidden", id: "banneralert-#{key}"
  54. end
  55. 1 def close_button(key)
  56. 152 tag.label class: "close", style: "width:30px", for: "banneralert-#{key}" do
  57. 152 tag.svg class: "fill-current h-6 w-6", role: "button", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20" do
  58. 152 concat(tag.title("Close"))
  59. 152 concat(tag.path(d: "M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"))
  60. end
  61. end
  62. end
  63. end

app/helpers/bands_helper.rb

100.0% lines covered

100.0% branches covered

1 relevant lines. 1 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 1 module BandsHelper
  2. end

app/helpers/events_helper.rb

100.0% lines covered

100.0% branches covered

17 relevant lines. 17 lines covered and 0 lines missed.
9 total branches, 9 branches covered and 0 branches missed.
    
  1. 1 module EventsHelper
  2. 1 def filter_by_period(events, period)
  3. 155 when: 1 case period
  4. 1 when: 145 when "past" then events.past
  5. 145 else: 9 when "future", nil then events.future
  6. 9 else events
  7. end
  8. end
  9. 1 def filter_by_band(events, band_id)
  10. 149 else: 1 then: 148 return events unless band_id.present? && band_id.to_i.positive?
  11. 1 events.joins(:bands).where(bands: {id: band_id})
  12. end
  13. 1 def sort_results(events, sort_param)
  14. 155 column, direction = extract_sort_params(sort_param)
  15. 155 else: 5 then: 150 return events unless Event.attribute_names.include?(column.to_s)
  16. 5 events.order(column => direction)
  17. end
  18. 1 def extract_sort_params(sort_param)
  19. 155 col, dir = sort_param.to_s.split
  20. 155 then: 3 else: 152 dir = %w[desc DESC].include?(dir) ? :desc : :asc
  21. 155 [col.presence || :date, dir]
  22. end
  23. end

app/helpers/members_helper.rb

100.0% lines covered

100.0% branches covered

1 relevant lines. 1 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 1 module MembersHelper
  2. end

app/helpers/permissions_helper.rb

100.0% lines covered

100.0% branches covered

14 relevant lines. 14 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 1 module PermissionsHelper
  2. 1 def potential_users
  3. 4 User.member.pluck(:username, :id)
  4. end
  5. 1 def potential_items(owner)
  6. 46 invitable_klasses = [Event, Band, Member]
  7. 46 invitable_klasses.flat_map do |klass|
  8. 138 pluck_and_prefix(klass, owner)
  9. end
  10. end
  11. 1 private
  12. 1 def pluck_and_prefix(klass, owner)
  13. 138 owned_permissions = owner.send(:"owned_#{klass.to_s.downcase.pluralize}")
  14. 138 owned_item_ids = owned_permissions.pluck(:item_id)
  15. 138 items = klass.where(id: owned_item_ids).pluck(:id, :name)
  16. 138 items.map do |id, name|
  17. 49 ["#{name} (#{klass})", "#{klass}_#{id}"]
  18. end
  19. end
  20. end

app/helpers/sessions_helper.rb

100.0% lines covered

100.0% branches covered

1 relevant lines. 1 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 1 module SessionsHelper
  2. end

app/helpers/users/registration_helper.rb

100.0% lines covered

100.0% branches covered

1 relevant lines. 1 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 1 module Users::RegistrationHelper
  2. end

app/jobs/application_job.rb

100.0% lines covered

100.0% branches covered

1 relevant lines. 1 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 1 class ApplicationJob < ActiveJob::Base
  2. # Automatically retry jobs that encountered a deadlock
  3. # retry_on ActiveRecord::Deadlocked
  4. # Most jobs are safe to ignore if the underlying records are no longer available
  5. # discard_on ActiveJob::DeserializationError
  6. end

app/jobs/send_mail_job.rb

66.67% lines covered

100.0% branches covered

6 relevant lines. 4 lines covered and 2 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 1 class SendMailJob < ApplicationJob
  2. 1 queue_as :default
  3. 1 retry_on StandardError, wait: 1.minute, attempts: 5
  4. 1 def perform(user_mail_id)
  5. user_mail = UserMail.find(user_mail_id)
  6. user_mail.attempt_send
  7. end
  8. end

app/lib/form_builders/nice_form_builder.rb

100.0% lines covered

77.78% branches covered

78 relevant lines. 78 lines covered and 0 lines missed.
18 total branches, 14 branches covered and 4 branches missed.
    
  1. 12 module FormBuilders
  2. 12 class NiceFormBuilder < ActionView::Helpers::FormBuilder
  3. 12 class_attribute :text_field_helpers,
  4. default: field_helpers - %i[
  5. label
  6. check_box
  7. radio_button
  8. fields_for
  9. fields
  10. hidden_field
  11. file_field
  12. ]
  13. 12 TEXT_FIELD_STYLE = "text_field".freeze
  14. 12 TEXT_AREA_STYLE = "textarea_field".freeze
  15. 12 SELECT_FIELD_STYLE = "select_field".freeze
  16. 12 SUBMIT_BUTTON_STYLE = "primary_button".freeze
  17. 12 CHECKBOX_FIELD_STYLE = "checkbox_group".freeze
  18. 12 DATE_SELECT_STYLE = "date_select".freeze
  19. 12 TIME_SELECT_STYLE = "time_select".freeze
  20. 12 text_field_helpers.each do |field_method|
  21. 216 define_method(field_method) do |method, options = {}|
  22. 96 then: 48 if options.delete(:already_nice)
  23. 48 super(method, options)
  24. else: 48 else
  25. 48 text_like_field(field_method, method, options)
  26. end
  27. end
  28. end
  29. 12 def submit(value = nil, options = {})
  30. 23 custom_opts, opts = partition_custom_opts(options)
  31. 23 classes = apply_style_classes(SUBMIT_BUTTON_STYLE, custom_opts)
  32. 23 super(value, {class: classes}.merge(opts))
  33. end
  34. 12 def select(method, choices = nil, options = {}, html_options = {}, &block)
  35. 11 custom_opts, opts = partition_custom_opts(options)
  36. 11 classes = apply_style_classes(SELECT_FIELD_STYLE, custom_opts, method)
  37. 11 labels = labels(method, custom_opts[:label], options)
  38. 11 field = super(
  39. method,
  40. choices,
  41. opts,
  42. html_options.merge({class: classes}),
  43. &block
  44. )
  45. 11 @template.content_tag("div", labels + field, {class: "field"})
  46. end
  47. 12 def collection_checkboxes(
  48. method,
  49. collection,
  50. value_method,
  51. text_method,
  52. options = {},
  53. html_options = {},
  54. &block
  55. )
  56. 2 custom_opts, opts = partition_custom_opts(options)
  57. 2 classes = apply_style_classes(
  58. CHECKBOX_FIELD_STYLE,
  59. custom_opts,
  60. method
  61. )
  62. 2 labels = labels(method, custom_opts[:label], options)
  63. 2 html_options = html_options.merge(class: classes)
  64. 2 check_boxes = super(
  65. method,
  66. collection,
  67. value_method,
  68. text_method,
  69. opts,
  70. html_options,
  71. &block
  72. )
  73. 2 @template.content_tag(
  74. "div",
  75. labels + check_boxes,
  76. {class: "field"}
  77. )
  78. end
  79. 12 def date_select(method, options = {}, html_options = {})
  80. 2 custom_opts, opts = partition_custom_opts(options)
  81. 2 classes = apply_style_classes(nil, custom_opts, method)
  82. 2 labels = labels(method, custom_opts[:label], options)
  83. 2 field = @template.content_tag("div",
  84. super(method, opts, html_options.merge(class: classes)),
  85. {class: "flex flex-row gap-4"})
  86. 2 @template.content_tag("div", labels + field, {class: "field"})
  87. end
  88. 12 def time_select(method, options = {}, html_options = {})
  89. 2 custom_opts, opts = partition_custom_opts(options)
  90. 2 classes = apply_style_classes(nil, custom_opts, method)
  91. 2 labels = labels(method, custom_opts[:label], options)
  92. 2 field = @template.content_tag("div",
  93. super(method, opts, html_options.merge(class: classes)),
  94. {class: "flex flex-row gap-4"})
  95. 2 @template.content_tag("div", labels + field, {class: "field"})
  96. end
  97. 12 private
  98. 12 def text_like_field(field_method, object_method, options = {})
  99. 48 custom_opts, opts = partition_custom_opts(options)
  100. 48 then: 0 else: 48 style = (field_method == :text_area) ? TEXT_AREA_STYLE : TEXT_FIELD_STYLE
  101. 48 classes = apply_style_classes(style, custom_opts, object_method)
  102. field_options = {
  103. 48 class: classes,
  104. then: 48 else: 0 title: errors_for(object_method)&.join(" ")
  105. }.compact.merge(opts).merge(already_nice: true)
  106. 48 field = send(field_method, object_method, field_options)
  107. 48 labels = labels(object_method, custom_opts[:label], options)
  108. 48 @template.content_tag("div", labels + field, {class: "field"})
  109. end
  110. 12 def labels(object_method, label_options, field_options)
  111. 65 label = nice_label(object_method, label_options, field_options)
  112. 65 error_label = error_label(object_method, field_options)
  113. 65 label + error_label
  114. end
  115. 12 def nice_label(object_method, label_options, field_options)
  116. 67 then: 8 else: 59 text, label_opts = label_options.present? ? label_options.values_at(:text, :except) : [nil, {}]
  117. 67 label_opts ||= {}
  118. 67 label_classes = label_opts[:class].to_s
  119. 67 then: 0 else: 67 label_classes += " disabled" if field_options[:disabled]
  120. 67 label(object_method, text, {
  121. class: label_classes.strip
  122. }.merge(label_opts.except(:class)))
  123. end
  124. 12 def error_label(object_method, options)
  125. 65 then: 63 else: 2 return if errors_for(object_method).blank?
  126. 2 error_message = @object.errors[object_method].collect(&:titleize).join(", ")
  127. 2 nice_label(object_method, {text: error_message, class: "error_message"}, options)
  128. end
  129. 12 def border_color_classes(object_method)
  130. 88 else: 65 then: 23 return "" unless object_method
  131. 65 then: 2 else: 63 "has_error" if errors_for(object_method).present?
  132. end
  133. 12 def apply_style_classes(base_class, custom_opts, object_method = nil)
  134. [
  135. 88 base_class,
  136. border_color_classes(object_method),
  137. custom_opts[:class]
  138. ].compact.join(" ")
  139. end
  140. 12 CUSTOM_OPTS = [:label, :class].freeze
  141. 12 def partition_custom_opts(opts)
  142. 116 opts.partition { |k, _| CUSTOM_OPTS.include?(k) }.map(&:to_h)
  143. end
  144. 12 def errors_for(object_method)
  145. 178 else: 178 then: 0 return unless @object.present? && object_method.present?
  146. 178 @object.errors[object_method]
  147. end
  148. end
  149. end

app/mailers/application_mailer.rb

100.0% lines covered

100.0% branches covered

2 relevant lines. 2 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 8 class ApplicationMailer < ActionMailer::Base
  2. 8 layout "mailer"
  3. end

app/mailers/test_mailer.rb

0.0% lines covered

100.0% branches covered

10 relevant lines. 0 lines covered and 10 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class TestMailer < ApplicationMailer
  2. def test_email(to)
  3. Rails.logger.info "Preparing to send test email to #{to}."
  4. mail(
  5. to: to,
  6. subject: "Test Email",
  7. body: "This is a test email."
  8. )
  9. end
  10. end

app/mailers/user_mailer.rb

87.5% lines covered

50.0% branches covered

16 relevant lines. 14 lines covered and 2 lines missed.
2 total branches, 1 branches covered and 1 branches missed.
    
  1. # app/mailers/user_mailer.rb
  2. 8 class UserMailer < ApplicationMailer
  3. 8 CONFIRM_REGISTRATION_SUBJECT = "Thank you for joining Libregig"
  4. 8 def confirm_registration(user_mail)
  5. 1 @username = user_mail.params["username"]
  6. 1 @url = user_mail.params["url"]
  7. 1 mail(to: user_mail.recipient, subject: CONFIRM_REGISTRATION_SUBJECT)
  8. end
  9. 8 def self.send_confirmation_registration(user)
  10. 1 confirmation_token = user.confirmation_tokens.create!(token: SecureRandom.urlsafe_base64)
  11. 1 user_mail = UserMail.new(
  12. user: user,
  13. recipient: user.email,
  14. subject: CONFIRM_REGISTRATION_SUBJECT,
  15. template: "confirm_registration",
  16. params: {
  17. username: user.username,
  18. url: generate_confirmation_url(confirmation_token)
  19. }
  20. )
  21. 1 then: 1 if user_mail.save
  22. 1 SendMailJob.perform_later(user_mail.id)
  23. else: 0 else
  24. errors = user_mail.errors.full_messages.join(", ")
  25. Rails.logger.error("Failed to create UserMail: #{errors}")
  26. end
  27. 1 user_mail
  28. end
  29. 8 def self.generate_confirmation_url(confirmation_token)
  30. 2 Rails.application.routes.url_helpers.confirm_registration_url(
  31. token: confirmation_token.token,
  32. host: Rails.configuration.server_url
  33. )
  34. end
  35. end

app/models/application_record.rb

100.0% lines covered

100.0% branches covered

2 relevant lines. 2 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 1 class ApplicationRecord < ActiveRecord::Base
  2. 1 primary_abstract_class
  3. end

app/models/band.rb

94.12% lines covered

50.0% branches covered

17 relevant lines. 16 lines covered and 1 lines missed.
2 total branches, 1 branches covered and 1 branches missed.
    
  1. 1 class Band < ApplicationRecord
  2. 1 has_many :event_bands, dependent: :destroy
  3. 1 has_many :events, through: :event_bands
  4. 1 has_many :band_members, dependent: :restrict_with_error
  5. 1 has_many :members, through: :band_members
  6. 1 has_many :permission, as: :item, dependent: :destroy
  7. 1 validates :description, presence: true
  8. 1 validates :name, presence: true
  9. 1 include Auditable
  10. 1 audit_log_columns :name, :description
  11. 1 def owner
  12. 2 then: 2 else: 0 permission.where(status: :owned).first&.user
  13. end
  14. 1 def url
  15. 1 Rails.application.routes.url_helpers.edit_band_path(self)
  16. end
  17. 1 def editable?
  18. 1 Current.user.admin? ||
  19. Current.user.owned_bands.any? { |b| b.id == id }
  20. end
  21. end

app/models/band_member.rb

100.0% lines covered

100.0% branches covered

3 relevant lines. 3 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 16 class BandMember < ApplicationRecord
  2. 16 belongs_to :member
  3. 16 belongs_to :band
  4. end

app/models/bands_audit.rb

100.0% lines covered

100.0% branches covered

3 relevant lines. 3 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 3 class BandsAudit < ApplicationRecord
  2. 3 self.table_name = "bands_audit"
  3. 3 belongs_to :band
  4. end

app/models/concerns/auditable.rb

100.0% lines covered

100.0% branches covered

19 relevant lines. 19 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 1 module Auditable
  2. 1 extend ActiveSupport::Concern
  3. 1 included do
  4. 3 after_update_commit :log_changes
  5. end
  6. 1 def log_changes
  7. 17 changes_to_log.each do |column, values|
  8. 26 audit_class.create!(
  9. item_id => id,
  10. :column_changed => column,
  11. :old_value => values.first,
  12. :user_id => Current.user.id
  13. )
  14. end
  15. end
  16. 1 private
  17. 1 def changes_to_log
  18. 17 saved_changes.slice(*self.class.logged_columns)
  19. end
  20. 1 def audit_class
  21. 26 "#{self.class.name.pluralize}Audit".constantize
  22. end
  23. 1 def item_id
  24. 26 "#{self.class.name.downcase}_id"
  25. end
  26. 1 class_methods do
  27. 1 def audit_log_columns(*columns)
  28. 3 @logged_columns = columns.map(&:to_s)
  29. end
  30. 1 def logged_columns
  31. 17 @logged_columns || []
  32. end
  33. end
  34. end

app/models/confirmation_token.rb

100.0% lines covered

100.0% branches covered

8 relevant lines. 8 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 9 class ConfirmationToken < ApplicationRecord
  2. 9 belongs_to :user
  3. 9 before_create :set_expires_at, unless: :expires_at?
  4. 9 validates :token, presence: true, uniqueness: true
  5. 13 scope :valid, -> { where("expires_at > ?", Time.current) }
  6. 9 private
  7. 9 def set_expires_at
  8. 5 self.expires_at = 24.hours.from_now
  9. end
  10. end

app/models/current.rb

100.0% lines covered

75.0% branches covered

19 relevant lines. 19 lines covered and 0 lines missed.
4 total branches, 3 branches covered and 1 branches missed.
    
  1. 1 class Current < ActiveSupport::CurrentAttributes
  2. 1 attribute :_user
  3. 1 attribute :_impersonator
  4. 1297 resets { Time.zone = nil }
  5. 1 def user=(user)
  6. 416 self._user = user
  7. 416 update_time_zone
  8. end
  9. 1 def user
  10. 2641 _user
  11. end
  12. 1 def impersonator=(impersonator)
  13. 410 self._impersonator = impersonator
  14. 410 update_time_zone
  15. end
  16. 1 def impersonator
  17. 1 _impersonator
  18. end
  19. 1 def impersonating?
  20. 194 _impersonator.present?
  21. end
  22. 1 private
  23. 1 def update_time_zone
  24. 826 then: 560 else: 266 then: 0 else: 266 Time.zone = _user&.time_zone || _impersonator&.time_zone
  25. end
  26. end

app/models/event.rb

100.0% lines covered

50.0% branches covered

14 relevant lines. 14 lines covered and 0 lines missed.
2 total branches, 1 branches covered and 1 branches missed.
    
  1. 1 class Event < ApplicationRecord
  2. 1 has_many :event_bands, dependent: :destroy
  3. 1 has_many :bands, through: :event_bands
  4. 1 has_many :permissions, as: :item, dependent: :destroy
  5. 3 scope :past, -> { where(<<~SQL) }
  6. end_date IS NULL OR
  7. start_date IS NULL OR
  8. end_date <= CURRENT_TIMESTAMP
  9. SQL
  10. 147 scope :future, -> { where(<<~SQL) }
  11. end_date IS NULL OR
  12. start_date IS NULL OR
  13. end_date >= CURRENT_TIMESTAMP
  14. SQL
  15. 1 include Auditable
  16. 1 audit_log_columns :name, :description, :start_date, :end_date
  17. 1 def owner
  18. 2 then: 2 else: 0 permissions.where(status: :owned).first&.user
  19. end
  20. 1 def url
  21. 1 Rails.application.routes.url_helpers.edit_event_path(self)
  22. end
  23. 1 def external_url
  24. 1 Rails.application.routes.url_helpers.edit_event_url(self, host: Rails.application.config.server_url)
  25. end
  26. end

app/models/event_band.rb

100.0% lines covered

100.0% branches covered

3 relevant lines. 3 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 1 class EventBand < ApplicationRecord
  2. 1 belongs_to :event
  3. 1 belongs_to :band
  4. end

app/models/events_audit.rb

100.0% lines covered

100.0% branches covered

3 relevant lines. 3 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 8 class EventsAudit < ApplicationRecord
  2. 8 self.table_name = "events_audit"
  3. 8 belongs_to :event
  4. end

app/models/member.rb

66.67% lines covered

12.5% branches covered

24 relevant lines. 16 lines covered and 8 lines missed.
8 total branches, 1 branches covered and 7 branches missed.
    
  1. 1 class Member < ApplicationRecord
  2. 1 has_many :band_members, dependent: :destroy
  3. 1 has_many :bands, through: :band_members
  4. 1 has_many :member_skills, dependent: :destroy
  5. 1 has_many :skills, through: :member_skills
  6. 128 validates :skills, presence: true, if: -> { skills_list.present? }
  7. 1 has_many :permission, as: :item, dependent: :destroy
  8. 1 include Auditable
  9. 1 audit_log_columns :name, :description
  10. 1 def owner
  11. 9 then: 9 else: 0 Permission.where(
  12. status: :owned,
  13. item_type: "Member",
  14. item_id: id
  15. ).first&.user
  16. end
  17. 1 def skills_list
  18. 129 skills.pluck(:name).join(", ")
  19. end
  20. 1 def skills_list=(skills_string)
  21. then: 0 else: 0 return if skills_string.blank?
  22. skill_names =
  23. skills_string
  24. .downcase
  25. .split(",")
  26. .map(&:strip)
  27. .compact_blank
  28. .uniq
  29. then: 0 else: 0 return if skill_names.empty?
  30. transaction do
  31. member_skills.destroy_all
  32. skill_names.each do |name|
  33. skill = Skill.find_or_create_by!(name: name)
  34. else: 0 then: 0 member_skills.create!(skill: skill) unless member_skills.exists?(skill: skill)
  35. end
  36. end
  37. end
  38. 1 def editable
  39. 1 false
  40. end
  41. end

app/models/member_skill.rb

100.0% lines covered

100.0% branches covered

4 relevant lines. 4 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 16 class MemberSkill < ApplicationRecord
  2. 16 belongs_to :member
  3. 16 belongs_to :skill
  4. 16 validates :member_id, uniqueness: {scope: :skill_id}
  5. end

app/models/members_audit.rb

100.0% lines covered

100.0% branches covered

3 relevant lines. 3 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 3 class MembersAudit < ApplicationRecord
  2. 3 self.table_name = "members_audit"
  3. 3 belongs_to :member
  4. end

app/models/permission.rb

89.74% lines covered

78.57% branches covered

39 relevant lines. 35 lines covered and 4 lines missed.
14 total branches, 11 branches covered and 3 branches missed.
    
  1. 16 class Permission < ApplicationRecord
  2. 16 include PermissionsHelper
  3. 16 belongs_to :user, class_name: "User"
  4. 16 belongs_to :bestowing_user, class_name: "User", optional: true
  5. 16 belongs_to :item, polymorphic: true
  6. 16 scope :accepted, -> { where(status: :accepted) }
  7. 16 scope :accepted_or_owned, -> { where(status: %i[accepted owned]) }
  8. 16 scope :item_type, ->(type) { where(item_type: type) }
  9. 16 def self.join_models(model)
  10. table_name = model.to_s.pluralize
  11. klass_name = model.to_s.classify
  12. joins("
  13. JOIN #{table_name}
  14. ON #{table_name}.id = permissions.item_id
  15. AND permissions.item_type = '#{klass_name}'
  16. ")
  17. end
  18. 16 scope :bands, -> { join_models(:band) }
  19. 16 scope :events, -> { join_models(:event) }
  20. 16 scope :members, -> { join_models(:member) }
  21. 16 scope :system_permissions, -> { where(bestowing_user: nil) }
  22. 16 validates :item_type, presence: true
  23. 16 validates :permission_type, presence: true, inclusion: {in: %w[view edit]}
  24. 16 validates :status, presence: true, inclusion: {in: %w[owned pending accepted rejected]}
  25. 16 validate :bestowing_user_must_be_organiser_or_nil, :user_must_be_member_or_organiser
  26. 16 validate :valid_item
  27. 16 validate :valid_user
  28. 16 enum :status, {
  29. owned: "owned",
  30. pending: "pending",
  31. accepted: "accepted",
  32. rejected: "rejected"
  33. }
  34. 16 private
  35. 16 def valid_item
  36. 352 then: 310 else: 42 return true if bestowing_user.nil?
  37. 42 item_ids = potential_items(bestowing_user).pluck(1)
  38. 42 item_str = "#{item_type}_#{item_id}"
  39. 42 else: 39 then: 3 unless item_ids.include?(item_str)
  40. 3 errors.add(:item, "is not a valid selection for #{bestowing_user}. Valid options: #{item_ids}")
  41. end
  42. end
  43. 16 def valid_user
  44. # TODO: make this fancier
  45. 352 else: 352 then: 0 unless User.find(user_id)
  46. errors.add(:user, "is not a valid selection")
  47. end
  48. end
  49. 16 def bestowing_user_must_be_organiser_or_nil
  50. 352 else: 351 then: 1 unless bestowing_user.nil? || bestowing_user.organiser?
  51. 1 errors.add(:bestowing_user, "must be an organiser")
  52. end
  53. end
  54. 16 def user_must_be_member_or_organiser
  55. 352 then: 352 else: 0 then: 102 else: 0 else: 349 then: 3 unless user&.organiser? || user&.member?
  56. 3 errors.add(:user, "must be a member or organiser")
  57. end
  58. end
  59. end

app/models/skill.rb

100.0% lines covered

100.0% branches covered

4 relevant lines. 4 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. 1 class Skill < ApplicationRecord
  2. 1 has_many :member_skills, dependent: :destroy
  3. 1 has_many :members, through: :member_skills
  4. 1 validates :name, presence: true
  5. end

app/models/user.rb

100.0% lines covered

100.0% branches covered

43 relevant lines. 43 lines covered and 0 lines missed.
18 total branches, 18 branches covered and 0 branches missed.
    
  1. 1 class User < ApplicationRecord
  2. 1 enum :user_type, {admin: 0, member: 1, organiser: 2}
  3. 1 has_secure_password
  4. 1 has_many :permissions,
  5. dependent: :destroy,
  6. inverse_of: :user
  7. 65 has_many :owned_bands, -> { where(permissions: {item_type: "Band", status: :owned}) },
  8. through: :permissions,
  9. source: :item,
  10. source_type: "Band"
  11. 65 has_many :owned_events, -> { where(permissions: {item_type: "Event", status: :owned}) },
  12. through: :permissions,
  13. source: :item,
  14. source_type: "Event"
  15. 65 has_many :owned_members, -> { where(permissions: {item_type: "Member", status: :owned}) },
  16. through: :permissions,
  17. source: :item,
  18. source_type: "Member"
  19. 1 has_many :confirmation_tokens, dependent: :destroy
  20. 560 then: 556 else: 3 before_save { email&.downcase! }
  21. 1 before_validation :set_default_time_zone
  22. 1 validates :username,
  23. presence: true,
  24. uniqueness: true
  25. 1 validates :email,
  26. presence: {message: "can't be blank"},
  27. uniqueness: true,
  28. format: {with: URI::MailTo::EMAIL_REGEXP, message: "is invalid", allow_blank: true}
  29. 1 validates :password,
  30. presence: true,
  31. length: {minimum: 6},
  32. if: :password_required?,
  33. allow_blank: true
  34. 1 validates :password_confirmation,
  35. presence: true,
  36. allow_blank: true
  37. 1 validates :time_zone,
  38. inclusion: {
  39. 151 in: ActiveSupport::TimeZone.all.map { |t| t.tzinfo.name },
  40. message: "%{value} is not a valid time zone"
  41. }, allow_blank: true
  42. 1 def confirmed?
  43. 287 confirmed || admin?
  44. end
  45. 1 def to_param
  46. 204 username
  47. end
  48. 1 def owned_links
  49. 3 then: 1 else: 2 return @owned_links if defined?(@owned_links)
  50. @owned_links =
  51. 2 bands.select(:name, :id) +
  52. events.select(:name, :id) +
  53. members.select(:name, :id)
  54. end
  55. 1 def bands
  56. 36 then: 3 else: 33 return @bands if defined?(@bands)
  57. @bands =
  58. 33 then: 21 admin? ?
  59. else: 12 Band.all :
  60. Band.where(id: band_permissions.map(&:item_id))
  61. end
  62. 1 def events
  63. 172 then: 3 else: 169 return @events if defined?(@events)
  64. @events =
  65. 169 then: 88 admin? ?
  66. else: 81 Event.all :
  67. Event.where(id: event_permissions.map(&:item_id))
  68. end
  69. 1 def members
  70. 13 then: 3 else: 10 return @members if defined?(@members)
  71. @members =
  72. 10 then: 1 admin? ?
  73. else: 9 Member.all :
  74. Member.where(id: member_permissions.map(&:item_id))
  75. end
  76. 1 private
  77. 1 def password_required?
  78. 1169 new_record? || password.present?
  79. end
  80. 1 def event_permissions
  81. 81 permissions.where(status: [:accepted, :owned], item_type: "Event")
  82. end
  83. 1 def band_permissions
  84. 12 permissions.where(status: [:accepted, :owned], item_type: "Band")
  85. end
  86. 1 def member_permissions
  87. 9 permissions.where(status: [:accepted, :owned], item_type: "Member")
  88. end
  89. 1 def set_default_time_zone
  90. 583 then: 8 else: 575 self.time_zone = "Etc/UTC" if time_zone.blank?
  91. end
  92. end

app/models/user_mail.rb

100.0% lines covered

75.0% branches covered

23 relevant lines. 23 lines covered and 0 lines missed.
4 total branches, 3 branches covered and 1 branches missed.
    
  1. 1 class UserMail < ApplicationRecord
  2. 1 belongs_to :user
  3. 1 enum :state, {pending: 0, sending: 1, sent: 2, failed: 3}
  4. 1 validates :subject, presence: true, length: {maximum: 120}
  5. 1 validates :recipient, presence: true, length: {maximum: 255}
  6. 1 validates :template, presence: true, length: {maximum: 50}
  7. 1 validates :params, presence: true
  8. 1 def html_content
  9. 4 content(:html)
  10. end
  11. 1 def text_content
  12. 4 content(:text)
  13. end
  14. 1 def attempt_send
  15. 3 else: 2 then: 1 return unless pending?
  16. 2 update!(state: :sending)
  17. begin
  18. 2 UserMailer.confirm_registration(self).deliver_now
  19. 1 update!(state: :sent)
  20. 1 Rails.logger.info("Mail sent successfully to #{recipient}.")
  21. rescue => e
  22. 1 then: 0 else: 1 raise e if Rails.env.development?
  23. 1 update!(state: :failed)
  24. 1 Rails.logger.error("Failed to send mail to #{recipient}: #{e}")
  25. end
  26. end
  27. 1 private
  28. 1 def content(format)
  29. 8 ApplicationController.render(
  30. layout: false,
  31. template: "user_mailer/#{template}",
  32. assigns: params,
  33. formats: [format]
  34. )
  35. end
  36. end