loading
Generated 2023-07-08T14:19:37-04:00

All Files ( 0.0% covered at 0.0 hits/line )

60 files in total.
1223 relevant lines, 0 lines covered and 1223 lines missed. ( 0.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
app/controllers/activities_controller.rb 0.00 % 20 16 0 16 0.00 100.00 % 0 0 0
app/controllers/application_controller.rb 0.00 % 38 27 0 27 0.00 100.00 % 0 0 0
app/controllers/configurables_controller.rb 0.00 % 34 26 0 26 0.00 100.00 % 0 0 0
app/controllers/districts_controller.rb 0.00 % 67 49 0 49 0.00 100.00 % 0 0 0
app/controllers/profiles_controller.rb 0.00 % 24 18 0 18 0.00 100.00 % 0 0 0
app/controllers/representatives_controller.rb 0.00 % 70 51 0 51 0.00 100.00 % 0 0 0
app/controllers/schools_controller.rb 0.00 % 72 53 0 53 0.00 100.00 % 0 0 0
app/controllers/searches_controller.rb 0.00 % 6 6 0 6 0.00 100.00 % 0 0 0
app/controllers/spots/customers_controller.rb 0.00 % 10 7 0 7 0.00 100.00 % 0 0 0
app/controllers/spots/images_controller.rb 0.00 % 23 16 0 16 0.00 100.00 % 0 0 0
app/controllers/spots/reports/photographed_controller.rb 0.00 % 10 7 0 7 0.00 100.00 % 0 0 0
app/controllers/spots/reports/upcoming_appointments_controller.rb 0.00 % 9 6 0 6 0.00 100.00 % 0 0 0
app/controllers/spots/reports/yearbook_poses_controller.rb 0.00 % 22 15 0 15 0.00 100.00 % 0 0 0
app/controllers/spots/reports_controller.rb 0.00 % 23 15 0 15 0.00 100.00 % 0 0 0
app/controllers/spots_controller.rb 0.00 % 44 26 0 26 0.00 100.00 % 0 0 0
app/controllers/uploads_controller.rb 0.00 % 98 73 0 73 0.00 100.00 % 0 0 0
app/controllers/users_controller.rb 0.00 % 88 65 0 65 0.00 100.00 % 0 0 0
app/decorators/application_decorator.rb 0.00 % 10 2 0 2 0.00 100.00 % 0 0 0
app/jobs/application_job.rb 0.00 % 8 4 0 4 0.00 100.00 % 0 0 0
app/jobs/shrine_destroy_job.rb 0.00 % 10 8 0 8 0.00 100.00 % 0 0 0
app/jobs/shrine_promote_job.rb 0.00 % 13 10 0 10 0.00 100.00 % 0 0 0
app/mailers/application_mailer.rb 0.00 % 7 4 0 4 0.00 100.00 % 0 0 0
app/models/administrator.rb 0.00 % 8 6 0 6 0.00 100.00 % 0 0 0
app/models/application_record.rb 0.00 % 7 4 0 4 0.00 100.00 % 0 0 0
app/models/district.rb 0.00 % 58 45 0 45 0.00 100.00 % 0 0 0
app/models/representative.rb 0.00 % 87 67 0 67 0.00 100.00 % 0 0 0
app/models/school.rb 0.00 % 107 83 0 83 0.00 100.00 % 0 0 0
app/models/school_representative.rb 0.00 % 30 22 0 22 0.00 100.00 % 0 0 0
app/models/school_user.rb 0.00 % 31 26 0 26 0.00 100.00 % 0 0 0
app/models/spots.rb 0.00 % 4 2 0 2 0.00 100.00 % 0 0 0
app/models/spots/customer.rb 0.00 % 77 57 0 57 0.00 100.00 % 0 0 0
app/models/spots/image_properties_picture.rb 0.00 % 48 35 0 35 0.00 100.00 % 0 0 0
app/models/spots/pose_order.rb 0.00 % 26 18 0 18 0.00 100.00 % 0 0 0
app/models/spots/school.rb 0.00 % 52 42 0 42 0.00 100.00 % 0 0 0
app/models/spots/session.rb 0.00 % 13 9 0 9 0.00 100.00 % 0 0 0
app/models/spots_record.rb 0.00 % 15 10 0 10 0.00 100.00 % 0 0 0
app/models/studio_user.rb 0.00 % 8 6 0 6 0.00 100.00 % 0 0 0
app/models/upload.rb 0.00 % 40 33 0 33 0.00 100.00 % 0 0 0
app/models/user.rb 0.00 % 76 61 0 61 0.00 100.00 % 0 0 0
app/models/user_school.rb 0.00 % 30 22 0 22 0.00 100.00 % 0 0 0
app/policies/activity_policy.rb 0.00 % 7 5 0 5 0.00 100.00 % 0 0 0
app/policies/application_policy.rb 0.00 % 21 15 0 15 0.00 100.00 % 0 0 0
app/policies/configurable_policy.rb 0.00 % 11 8 0 8 0.00 100.00 % 0 0 0
app/policies/district_policy.rb 0.00 % 23 17 0 17 0.00 100.00 % 0 0 0
app/policies/profile_policy.rb 0.00 % 9 8 0 8 0.00 100.00 % 0 0 0
app/policies/representative_policy.rb 0.00 % 23 17 0 17 0.00 100.00 % 0 0 0
app/policies/school_policy.rb 0.00 % 23 17 0 17 0.00 100.00 % 0 0 0
app/policies/spots/customer_policy.rb 0.00 % 5 5 0 5 0.00 100.00 % 0 0 0
app/policies/spots/image_properties_picture_policy.rb 0.00 % 9 6 0 6 0.00 100.00 % 0 0 0
app/policies/spots/reports/photographed_policy.rb 0.00 % 7 6 0 6 0.00 100.00 % 0 0 0
app/policies/spots/reports/upcoming_appointments_policy.rb 0.00 % 7 6 0 6 0.00 100.00 % 0 0 0
app/policies/spots/reports/yearbook_poses_policy.rb 0.00 % 7 6 0 6 0.00 100.00 % 0 0 0
app/policies/spots/reports_policy.rb 0.00 % 3 3 0 3 0.00 100.00 % 0 0 0
app/policies/spots_policy.rb 0.00 % 2 2 0 2 0.00 100.00 % 0 0 0
app/policies/upload_policy.rb 0.00 % 28 21 0 21 0.00 100.00 % 0 0 0
app/policies/user_policy.rb 0.00 % 32 23 0 23 0.00 100.00 % 0 0 0
app/uploaders/data_uploader.rb 0.00 % 4 2 0 2 0.00 100.00 % 0 0 0
app/uploaders/square_image_uploader.rb 0.00 % 4 2 0 2 0.00 100.00 % 0 0 0
app/uploaders/wide_image_uploader.rb 0.00 % 4 2 0 2 0.00 100.00 % 0 0 0
lib/maily_hooks.rb 100.00 % 0 0 0 0 0.00 100.00 % 0 0 0

Controllers ( 0.0% covered at 0.0 hits/line )

17 files in total.
476 relevant lines, 0 lines covered and 476 lines missed. ( 0.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
app/controllers/activities_controller.rb 0.00 % 20 16 0 16 0.00 100.00 % 0 0 0
app/controllers/application_controller.rb 0.00 % 38 27 0 27 0.00 100.00 % 0 0 0
app/controllers/configurables_controller.rb 0.00 % 34 26 0 26 0.00 100.00 % 0 0 0
app/controllers/districts_controller.rb 0.00 % 67 49 0 49 0.00 100.00 % 0 0 0
app/controllers/profiles_controller.rb 0.00 % 24 18 0 18 0.00 100.00 % 0 0 0
app/controllers/representatives_controller.rb 0.00 % 70 51 0 51 0.00 100.00 % 0 0 0
app/controllers/schools_controller.rb 0.00 % 72 53 0 53 0.00 100.00 % 0 0 0
app/controllers/searches_controller.rb 0.00 % 6 6 0 6 0.00 100.00 % 0 0 0
app/controllers/spots/customers_controller.rb 0.00 % 10 7 0 7 0.00 100.00 % 0 0 0
app/controllers/spots/images_controller.rb 0.00 % 23 16 0 16 0.00 100.00 % 0 0 0
app/controllers/spots/reports/photographed_controller.rb 0.00 % 10 7 0 7 0.00 100.00 % 0 0 0
app/controllers/spots/reports/upcoming_appointments_controller.rb 0.00 % 9 6 0 6 0.00 100.00 % 0 0 0
app/controllers/spots/reports/yearbook_poses_controller.rb 0.00 % 22 15 0 15 0.00 100.00 % 0 0 0
app/controllers/spots/reports_controller.rb 0.00 % 23 15 0 15 0.00 100.00 % 0 0 0
app/controllers/spots_controller.rb 0.00 % 44 26 0 26 0.00 100.00 % 0 0 0
app/controllers/uploads_controller.rb 0.00 % 98 73 0 73 0.00 100.00 % 0 0 0
app/controllers/users_controller.rb 0.00 % 88 65 0 65 0.00 100.00 % 0 0 0

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 ( 0.0% covered at 0.0 hits/line )

18 files in total.
548 relevant lines, 0 lines covered and 548 lines missed. ( 0.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
app/models/administrator.rb 0.00 % 8 6 0 6 0.00 100.00 % 0 0 0
app/models/application_record.rb 0.00 % 7 4 0 4 0.00 100.00 % 0 0 0
app/models/district.rb 0.00 % 58 45 0 45 0.00 100.00 % 0 0 0
app/models/representative.rb 0.00 % 87 67 0 67 0.00 100.00 % 0 0 0
app/models/school.rb 0.00 % 107 83 0 83 0.00 100.00 % 0 0 0
app/models/school_representative.rb 0.00 % 30 22 0 22 0.00 100.00 % 0 0 0
app/models/school_user.rb 0.00 % 31 26 0 26 0.00 100.00 % 0 0 0
app/models/spots.rb 0.00 % 4 2 0 2 0.00 100.00 % 0 0 0
app/models/spots/customer.rb 0.00 % 77 57 0 57 0.00 100.00 % 0 0 0
app/models/spots/image_properties_picture.rb 0.00 % 48 35 0 35 0.00 100.00 % 0 0 0
app/models/spots/pose_order.rb 0.00 % 26 18 0 18 0.00 100.00 % 0 0 0
app/models/spots/school.rb 0.00 % 52 42 0 42 0.00 100.00 % 0 0 0
app/models/spots/session.rb 0.00 % 13 9 0 9 0.00 100.00 % 0 0 0
app/models/spots_record.rb 0.00 % 15 10 0 10 0.00 100.00 % 0 0 0
app/models/studio_user.rb 0.00 % 8 6 0 6 0.00 100.00 % 0 0 0
app/models/upload.rb 0.00 % 40 33 0 33 0.00 100.00 % 0 0 0
app/models/user.rb 0.00 % 76 61 0 61 0.00 100.00 % 0 0 0
app/models/user_school.rb 0.00 % 30 22 0 22 0.00 100.00 % 0 0 0

Mailers ( 0.0% covered at 0.0 hits/line )

1 files in total.
4 relevant lines, 0 lines covered and 4 lines missed. ( 0.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
app/mailers/application_mailer.rb 0.00 % 7 4 0 4 0.00 100.00 % 0 0 0

Helpers ( 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

Jobs ( 0.0% covered at 0.0 hits/line )

3 files in total.
22 relevant lines, 0 lines covered and 22 lines missed. ( 0.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
app/jobs/application_job.rb 0.00 % 8 4 0 4 0.00 100.00 % 0 0 0
app/jobs/shrine_destroy_job.rb 0.00 % 10 8 0 8 0.00 100.00 % 0 0 0
app/jobs/shrine_promote_job.rb 0.00 % 13 10 0 10 0.00 100.00 % 0 0 0

Libraries ( 100.0% covered at 0.0 hits/line )

1 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
lib/maily_hooks.rb 100.00 % 0 0 0 0 0.00 100.00 % 0 0 0

Decorators ( 0.0% covered at 0.0 hits/line )

1 files in total.
2 relevant lines, 0 lines covered and 2 lines missed. ( 0.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
app/decorators/application_decorator.rb 0.00 % 10 2 0 2 0.00 100.00 % 0 0 0

Policies ( 0.0% covered at 0.0 hits/line )

16 files in total.
165 relevant lines, 0 lines covered and 165 lines missed. ( 0.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
app/policies/activity_policy.rb 0.00 % 7 5 0 5 0.00 100.00 % 0 0 0
app/policies/application_policy.rb 0.00 % 21 15 0 15 0.00 100.00 % 0 0 0
app/policies/configurable_policy.rb 0.00 % 11 8 0 8 0.00 100.00 % 0 0 0
app/policies/district_policy.rb 0.00 % 23 17 0 17 0.00 100.00 % 0 0 0
app/policies/profile_policy.rb 0.00 % 9 8 0 8 0.00 100.00 % 0 0 0
app/policies/representative_policy.rb 0.00 % 23 17 0 17 0.00 100.00 % 0 0 0
app/policies/school_policy.rb 0.00 % 23 17 0 17 0.00 100.00 % 0 0 0
app/policies/spots/customer_policy.rb 0.00 % 5 5 0 5 0.00 100.00 % 0 0 0
app/policies/spots/image_properties_picture_policy.rb 0.00 % 9 6 0 6 0.00 100.00 % 0 0 0
app/policies/spots/reports/photographed_policy.rb 0.00 % 7 6 0 6 0.00 100.00 % 0 0 0
app/policies/spots/reports/upcoming_appointments_policy.rb 0.00 % 7 6 0 6 0.00 100.00 % 0 0 0
app/policies/spots/reports/yearbook_poses_policy.rb 0.00 % 7 6 0 6 0.00 100.00 % 0 0 0
app/policies/spots/reports_policy.rb 0.00 % 3 3 0 3 0.00 100.00 % 0 0 0
app/policies/spots_policy.rb 0.00 % 2 2 0 2 0.00 100.00 % 0 0 0
app/policies/upload_policy.rb 0.00 % 28 21 0 21 0.00 100.00 % 0 0 0
app/policies/user_policy.rb 0.00 % 32 23 0 23 0.00 100.00 % 0 0 0

Uploaders ( 0.0% covered at 0.0 hits/line )

3 files in total.
6 relevant lines, 0 lines covered and 6 lines missed. ( 0.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
app/uploaders/data_uploader.rb 0.00 % 4 2 0 2 0.00 100.00 % 0 0 0
app/uploaders/square_image_uploader.rb 0.00 % 4 2 0 2 0.00 100.00 % 0 0 0
app/uploaders/wide_image_uploader.rb 0.00 % 4 2 0 2 0.00 100.00 % 0 0 0

app/controllers/activities_controller.rb

0.0% lines covered

100.0% branches covered

16 relevant lines. 0 lines covered and 16 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class ActivitiesController < ApplicationController
  2. before_action :set_resources
  3. def index
  4. authorize! with: ActivityPolicy
  5. @pagy, @activities = pagy(@resources)
  6. end
  7. private
  8. def set_resources
  9. @resources =
  10. if params.key?(:user_id)
  11. PublicActivity::Activity.where(owner_type: 'User', owner_id: params[:user_id])
  12. else
  13. PublicActivity::Activity.all
  14. end
  15. end
  16. end

app/controllers/application_controller.rb

0.0% lines covered

100.0% branches covered

27 relevant lines. 0 lines covered and 27 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. # TODO: Only accept json. Only respond as json. Force.
  3. class ApplicationController < ActionController::API
  4. include ActionController::MimeResponds
  5. include ActionPolicy::Controller
  6. include Pagy::Backend
  7. include PublicActivity::StoreController
  8. before_action :set_paper_trail_whodunnit
  9. before_action :authenticate_user!
  10. before_action :configure_permitted_parameters, if: :devise_controller?
  11. authorize :user, through: :current_user
  12. impersonates :user
  13. respond_to :json
  14. rescue_from ActionController::UnknownFormat do |ex|
  15. response.headers['x-exception-message'] = ex.message unless Rails.env.production?
  16. head :bad_request
  17. end
  18. private
  19. def configure_permitted_parameters
  20. devise_parameter_sanitizer.permit(:sign_up,
  21. keys: [
  22. :first_name, :last_name, :terms_of_service, :access_code,
  23. user_schools_attributes: %i[school_id]
  24. ])
  25. end
  26. def user_for_paper_trail
  27. user_signed_in? ? true_user.id : 'Public'
  28. end
  29. end

app/controllers/configurables_controller.rb

0.0% lines covered

100.0% branches covered

26 relevant lines. 0 lines covered and 26 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class ConfigurablesController < ApplicationController
  3. before_action :set_keys
  4. def show
  5. authorize!
  6. end
  7. def update
  8. authorize!
  9. failures = Configurable
  10. .keys.filter_map do |key|
  11. params.key?(key) &&
  12. Configurable.find_or_create_by(name: key)
  13. end.reject do |configurable|
  14. configurable.value = params[configurable.name]
  15. configurable.save
  16. end
  17. if failures.empty?
  18. render :show
  19. else
  20. render json: failures.flat_map(&:errors), status: :unprocessable_entity
  21. end
  22. end
  23. private
  24. def set_keys
  25. @keys = Configurable.keys
  26. end
  27. end

app/controllers/districts_controller.rb

0.0% lines covered

100.0% branches covered

49 relevant lines. 0 lines covered and 49 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class DistrictsController < ApplicationController
  3. before_action :set_resources, only: %i[index]
  4. before_action :set_district, only: %i[show update destroy]
  5. def index
  6. authorize!
  7. @pagy, @districts = pagy(@resources)
  8. end
  9. def create
  10. @district = District.new(district_params)
  11. authorize!
  12. if @district.save
  13. render :show, status: :created
  14. else
  15. render json: @district.errors, status: :unprocessable_entity
  16. end
  17. end
  18. def show
  19. authorize!
  20. end
  21. def update
  22. authorize!
  23. if @district.update(district_params)
  24. render :show, status: :ok
  25. else
  26. render json: @district.errors, status: :unprocessable_entity
  27. end
  28. end
  29. def destroy
  30. authorize!
  31. @district.public_send(@district.discarded? ? :undiscard : :discard)
  32. end
  33. private
  34. def discarded_scope
  35. return :all unless params.key?(:a)
  36. params[:a] == '1' ? :kept : :discarded
  37. end
  38. def district_params
  39. params.fetch(:district, {})
  40. .permit(:name, :school_ids)
  41. end
  42. def set_resources
  43. @resources = District.public_send(discarded_scope)
  44. @resources = @resources.search(params[:q]) if params[:q].present?
  45. end
  46. def set_district
  47. @district =
  48. District.friendly.find(params[:id])
  49. end
  50. end

app/controllers/profiles_controller.rb

0.0% lines covered

100.0% branches covered

18 relevant lines. 0 lines covered and 18 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class ProfilesController < ApplicationController
  3. def show
  4. authorize! current_user, with: ProfilePolicy
  5. end
  6. def update
  7. authorize! current_user, with: ProfilePolicy
  8. if current_user.update(profile_params)
  9. render :show, status: :ok
  10. else
  11. render json: current_user.errors, status: :unprocessable_entity
  12. end
  13. end
  14. private
  15. def profile_params
  16. params.fetch(:profile, {})
  17. .permit(:email, :password, :password_confirmation)
  18. end
  19. end

app/controllers/representatives_controller.rb

0.0% lines covered

100.0% branches covered

51 relevant lines. 0 lines covered and 51 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class RepresentativesController < ApplicationController
  3. before_action :set_resources, only: %i[index]
  4. before_action :set_representative, only: %i[show update destroy]
  5. def index
  6. authorize!
  7. @pagy, @representatives = pagy(@resources)
  8. end
  9. def create
  10. @representative = Representative.new(representative_params)
  11. authorize!
  12. if @representative.save
  13. render :show, status: :created
  14. else
  15. render json: @representative.errors, status: :unprocessable_entity
  16. end
  17. end
  18. def show
  19. authorize!
  20. end
  21. def update
  22. authorize!
  23. if @representative.update(representative_params)
  24. render :show, status: :ok
  25. else
  26. render json: @representative.errors, status: :unprocessable_entity
  27. end
  28. end
  29. def destroy
  30. authorize!
  31. @representative.public_send(@representative.discarded? ? :undiscard : :discard)
  32. end
  33. private
  34. # TODO: https://actionpolicy.evilmartians.io/#/scoping
  35. def discarded_scope
  36. return :all unless params.key?(:a)
  37. params[:a] == '1' ? :kept : :discarded
  38. end
  39. def representative_params
  40. params.fetch(:representative, {}).permit(:title,
  41. :first_name, :last_name, :email, :phone_number, :extra_text,
  42. :image, image_data: [:id, :storage, metadata: %i[blurhash filename height mime_type size width]],
  43. school_representatives_attributes: %i[id school_id _destroy])
  44. end
  45. def set_resources
  46. @resources = Representative.public_send(discarded_scope)
  47. @resources = @resources.search(params[:q]) if params[:q].present?
  48. end
  49. def set_representative
  50. @representative =
  51. Representative.friendly.find(params[:id])
  52. end
  53. end

app/controllers/schools_controller.rb

0.0% lines covered

100.0% branches covered

53 relevant lines. 0 lines covered and 53 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class SchoolsController < ApplicationController
  3. before_action :set_resources, only: %i[index]
  4. before_action :set_school, only: %i[show update destroy]
  5. def index
  6. authorize!
  7. @pagy, @schools = pagy(@resources)
  8. end
  9. def create
  10. @school = School.new(school_params)
  11. authorize!
  12. if @school.save
  13. render :show, status: :created
  14. else
  15. render json: @school.errors, status: :unprocessable_entity
  16. end
  17. end
  18. def show
  19. authorize!
  20. end
  21. def update
  22. authorize!
  23. if @school.update(school_params)
  24. render :show, status: :ok
  25. else
  26. render json: @school.errors, status: :unprocessable_entity
  27. end
  28. end
  29. def destroy
  30. authorize!
  31. @school.public_send(@school.discarded? ? :undiscard : :discard)
  32. end
  33. private
  34. # TODO: https://actionpolicy.evilmartians.io/#/scoping
  35. def discarded_scope
  36. return :all unless params.key?(:a)
  37. params[:a] == '1' ? :kept : :discarded
  38. end
  39. def school_params
  40. params.fetch(:school, {}).permit(:name,
  41. :district_id, :spots_id, :download_service_url, :banner, :logo,
  42. banner_data: [:id, :storage, metadata: %i[blurhash filename height mime_type size width]],
  43. logo_data: [:id, :storage, metadata: %i[blurhash filename height mime_type size width]],
  44. school_representatives_attributes: %i[id representative_id _destroy],
  45. user_schools_attributes: %i[id user_id _destroy])
  46. end
  47. def set_resources
  48. @resources = School.includes(:district, :spots).public_send(discarded_scope)
  49. @resources = @resources.search(params[:q]) if params[:q].present?
  50. end
  51. def set_school
  52. @school =
  53. School.friendly.find(params[:id])
  54. end
  55. end

app/controllers/searches_controller.rb

0.0% lines covered

100.0% branches covered

6 relevant lines. 0 lines covered and 6 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class SearchesController < ApplicationController
  2. def show
  3. @results =
  4. SPOTS::Customer.where(['CustomerID LIKE ?', "%#{params[:q]}%"])
  5. end
  6. end

app/controllers/spots/customers_controller.rb

0.0% lines covered

100.0% branches covered

7 relevant lines. 0 lines covered and 7 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class SPOTS::CustomersController < SPOTSController
  3. def show
  4. @customer =
  5. SPOTS::Customer.find(params[:id])
  6. authorize! @customer
  7. end
  8. end

app/controllers/spots/images_controller.rb

0.0% lines covered

100.0% branches covered

16 relevant lines. 0 lines covered and 16 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class SPOTS::ImagesController < SPOTSController
  3. before_action :set_image
  4. def show
  5. authorize! @image
  6. send_data @image.PictureData, disposition: :attachment,
  7. filename: @image.filename
  8. end
  9. private
  10. def set_image
  11. @image =
  12. SPOTS::ImagePropertiesPicture.find(image_params)
  13. end
  14. def image_params
  15. [params[:customer_id], params[:session_id], params[:id]]
  16. end
  17. end

app/controllers/spots/reports/photographed_controller.rb

0.0% lines covered

100.0% branches covered

7 relevant lines. 0 lines covered and 7 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class SPOTS::Reports::PhotographedController < SPOTS::ReportsController
  3. def index
  4. authorize! with: SPOTS::Reports::PhotographedPolicy
  5. @pagy, @customers =
  6. pagy(@school.spots.customers.public_send(params.fetch(:a, '1') == '1' ? :photographed : :not_photographed))
  7. end
  8. end

app/controllers/spots/reports/upcoming_appointments_controller.rb

0.0% lines covered

100.0% branches covered

6 relevant lines. 0 lines covered and 6 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class SPOTS::Reports::UpcomingAppointmentsController < SPOTS::ReportsController
  3. def index
  4. authorize! with: SPOTS::Reports::UpcomingAppointmentsPolicy
  5. @pagy, @appointments = pagy_array(@school.spots.upcoming_appointments)
  6. end
  7. end

app/controllers/spots/reports/yearbook_poses_controller.rb

0.0% lines covered

100.0% branches covered

15 relevant lines. 0 lines covered and 15 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class SPOTS::Reports::YearbookPosesController < SPOTS::ReportsController
  3. before_action :ensure_pose_chosen_report_enabled
  4. def index
  5. authorize! with: SPOTS::Reports::YearbookPosesPolicy
  6. @pagy, @customers =
  7. pagy(@school.spots.customers.public_send(params.fetch(:a, '1') == '1' ? :with_yearbook_pose : :without_yearbook_pose))
  8. end
  9. private
  10. def ensure_pose_chosen_report_enabled
  11. return if Configurable.pose_chosen_report_enabled?
  12. render json: {
  13. error: 'Report unavailable'
  14. }, status: :forbidden
  15. end
  16. end

app/controllers/spots/reports_controller.rb

0.0% lines covered

100.0% branches covered

15 relevant lines. 0 lines covered and 15 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class SPOTS::ReportsController < SPOTSController
  3. before_action :set_school
  4. before_action :require_connected_spots_school
  5. authorize :school, through: :set_school
  6. private
  7. def require_connected_spots_school
  8. return if @school.spots.present?
  9. # TODO: Create constant
  10. render json: {
  11. error: 'Portrait Data Unavailable'
  12. }, status: :bad_request
  13. end
  14. def set_school
  15. @school = School.find(params[:school_id])
  16. end
  17. end

app/controllers/spots_controller.rb

0.0% lines covered

100.0% branches covered

26 relevant lines. 0 lines covered and 26 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class SPOTSController < ApplicationController
  3. # TODO: db switching for "simple feature"
  4. # around_action :connect_to_desired_spots_database
  5. rescue_from TinyTds::Error do |ex|
  6. response.headers['x-exception-message'] = ex.message unless Rails.env.production?
  7. # TODO: Create constant
  8. render json: {
  9. error: 'Portrait Data Connection Error'
  10. }, status: :service_unavailable
  11. end
  12. private
  13. # NOTE: Use only for reference. Use session or other param to define index
  14. # used for new/original_database. Allows for per request calls. Investigate
  15. # potential latency issues. Investigate, if happening, impact of new connections.
  16. def connect_to_desired_spots_database
  17. # rubocop:disable Style/BracesAroundHashParameters
  18. SPOTSRecord.establish_connection({
  19. adapter: :sqlserver,
  20. database: Configurable.spots_db_name,
  21. host: new_database,
  22. username: Configurable.spots_db_user,
  23. password: Configurable.spots_db_pass
  24. })
  25. # rubocop:enable Style/BracesAroundHashParameters
  26. yield
  27. # rubocop:disable Style/BracesAroundHashParameters
  28. SPOTSRecord.establish_connection({
  29. adapter: :sqlserver,
  30. database: Configurable.spots_db_name,
  31. host: original_database,
  32. username: Configurable.spots_db_user,
  33. password: Configurable.spots_db_pass
  34. })
  35. # rubocop:enable Style/BracesAroundHashParameters
  36. end
  37. end

app/controllers/uploads_controller.rb

0.0% lines covered

100.0% branches covered

73 relevant lines. 0 lines covered and 73 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class UploadsController < ApplicationController
  3. before_action :ensure_single_source, only: %i[index create]
  4. before_action :set_source, only: %i[index create]
  5. before_action :set_resources, only: %i[index]
  6. before_action :set_upload, only: %i[show update destroy]
  7. authorize :source, through: :set_source
  8. def index
  9. authorize!
  10. @pagy, @uploads = pagy(@resources)
  11. end
  12. def create
  13. authorize!
  14. @upload =
  15. @source.uploads.new(upload_params.merge(created_ip: request.remote_ip, updated_ip: request.remote_ip, user_id: current_user.id))
  16. if @upload.save
  17. render :show, status: :created
  18. else
  19. render json: @upload.errors, status: :unprocessable_entity
  20. end
  21. end
  22. def show
  23. authorize!
  24. end
  25. def update
  26. authorize!
  27. if @upload.update(upload_params.merge(updated_ip: request.remote_ip, user_id: current_user.id))
  28. render :show, status: :ok
  29. else
  30. render json: @upload.errors, status: :unprocessable_entity
  31. end
  32. end
  33. def destroy
  34. authorize!
  35. @upload.discarded_ip = request.remote_ip
  36. @upload.public_send(@upload.discarded? ? :undiscard : :discard)
  37. end
  38. private
  39. # TODO: https://actionpolicy.evilmartians.io/#/scoping
  40. def discarded_scope
  41. return :all unless params.key?(:a)
  42. params[:a] == '1' ? :kept : :discarded
  43. end
  44. def ensure_single_source
  45. return unless params.slice(:user_id, :school_id).keys.size > 1
  46. head :bad_request
  47. end
  48. def set_resources
  49. @resources =
  50. if @source == Upload
  51. @source
  52. else
  53. @source.uploads
  54. end.includes(:user, :school).public_send(discarded_scope)
  55. @resources = @resources.search(params[:q]) if params[:q].present?
  56. end
  57. def set_source
  58. @source =
  59. if params.key?(:school_id)
  60. School.friendly.find(params[:school_id])
  61. elsif params.key?(:user_id)
  62. User.friendly.find(params[:user_id])
  63. else
  64. Upload
  65. end
  66. end
  67. def set_upload
  68. @upload =
  69. Upload.find(params[:id])
  70. end
  71. def upload_params
  72. params.fetch(:upload, {}).permit(:note,
  73. data_data: [:id, :storage, metadata: %i[blurhash filename height mime_type size width]])
  74. end
  75. end

app/controllers/users_controller.rb

0.0% lines covered

100.0% branches covered

65 relevant lines. 0 lines covered and 65 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class UsersController < ApplicationController
  3. before_action :set_resources, only: %i[index]
  4. before_action :set_user, only: %i[show update destroy]
  5. def index
  6. authorize!
  7. @pagy, @users = pagy(@resources)
  8. end
  9. def create
  10. @user = User.new(user_params)
  11. authorize!
  12. @user.access_code = Configurable.sign_up_access_code
  13. @user.activated_at = Time.current
  14. if @user.save
  15. render :show, status: :created
  16. else
  17. render json: @user.errors, status: :unprocessable_entity
  18. end
  19. end
  20. def show
  21. authorize!
  22. end
  23. def update
  24. authorize!
  25. if @user.update(user_params)
  26. render :show, status: :ok
  27. else
  28. render json: @user.errors, status: :unprocessable_entity
  29. end
  30. end
  31. def destroy
  32. authorize!
  33. @user.public_send(@user.discarded? ? :undiscard : :discard)
  34. end
  35. private
  36. # TODO: https://actionpolicy.evilmartians.io/#/scoping
  37. def discarded_scope
  38. return :all unless params.key?(:a)
  39. if params[:a] == '1'
  40. :kept
  41. else
  42. params[:a] == '-1' ? :pending : :discarded
  43. end
  44. end
  45. def user_params
  46. permitted_params = [
  47. :first_name, :last_name, :email, :password, :password_confirmation,
  48. :avatar, avatar_data: [:id, :storage, metadata: %i[blurhash filename height mime_type size width]]
  49. ]
  50. if (params.dig(:user, :type) == 'Administrator' && current_user.is_a?(Administrator)) ||
  51. (params.dig(:user, :type) == 'StudioUser' && (current_user.is_a?(Administrator) || current_user.is_a?(StudioUser)))
  52. permitted_params += %w[type]
  53. end
  54. if (params.dig(:user, :type) || @user&.type) == 'SchoolUser'
  55. permitted_params += [user_schools_attributes: %i[id school_id _destroy]]
  56. end
  57. params.fetch(:user, {}).permit(permitted_params)
  58. end
  59. def set_resources
  60. @resources = User.where.not(id: current_user.id).public_send(discarded_scope)
  61. @resources = @resources.search(params[:q]) if params[:q].present?
  62. end
  63. def set_user
  64. @user =
  65. User.friendly.find(params[:id])
  66. end
  67. end

app/decorators/application_decorator.rb

0.0% lines covered

100.0% branches covered

2 relevant lines. 0 lines covered and 2 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class ApplicationDecorator < Draper::Decorator
  3. # Define methods for all decorated objects.
  4. # Helpers are accessed through `helpers` (aka `h`). For example:
  5. #
  6. # def percent_amount
  7. # h.number_to_percentage object.amount, precision: 2
  8. # end
  9. end

app/jobs/application_job.rb

0.0% lines covered

100.0% branches covered

4 relevant lines. 0 lines covered and 4 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class ApplicationJob < ActiveJob::Base
  3. retry_on Exception, attempts: :unlimited
  4. # Most jobs are safe to ignore if the underlying records are no longer available
  5. discard_on ActiveJob::DeserializationError
  6. end

app/jobs/shrine_destroy_job.rb

0.0% lines covered

100.0% branches covered

8 relevant lines. 0 lines covered and 8 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class ShrineDestroyJob < ApplicationJob
  2. queue_as :attachment_processing
  3. def perform(attacher_class, data)
  4. attacher_class = Object.const_get(attacher_class)
  5. attacher = attacher_class.from_data(data)
  6. attacher.destroy
  7. end
  8. end

app/jobs/shrine_promote_job.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 ShrinePromoteJob < ApplicationJob
  2. queue_as :attachment_processing
  3. def perform(attacher_class, record_class, record_id, name, file_data)
  4. attacher_class = Object.const_get(attacher_class)
  5. record = Object.const_get(record_class).find(record_id) # if using Active Record
  6. attacher = attacher_class.retrieve(model: record, name: name, file: file_data)
  7. attacher.atomic_promote
  8. rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
  9. # attachment has changed or record has been deleted, nothing to do
  10. end
  11. end

app/mailers/application_mailer.rb

0.0% lines covered

100.0% branches covered

4 relevant lines. 0 lines covered and 4 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class ApplicationMailer < ActionMailer::Base
  3. default from: Configurable.email_customer_service
  4. layout 'mailer'
  5. end

app/models/administrator.rb

0.0% lines covered

100.0% branches covered

6 relevant lines. 0 lines covered and 6 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class Administrator < User
  2. attr_readonly :activated_at
  3. before_create :set_activated_at
  4. tracked owner: -> (controller, _) { controller&.true_user },
  5. params: TRACKED_PARAMETERS
  6. end

app/models/application_record.rb

0.0% lines covered

100.0% branches covered

4 relevant lines. 0 lines covered and 4 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class ApplicationRecord < ActiveRecord::Base
  3. primary_abstract_class
  4. self.implicit_order_column = :created_at
  5. end

app/models/district.rb

0.0% lines covered

100.0% branches covered

45 relevant lines. 0 lines covered and 45 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class District < ApplicationRecord
  3. include Discard::Model
  4. include FriendlyId
  5. include PgSearch::Model
  6. include PublicActivity::Model
  7. has_many :schools, inverse_of: :district,
  8. dependent: :destroy
  9. validates :name,
  10. presence: true,
  11. uniqueness: { case_sensitive: false, scope: %i[discarded_at] }
  12. after_validation :move_friendly_id_error_to_name
  13. after_discard { schools.kept.update_all(discarded_at: discarded_at) }
  14. friendly_id :name, use: %i[slugged]
  15. has_paper_trail on: %i[create destroy update]
  16. pg_search_scope :search,
  17. against: {
  18. name: 'A'
  19. },
  20. using: {
  21. tsearch: {
  22. prefix: true,
  23. negation: true,
  24. highlight: true,
  25. dictionary: :english,
  26. tsvector_column: :name_tsearch_tsvector
  27. },
  28. dmetaphone: {
  29. tsvector_column: :name_dmetaphone_tsvector
  30. }
  31. }
  32. tracked owner: -> (controller, _) { controller&.true_user },
  33. params: {
  34. name: :name,
  35. school_count: -> (_, model) { model.schools.size },
  36. discarded: :discarded?,
  37. discarded_at: :discarded_at
  38. }
  39. private
  40. def move_friendly_id_error_to_name
  41. errors.add :name, *errors.delete(:friendly_id) if errors[:friendly_id].present?
  42. end
  43. def should_generate_new_friendly_id?
  44. name_changed? || super
  45. end
  46. end

app/models/representative.rb

0.0% lines covered

100.0% branches covered

67 relevant lines. 0 lines covered and 67 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class Representative < ApplicationRecord
  3. include Discard::Model
  4. include FriendlyId
  5. include PgSearch::Model
  6. include PublicActivity::Model
  7. include SquareImageUploader::Attachment(:avatar)
  8. has_many :school_representatives, inverse_of: :representative,
  9. dependent: :destroy
  10. has_many :schools,
  11. through: :school_representatives
  12. validates :first_name,
  13. presence: true
  14. validates :last_name,
  15. presence: true
  16. after_validation :move_friendly_id_error_to_name
  17. after_discard { school_representatives.destroy_all }
  18. accepts_nested_attributes_for :school_representatives,
  19. allow_destroy: true, reject_if: :all_blank
  20. friendly_id :full_name, use: %i[slugged]
  21. has_paper_trail on: %i[create destroy update]
  22. pg_search_scope :search,
  23. against: {
  24. first_name: 'B',
  25. last_name: 'A'
  26. },
  27. using: {
  28. tsearch: {
  29. prefix: true,
  30. negation: true,
  31. highlight: true,
  32. dictionary: :english,
  33. tsvector_column:
  34. %i[last_name_tsearch_tsvector first_name_tsearch_tsvector]
  35. },
  36. dmetaphone: {
  37. tsvector_column:
  38. %i[last_name_dmetaphone_tsvector first_name_dmetaphone_tsvector]
  39. }
  40. }
  41. tracked owner: -> (controller, _) { controller&.true_user },
  42. params: {
  43. title: :title,
  44. first_name: :first_name,
  45. last_name: :last_name,
  46. email: :email,
  47. phone_number: :phone_number,
  48. extra_text: :extra_text,
  49. avatar_changed: :avatar_data_changed?,
  50. schools_count: -> (_, model) { model.schools.size },
  51. discarded: :discarded?,
  52. discarded_at: :discarded_at
  53. }
  54. def full_name(with_title: false)
  55. f_n = "#{first_name} #{last_name}"
  56. return f_n unless with_title
  57. "#{title} #{f_n}"
  58. end
  59. private
  60. def move_friendly_id_error_to_name
  61. return unless errors[:friendly_id].present?
  62. errors.delete(:friendly_id)
  63. errors.add :base, 'Full name combination is reserved'
  64. end
  65. def should_generate_new_friendly_id?
  66. first_name_changed? || last_name_changed? || super
  67. end
  68. end

app/models/school.rb

0.0% lines covered

100.0% branches covered

83 relevant lines. 0 lines covered and 83 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class School < ApplicationRecord
  2. include Discard::Model
  3. include FriendlyId
  4. include PgSearch::Model
  5. include PublicActivity::Model
  6. include SquareImageUploader::Attachment(:logo)
  7. include WideImageUploader::Attachment(:banner)
  8. scope :with_spots, -> { where.not(spots_id: nil) }
  9. belongs_to :district, inverse_of: :schools,
  10. touch: true
  11. belongs_to :spots, class_name: 'SPOTS::School',
  12. inverse_of: :portal, optional: true
  13. has_many :customers,
  14. through: :spots, disable_joins: true
  15. has_many :school_representatives, inverse_of: :school,
  16. dependent: :destroy
  17. has_many :representatives,
  18. through: :school_representatives
  19. has_many :uploads, inverse_of: :school,
  20. dependent: :nullify
  21. has_many :user_schools, inverse_of: :school,
  22. dependent: :destroy
  23. has_many :users,
  24. through: :user_schools
  25. validates :name,
  26. presence: true,
  27. uniqueness: { case_sensitive: false, scope: %i[discarded_at] }
  28. # REVIEW: Can this be replaced by validates length on scope
  29. validate :selected_district_is_active
  30. after_validation :move_friendly_id_error_to_name
  31. after_validation :move_district_error_to_district_id
  32. after_discard { school_representatives.destroy_all }
  33. after_discard { user_schools.destroy_all }
  34. accepts_nested_attributes_for :school_representatives,
  35. allow_destroy: true, reject_if: :all_blank
  36. accepts_nested_attributes_for :user_schools,
  37. allow_destroy: true, reject_if: :all_blank
  38. delegate :name,
  39. to: :district, prefix: true
  40. delegate :statistics,
  41. to: :spots, prefix: true, allow_nil: true
  42. friendly_id :name, use: %i[slugged]
  43. has_paper_trail on: %i[create destroy update]
  44. pg_search_scope :search,
  45. against: {
  46. name: 'A'
  47. },
  48. using: {
  49. tsearch: {
  50. prefix: true,
  51. negation: true,
  52. highlight: true,
  53. dictionary: :english,
  54. tsvector_column: :name_tsearch_tsvector
  55. },
  56. dmetaphone: {
  57. tsvector_column: :name_dmetaphone_tsvector
  58. }
  59. }
  60. tracked owner: -> (controller, _) { controller&.true_user },
  61. params: {
  62. name: :last_name,
  63. spots_id: :spots_id,
  64. district_name: :district_name,
  65. logo_changed: :logo_data_changed?,
  66. banner_changed: :banner_data_changed?,
  67. discarded: :discarded?,
  68. discarded_at: :discarded_at
  69. }
  70. private
  71. def move_district_error_to_district_id
  72. errors.add :district_id, *errors.delete(:district) if errors[:district].present?
  73. end
  74. def move_friendly_id_error_to_name
  75. errors.add :name, *errors.delete(:friendly_id) if errors[:friendly_id].present?
  76. end
  77. def selected_district_is_active
  78. return unless district
  79. errors.add :district_id, 'must be active' if district_changed? && district.discarded?
  80. end
  81. def should_generate_new_friendly_id?
  82. name_changed? || super
  83. end
  84. end

app/models/school_representative.rb

0.0% lines covered

100.0% branches covered

22 relevant lines. 0 lines covered and 22 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class SchoolRepresentative < ApplicationRecord
  2. self.primary_key = %i[school_id representative_id]
  3. belongs_to :school, inverse_of: :school_representatives,
  4. touch: true
  5. belongs_to :representative, inverse_of: :school_representatives,
  6. touch: true
  7. validates :school_id,
  8. uniqueness: { scope: %i[representative_id] }
  9. validates :representative_id,
  10. uniqueness: { scope: %i[school_id] }
  11. validate :only_active_associated_allowed,
  12. on: %i[create update]
  13. delegate :discarded?, :kept?,
  14. to: :representative, prefix: true
  15. delegate :discarded?, :kept?,
  16. to: :school, prefix: true
  17. private
  18. def only_active_associated_allowed
  19. errors.add :school_id, 'must be active' if school_discarded?
  20. errors.add :representative_id, 'must be active' if representative_discarded?
  21. end
  22. end

app/models/school_user.rb

0.0% lines covered

100.0% branches covered

26 relevant lines. 0 lines covered and 26 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class SchoolUser < User
  2. attr_accessor :terms_of_service
  3. attr_accessor :access_code
  4. has_many :user_schools, inverse_of: :user,
  5. foreign_key: :user_id, dependent: :destroy
  6. has_many :schools,
  7. through: :user_schools
  8. validates :access_code,
  9. comparison: {
  10. equal_to: Configurable.sign_up_access_code,
  11. message: 'does not match, please try again.'
  12. }, on: %i[create]
  13. validates :terms_of_service,
  14. acceptance: true, on: %i[create]
  15. validates :user_schools,
  16. length: {
  17. minimum: 1,
  18. message: 'must belong to at least one school'
  19. }
  20. accepts_nested_attributes_for :user_schools, allow_destroy: true, reject_if: :all_blank
  21. tracked owner: -> (controller, _) { controller&.true_user },
  22. params: TRACKED_PARAMETERS.merge(schools_count: -> (_, model) { model.schools.size })
  23. def active_for_authentication?
  24. super && schools.any?
  25. end
  26. end

app/models/spots.rb

0.0% lines covered

100.0% branches covered

2 relevant lines. 0 lines covered and 2 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. module SPOTS
  3. end

app/models/spots/customer.rb

0.0% lines covered

100.0% branches covered

57 relevant lines. 0 lines covered and 57 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. module SPOTS
  3. class Customer < SPOTSRecord
  4. # REVIEW: if this works as intended
  5. OUTER_JOIN_POSE_ORDERS_SQL = <<~SQL
  6. LEFT OUTER JOIN [PoseOrders]
  7. ON [PoseOrders].[CustomerID] = [Customers].[CustomerID]
  8. SQL
  9. scope :photographed, -> { joins(:recent_session).includes(:recent_session).where(Photographed: true) }
  10. scope :not_photographed, -> { where(Photographed: [false, nil, '']) }
  11. scope :with_poses, -> { photographed.joins(:pose_orders).distinct }
  12. scope :without_poses, lambda {
  13. photographed.joins(OUTER_JOIN_POSE_ORDERS_SQL)
  14. .where('[PoseOrders].[CustomerID] IS NULL')
  15. .distinct
  16. } # REVIEW: if this works as intended
  17. scope :with_yearbook_pose, lambda {
  18. includes(:yearbook_poses)
  19. .with_poses.merge(SPOTS::PoseOrder.yearbook)
  20. }
  21. scope :without_yearbook_pose, lambda {
  22. photographed
  23. .where.not(CustomerID: SPOTS::PoseOrder.yearbook.select(:CustomerID))
  24. .distinct
  25. }
  26. self.primary_key = 'CustomerID'
  27. belongs_to :school,
  28. class_name: 'SPOTS::School',
  29. foreign_key: 'SchoolID', inverse_of: :customers
  30. has_many :images,
  31. through: :pose_orders, inverse_of: :customer
  32. # REVIEW: through??
  33. has_many :yearbook_poses, -> { SPOTS::PoseOrder.yearbook },
  34. class_name: 'SPOTS::PoseOrder', foreign_key: 'CustomerID',
  35. inverse_of: :customer, dependent: :restrict_with_exception
  36. has_many :pose_orders,
  37. class_name: 'SPOTS::PoseOrder', foreign_key: 'CustomerID',
  38. inverse_of: :customer, dependent: :restrict_with_exception
  39. has_one :recent_session, -> { SPOTS::Session.most_recent },
  40. class_name: 'SPOTS::Session', foreign_key: 'CustomerID',
  41. inverse_of: :customer, dependent: :restrict_with_exception
  42. has_many :sessions,
  43. class_name: 'SPOTS::Session', foreign_key: 'CustomerID',
  44. inverse_of: :customer, dependent: :restrict_with_exception
  45. validates :FirstName, :LastName, :StudentID, :EMail,
  46. :Address, :City, :State, :ZipCode, :Phone,
  47. presence: true
  48. before_destroy -> { Rails::VERSION::MAJOR >= 5 ? throw(:abort) : false },
  49. prepend: true
  50. def full_name
  51. "#{self.FirstName} #{self.LastName}"
  52. end
  53. # rubocop:disable Naming/MethodName
  54. def Photographed
  55. super || false
  56. end
  57. # rubocop:enable Naming/MethodName
  58. # TODO: presenter
  59. # REVIEW: should move to SPOTS::PoseOrder.ybpn?
  60. def yearbook_pose_numbers
  61. yearbook_poses.map(&:pose_number)
  62. end
  63. end
  64. end

app/models/spots/image_properties_picture.rb

0.0% lines covered

100.0% branches covered

35 relevant lines. 0 lines covered and 35 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. module SPOTS
  3. class ImagePropertiesPicture < SPOTSRecord
  4. self.table_name = 'ImagePropertiesPicture'
  5. self.primary_keys = :CustomerID, :SessionNumber, :Pose
  6. belongs_to :customer,
  7. foreign_key: :CustomerID, inverse_of: :images
  8. belongs_to :pose_order,
  9. foreign_key: %i[CustomerID Pose SessionNumber], inverse_of: :image
  10. has_one :school, through: :customer
  11. def height(max = nil)
  12. return dimensions[1] if max.blank?
  13. height < width && (max * ratio) || max
  14. end
  15. def ratio
  16. height > width ? width / height : height / width
  17. end
  18. def to_io
  19. return @io if defined? @io
  20. @io = StringIO.new
  21. @io.set_encoding Encoding::BINARY
  22. @io << self.PictureData
  23. end
  24. def width(max = nil)
  25. return dimensions[0] if max.blank?
  26. height > width && (max * ratio) || max
  27. end
  28. def filename
  29. "#{self.CustomerID}_#{self.SessionNumber}_#{self.Pose}.jpg"
  30. end
  31. private
  32. def dimensions
  33. @dimensions ||= FastImage.size(to_io).map { |dim| BigDecimal(dim) }
  34. end
  35. end
  36. end

app/models/spots/pose_order.rb

0.0% lines covered

100.0% branches covered

18 relevant lines. 0 lines covered and 18 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. module SPOTS
  3. class PoseOrder < SPOTSRecord
  4. scope :yearbook, -> { where(YB: true).includes(:image) }
  5. scope :not_yearbook, -> { where.not(YB: true) }
  6. self.table_name = 'PoseOrders'
  7. self.primary_keys = :CustomerID, :PoseNo, :SessionNumber, :OrderNumber
  8. # REVIEW: order matters?
  9. has_one :image,
  10. class_name: 'SPOTS::ImagePropertiesPicture',
  11. foreign_key: %i[CustomerID Pose SessionNumber],
  12. inverse_of: :pose_order, dependent: :restrict_with_exception
  13. belongs_to :customer,
  14. class_name: 'SPOTS::Customer',
  15. foreign_key: 'CustomerID', inverse_of: :pose_orders
  16. # TODO: presenter
  17. def pose_number
  18. "#{self.SessionNumber}#{self.PoseNo}"
  19. end
  20. end
  21. end

app/models/spots/school.rb

0.0% lines covered

100.0% branches covered

42 relevant lines. 0 lines covered and 42 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. module SPOTS
  3. class School < SPOTSRecord
  4. self.primary_key = 'SchoolID'
  5. has_one :portal,
  6. class_name: '::School', foreign_key: :spots_id,
  7. inverse_of: :spots, dependent: :restrict_with_exception
  8. has_many :customers,
  9. class_name: 'SPOTS::Customer', foreign_key: 'SchoolID',
  10. inverse_of: :school, dependent: :restrict_with_exception
  11. def statistics
  12. return @statistics if defined?(@statistics)
  13. data = customers.group(:Photographed).size
  14. appointment_count = upcoming_appointments.count
  15. @statistics = { photographed: data.delete(true), upcoming: appointment_count }
  16. @statistics[:not_photographed] = data.values.sum - appointment_count
  17. @statistics
  18. end
  19. def upcoming_appointments
  20. sql = <<~SQL
  21. SELECT DISTINCT
  22. UPPER(dbo.Timetrade_Data.TimetradeLastName) AS LastName,
  23. UPPER(dbo.Timetrade_Data.TimetradeFirstName) AS FirstName,
  24. Format(dbo.Timetrade_Data.ScheduleStartTime, 'MM-dd-yyyy hh:mm tt') AS AppointmentAt,
  25. dbo.Timetrade_Data.StudentIDNumber AS StudentID,
  26. dbo.Timetrade_Data.CustomerID,
  27. dbo.Timetrade_Data.ConfirmationNumber AS ConfirmationNumber,
  28. dbo.SchoolID_SchoolIDAlpha.SchoolID AS SPOTSSchoolNumber
  29. FROM
  30. dbo.Timetrade_Data INNER JOIN dbo.SchoolID_SchoolIDAlpha ON dbo.Timetrade_Data.SchoolID = dbo.SchoolID_SchoolIDAlpha.SchoolIDAlpha
  31. WHERE
  32. ((dbo.Timetrade_Data.EventName = 'appointmentBooked') OR (dbo.Timetrade_Data.EventName = 'appointmentChanged')) AND
  33. (dbo.Timetrade_Data.CancelledAt IS NULL) AND
  34. (dbo.Timetrade_Data.ScheduleStartTime > GETDATE()) AND
  35. dbo.SchoolID_SchoolIDAlpha.SchoolID = @0
  36. ORDER BY
  37. LastName, FirstName
  38. SQL
  39. SPOTS::Customer.find_by_sql(sql,
  40. [ActiveRecord::Relation::QueryAttribute.new(nil, self.SchoolID.to_s, ActiveRecord::Type::Integer.new)])
  41. end
  42. end
  43. end

app/models/spots/session.rb

0.0% lines covered

100.0% branches covered

9 relevant lines. 0 lines covered and 9 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. module SPOTS
  3. class Session < SPOTSRecord
  4. scope :most_recent, -> { order(DateTime: :desc).limit(1) }
  5. self.primary_key = 'SessionID'
  6. belongs_to :customer,
  7. class_name: 'SPOTS::Customer',
  8. foreign_key: 'CustomerID', inverse_of: :sessions
  9. end
  10. end

app/models/spots_record.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. # frozen_string_literal: true
  2. class SPOTSRecord < ActiveRecord::Base
  3. self.abstract_class = true
  4. # rubocop:disable Style/BracesAroundHashParameters
  5. establish_connection({
  6. adapter: :sqlserver,
  7. database: Configurable.spots_db_name,
  8. host: Configurable.spots_db_host,
  9. username: Configurable.spots_db_user,
  10. password: Configurable.spots_db_pass
  11. })
  12. # rubocop:enable Style/BracesAroundHashParameters
  13. end

app/models/studio_user.rb

0.0% lines covered

100.0% branches covered

6 relevant lines. 0 lines covered and 6 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class StudioUser < User
  2. attr_readonly :activated_at
  3. before_create :set_activated_at
  4. tracked owner: -> (controller, _) { controller&.true_user },
  5. params: TRACKED_PARAMETERS
  6. end

app/models/upload.rb

0.0% lines covered

100.0% branches covered

33 relevant lines. 0 lines covered and 33 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class Upload < ApplicationRecord
  3. include DataUploader::Attachment(:data)
  4. include Discard::Model
  5. include PgSearch::Model
  6. include PublicActivity::Model
  7. belongs_to :user, touch: true
  8. belongs_to :school, touch: true
  9. validates :data,
  10. presence: true
  11. has_paper_trail on: %i[create destroy update]
  12. pg_search_scope :search,
  13. against: {
  14. note: 'A'
  15. },
  16. using: {
  17. tsearch: {
  18. prefix: true,
  19. negation: true,
  20. highlight: true,
  21. dictionary: :english,
  22. tsvector_column: :note_tsearch_tsvector
  23. },
  24. dmetaphone: {
  25. tsvector_column: :note_dmetaphone_tsvector
  26. }
  27. }
  28. tracked owner: -> (controller, _) { controller&.true_user },
  29. params: {
  30. note: :note,
  31. discarded: :discarded?,
  32. discarded_at: :discarded_at
  33. }
  34. end

app/models/user.rb

0.0% lines covered

100.0% branches covered

61 relevant lines. 0 lines covered and 61 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class User < ApplicationRecord
  3. include Discard::Model
  4. include FriendlyId
  5. include PgSearch::Model
  6. include PublicActivity::Model
  7. include SquareImageUploader::Attachment(:avatar)
  8. TRACKED_PARAMETERS = {
  9. first_name: :first_name,
  10. last_name: :last_name,
  11. activated: :activated?,
  12. discarded: :discarded?,
  13. discarded_at: :discarded_at,
  14. password_changed: :encrypted_password_changed?
  15. }.freeze
  16. scope :pending, -> { kept.where(activated_at: nil) }
  17. has_many :uploads, inverse_of: :user,
  18. dependent: :nullify
  19. validates :first_name,
  20. presence: true
  21. validates :last_name,
  22. presence: true
  23. validates :password_confirmation,
  24. presence: true, if: :encrypted_password_changed?
  25. devise :database_authenticatable, :registerable,
  26. :recoverable, :rememberable, :trackable,
  27. :validatable, :zxcvbnable
  28. friendly_id :full_name, use: %i[slugged]
  29. has_paper_trail on: %i[create destroy update]
  30. pg_search_scope :search,
  31. against: {
  32. first_name: 'B',
  33. last_name: 'A'
  34. },
  35. using: {
  36. tsearch: {
  37. prefix: true,
  38. negation: true,
  39. highlight: true,
  40. dictionary: :english,
  41. tsvector_column:
  42. %i[last_name_tsearch_tsvector first_name_tsearch_tsvector]
  43. },
  44. dmetaphone: {
  45. tsvector_column:
  46. %i[last_name_dmetaphone_tsvector first_name_dmetaphone_tsvector]
  47. }
  48. }
  49. def active_for_authentication?
  50. super && !discarded? && activated?
  51. end
  52. def activated?
  53. activated_at.present?
  54. end
  55. def full_name
  56. "#{first_name} #{last_name}"
  57. end
  58. private
  59. def set_activated_at
  60. self.activated_at = Time.current
  61. end
  62. end

app/models/user_school.rb

0.0% lines covered

100.0% branches covered

22 relevant lines. 0 lines covered and 22 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class UserSchool < ApplicationRecord
  2. self.primary_key = %i[user_id school_id]
  3. belongs_to :user, inverse_of: :user_schools,
  4. class_name: 'SchoolUser', touch: true
  5. belongs_to :school, inverse_of: :user_schools,
  6. touch: true
  7. validates :user_id,
  8. uniqueness: { scope: %i[school_id] }
  9. validates :school_id,
  10. uniqueness: { scope: %i[user_id] }
  11. validate :only_active_associated_allowed,
  12. on: %i[create update]
  13. delegate :activated?, :discarded?, :kept?,
  14. to: :user, prefix: true
  15. delegate :discarded?, :kept?,
  16. to: :school, prefix: true
  17. private
  18. def only_active_associated_allowed
  19. errors.add :user_id, 'must be active' if user_discarded?
  20. errors.add :school_id, 'must be active' if school_discarded?
  21. end
  22. end

app/policies/activity_policy.rb

0.0% lines covered

100.0% branches covered

5 relevant lines. 0 lines covered and 5 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class ActivityPolicy < ApplicationPolicy
  3. def index?
  4. administrative_user?
  5. end
  6. end

app/policies/application_policy.rb

0.0% lines covered

100.0% branches covered

15 relevant lines. 0 lines covered and 15 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class ApplicationPolicy < ActionPolicy::Base
  3. private
  4. def administrative_user?
  5. studio_user? || administrator?
  6. end
  7. def administrator?
  8. user.is_a?(Administrator)
  9. end
  10. def owner?
  11. record.user_id == user.id
  12. end
  13. def studio_user?
  14. user.is_a?(StudioUser)
  15. end
  16. end

app/policies/configurable_policy.rb

0.0% lines covered

100.0% branches covered

8 relevant lines. 0 lines covered and 8 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class ConfigurablePolicy < ApplicationPolicy
  3. def show?
  4. administrator?
  5. end
  6. def update?
  7. administrator?
  8. end
  9. end

app/policies/district_policy.rb

0.0% lines covered

100.0% branches covered

17 relevant lines. 0 lines covered and 17 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class DistrictPolicy < ApplicationPolicy
  3. def index?
  4. administrative_user?
  5. end
  6. def create?
  7. administrative_user?
  8. end
  9. def show?
  10. administrative_user?
  11. end
  12. def update?
  13. administrative_user?
  14. end
  15. def destroy?
  16. administrative_user?
  17. end
  18. end

app/policies/profile_policy.rb

0.0% lines covered

100.0% branches covered

8 relevant lines. 0 lines covered and 8 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class ProfilePolicy < ApplicationPolicy
  2. def show?
  3. record.id == user.id
  4. end
  5. def update?
  6. record.id == user.id
  7. end
  8. end

app/policies/representative_policy.rb

0.0% lines covered

100.0% branches covered

17 relevant lines. 0 lines covered and 17 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class RepresentativePolicy < ApplicationPolicy
  3. def index?
  4. administrative_user?
  5. end
  6. def create?
  7. administrative_user?
  8. end
  9. def show?
  10. administrative_user?
  11. end
  12. def update?
  13. administrative_user?
  14. end
  15. def destroy?
  16. administrative_user?
  17. end
  18. end

app/policies/school_policy.rb

0.0% lines covered

100.0% branches covered

17 relevant lines. 0 lines covered and 17 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class SchoolPolicy < ApplicationPolicy
  3. def index?
  4. administrative_user?
  5. end
  6. def create?
  7. administrative_user?
  8. end
  9. def show?
  10. administrative_user?
  11. end
  12. def update?
  13. administrative_user?
  14. end
  15. def destroy?
  16. administrative_user?
  17. end
  18. end

app/policies/spots/customer_policy.rb

0.0% lines covered

100.0% branches covered

5 relevant lines. 0 lines covered and 5 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class SPOTS::CustomerPolicy < SPOTSPolicy
  2. def show?
  3. administrative_user?
  4. end
  5. end

app/policies/spots/image_properties_picture_policy.rb

0.0% lines covered

100.0% branches covered

6 relevant lines. 0 lines covered and 6 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class SPOTS::ImagePropertiesPicturePolicy < SPOTSPolicy
  3. def show?
  4. allow! if administrative_user?
  5. user.schools.exists?(spots_id: record.school.SchoolID)
  6. end
  7. end

app/policies/spots/reports/photographed_policy.rb

0.0% lines covered

100.0% branches covered

6 relevant lines. 0 lines covered and 6 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class SPOTS::Reports::PhotographedPolicy < SPOTS::ReportsPolicy
  2. def index?
  3. allow! if administrative_user?
  4. user.is_a?(SchoolUser) && user.schools.exists?(school.id)
  5. end
  6. end

app/policies/spots/reports/upcoming_appointments_policy.rb

0.0% lines covered

100.0% branches covered

6 relevant lines. 0 lines covered and 6 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class SPOTS::Reports::UpcomingAppointmentsPolicy < ApplicationPolicy
  2. def index?
  3. allow! if administrative_user?
  4. user.is_a?(SchoolUser) && user.schools.exists?(school.id)
  5. end
  6. end

app/policies/spots/reports/yearbook_poses_policy.rb

0.0% lines covered

100.0% branches covered

6 relevant lines. 0 lines covered and 6 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class SPOTS::Reports::YearbookPosesPolicy < SPOTS::ReportsPolicy
  2. def index?
  3. allow! if administrative_user?
  4. user.is_a?(SchoolUser) && user.schools.exists?(school.id)
  5. end
  6. end

app/policies/spots/reports_policy.rb

0.0% lines covered

100.0% branches covered

3 relevant lines. 0 lines covered and 3 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class SPOTS::ReportsPolicy < SPOTSPolicy
  2. authorize :school
  3. end

app/policies/spots_policy.rb

0.0% lines covered

100.0% branches covered

2 relevant lines. 0 lines covered and 2 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class SPOTSPolicy < ApplicationPolicy
  2. end

app/policies/upload_policy.rb

0.0% lines covered

100.0% branches covered

21 relevant lines. 0 lines covered and 21 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. class UploadPolicy < ApplicationPolicy
  2. authorize :source
  3. def index?
  4. allow! if administrative_user?
  5. allow! if source.is_a?(School) && user.schools.exists?(source.id)
  6. source.is_a?(SchoolUser) && source.id == user.id
  7. end
  8. def create?
  9. allow! if administrative_user?
  10. source.is_a?(School) && user.schools.exists?(source.id)
  11. end
  12. def show?
  13. administrative_user? || owner?
  14. end
  15. def update?
  16. administrative_user? || owner?
  17. end
  18. def destroy?
  19. administrative_user? || owner?
  20. end
  21. end

app/policies/user_policy.rb

0.0% lines covered

100.0% branches covered

23 relevant lines. 0 lines covered and 23 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class UserPolicy < ApplicationPolicy
  3. def index?
  4. administrative_user?
  5. end
  6. def create?
  7. allow! if administrator?
  8. deny! unless administrative_user?
  9. !record.is_a?(Administrator)
  10. end
  11. def show?
  12. administrative_user? || record.id == user.id
  13. end
  14. def update?
  15. allow! if administrator? || record.id == user.id
  16. deny! unless administrative_user?
  17. !record.is_a?(Administrator)
  18. end
  19. def destroy?
  20. allow! if administrator?
  21. deny! unless administrative_user?
  22. !record.is_a?(Administrator)
  23. end
  24. end

app/uploaders/data_uploader.rb

0.0% lines covered

100.0% branches covered

2 relevant lines. 0 lines covered and 2 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class DataUploader < Shrine
  3. end

app/uploaders/square_image_uploader.rb

0.0% lines covered

100.0% branches covered

2 relevant lines. 0 lines covered and 2 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class SquareImageUploader < Shrine
  3. end

app/uploaders/wide_image_uploader.rb

0.0% lines covered

100.0% branches covered

2 relevant lines. 0 lines covered and 2 lines missed.
0 total branches, 0 branches covered and 0 branches missed.
    
  1. # frozen_string_literal: true
  2. class WideImageUploader < Shrine
  3. end

lib/maily_hooks.rb

100.0% lines covered

100.0% branches covered

0 relevant lines. 0 lines covered and 0 lines missed.
0 total branches, 0 branches covered and 0 branches missed.