Skip to content
This repository has been archived by the owner on Jul 24, 2020. It is now read-only.

[1288] Refactor scopes into Query Objects #1355

Merged
merged 1 commit into from
Jan 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/controllers/categories_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def deactivate
redirect_to @category
elsif params[:deactivation_confirmed]
@category.equipment_models.each do |em|
Reservation.for_eq_model(em).finalized.each do |r|
Reservation.for_eq_model(em.id).finalized.each do |r|
r.archive(current_user, 'The category was deactivated.')
.save(validate: false)
end
Expand Down
13 changes: 8 additions & 5 deletions app/controllers/equipment_models_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ def index
end

def show # rubocop:disable AbcSize, MethodLength
relevant_reservations = Reservation.active.for_eq_model(@equipment_model)
relevant_reservations =
Reservation.for_eq_model(@equipment_model.id).active
@associated_equipment_models =
@equipment_model.associated_equipment_models.sample(6)

Expand Down Expand Up @@ -59,9 +60,11 @@ def show # rubocop:disable AbcSize, MethodLength
@restricted = @equipment_model.model_restricted?(cart.reserver_id)

# For pending reservations table
@pending = relevant_reservations.reserved_in_date_range(Time.zone.today,
Time.zone.today +
8.days).reserved
@pending =
relevant_reservations.reserved_in_date_range(Time.zone.today,
Time.zone.today + 8.days)
# Future reservations using Query object
@future = @pending.future
end

def new
Expand Down Expand Up @@ -124,7 +127,7 @@ def deactivate
flash[:notice] = 'Deactivation cancelled.'
redirect_to @equipment_model
elsif params[:deactivation_confirmed]
Reservation.for_eq_model(@equipment_model).finalized.each do |r|
Reservation.for_eq_model(@equipment_model.id).finalized.each do |r|
r.archive(current_user, 'The equipment model was deactivated.')
.save(validate: false)
end
Expand Down
1 change: 0 additions & 1 deletion app/controllers/reservations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ def index
end

set_counts(source, time)

@reservations_set = time.send(@filter)
end

Expand Down
2 changes: 1 addition & 1 deletion app/decorators/category_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def make_deactivate_btn
# find reservations for models in the category in the next week
res = 0
object.equipment_models.each do |em|
res += Reservation.for_eq_model(em).finalized
res += Reservation.for_eq_model(em.id).finalized
.reserved_in_date_range(Time.zone.today - 1.day,
Time.zone.today + 7.days)
.count
Expand Down
2 changes: 1 addition & 1 deletion app/decorators/equipment_model_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class EquipmentModelDecorator < ApplicationDecorator
def make_deactivate_btn
unless object.deleted_at
# find reservations in the next week
res = Reservation.for_eq_model(object).finalized
res = Reservation.for_eq_model(object.id).finalized
.reserved_in_date_range(Time.zone.today - 1.day,
Time.zone.today + 7.days)
.count
Expand Down
2 changes: 1 addition & 1 deletion app/models/cart_validations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def check_max_cat

def check_availability(model = EquipmentModel.find(items.keys.first),
quantity = 1,
source_res = Reservation.for_eq_model(self)
source_res = Reservation.for_eq_model(id)
.active.all)

# checks that the model is available for the given quantity given the
Expand Down
6 changes: 3 additions & 3 deletions app/models/equipment_model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def num_available_from_source(start_date, due_date, source_reservations)
def num_available(start_date, due_date)
# for if you just want the number available, 1 query to get
# relevant reservations
relevant_reservations = Reservation.for_eq_model(self).finalized
relevant_reservations = Reservation.for_eq_model(id).finalized
.reserved_in_date_range(start_date, due_date)
.all
num_available_from_source(start_date, due_date, relevant_reservations)
Expand All @@ -207,14 +207,14 @@ def model_restricted?(reserver_id)
# Returns the number of overdue objects for a given model,
# as long as they have been checked out.
def number_overdue
Reservation.overdue.for_eq_model(self).size
Reservation.overdue.for_eq_model(id).size
end

def available_count(date)
# get the total number of items of this kind then subtract the total
# quantity currently reserved, checked-out, and overdue
total = equipment_items.active.count
reserved = Reservation.reserved_on_date(date).for_eq_model(self).count
reserved = Reservation.reserved_on_date(date).for_eq_model(id).count
total - reserved - number_overdue
end

Expand Down
57 changes: 55 additions & 2 deletions app/models/reservation.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# rubocop:disable ClassLength
# rubocop:disable Metrics/ClassLength, Rails/ScopeArgs
class Reservation < ActiveRecord::Base
include Linkable
include ReservationValidations
include ReservationScopes

belongs_to :equipment_model
belongs_to :equipment_item
Expand Down Expand Up @@ -37,6 +36,60 @@ class Reservation < ActiveRecord::Base
fined: (1 << 4), missed_email_sent: (1 << 5),
expired: (1 << 6) }

## Scopes ##
# general scopes
default_scope { order('start_date, due_date, reserver_id') }
scope :for_eq_model, ->(em_id) { where(equipment_model_id: em_id) }
scope :for_reserver, ->(reserver_id) { where(reserver_id: reserver_id) }

# flag scopes
scope :flagged, ->(flag) { where('flags & ? > 0', FLAGS[flag]) }
scope :not_flagged, ->(flag) { where('flags & ? = 0', FLAGS[flag]) }

# basic status scopes
scope :active, lambda {
where(status: Reservation.statuses.values_at(*%w(reserved checked_out)))
}
scope :finalized, lambda {
where.not(status: Reservation.statuses.values_at(*%w(denied requested)))
}
scope :active_or_requested, lambda {
where(status: Reservation.statuses.values_at(
*%w(requested reserved checked_out)))
}

# overdue / request scopes
scope :overdue, ->() { where(overdue: true).checked_out }
scope :returned_on_time, ->() { where(overdue: false).returned }
scope :returned_overdue, ->() { where(overdue: true).returned }
scope :approved_requests, ->() { flagged(:request).finalized }
scope :missed_requests, ->() { past_date(:start_date).requested }

# generalized date scopes (pass parameter as either a string or a symbol)
scope :past_date, ->(param) { where("#{param} < ?", Time.zone.today) }
scope :today_date, ->(param) { where(param.to_sym => Time.zone.today) }

# basic date scopes
scope :checked_out_today, ->() { today_date(:checked_out) }
scope :checked_out_previous, ->() { past_date(:checked_out) }
scope :due_today, ->() { today_date(:due_date) }

# more complex / task-specific scopes
scope :checkoutable, Reservations::CheckoutableQuery
scope :ends_on_days, Reservations::EndsOnDaysQuery
scope :future, Reservations::FutureQuery
scope :notes_unsent, Reservations::NotesUnsentQuery
scope :reserved_in_date_range, Reservations::ReservedInDateRangeQuery
scope :reserved_on_date, Reservations::ReservedOnDateQuery
scope :starts_on_days, Reservations::StartsOnDaysQuery
scope :upcoming, Reservations::UpcomingQuery

# join Scopes
scope :with_categories, lambda {
joins(:equipment_model)
.select('reservations.*, equipment_models.category_id as category_id')
}

## Class methods ##

def self.completed_procedures(procedures)
Expand Down
88 changes: 0 additions & 88 deletions app/models/reservation_scopes.rb

This file was deleted.

13 changes: 13 additions & 0 deletions app/queries/query_base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class QueryBase
class << self
delegate :call, to: :new
end

def initialize
fail NotImplementedError
end

def call
fail NotImplementedError
end
end
7 changes: 7 additions & 0 deletions app/queries/reservations/checkoutable_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Reservations
class CheckoutableQuery < Reservations::ReservationsQueryBase
def call
@relation.where('start_date <= ?', Time.zone.today).reserved
end
end
end
7 changes: 7 additions & 0 deletions app/queries/reservations/ends_on_days_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Reservations
class EndsOnDaysQuery < Reservations::ReservationsQueryBase
def call(start_date, end_date)
@relation.where(due_date: start_date..end_date)
end
end
end
7 changes: 7 additions & 0 deletions app/queries/reservations/future_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Reservations
class FutureQuery < Reservations::ReservationsQueryBase
def call
@relation.where('start_date > ?', Time.zone.today.to_time).reserved
end
end
end
7 changes: 7 additions & 0 deletions app/queries/reservations/notes_unsent_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Reservations
class NotesUnsentQuery < Reservations::ReservationsQueryBase
def call
@relation.where(notes_unsent: true).where.not(notes: nil)
end
end
end
7 changes: 7 additions & 0 deletions app/queries/reservations/reservations_query_base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Reservations
class ReservationsQueryBase < QueryBase
def initialize(relation = Reservation.all)
@relation = relation
end
end
end
9 changes: 9 additions & 0 deletions app/queries/reservations/reserved_in_date_range_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Reservations
class ReservedInDateRangeQuery < Reservations::ReservationsQueryBase
def call(start_date, end_date)
@relation
.where('start_date <= ? and due_date >= ?', end_date, start_date)
.reserved
end
end
end
7 changes: 7 additions & 0 deletions app/queries/reservations/reserved_on_date_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Reservations
class ReservedOnDateQuery < Reservations::ReservationsQueryBase
def call(date)
@relation.where('start_date <= ? and due_date >= ?', date, date).active
end
end
end
7 changes: 7 additions & 0 deletions app/queries/reservations/starts_on_days_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Reservations
class StartsOnDaysQuery < Reservations::ReservationsQueryBase
def call(start_date, end_date)
@relation.where(start_date: start_date..end_date)
end
end
end
7 changes: 7 additions & 0 deletions app/queries/reservations/upcoming_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Reservations
class UpcomingQuery < Reservations::ReservationsQueryBase
def call
@relation.unscoped.today_date(:start_date).reserved.order('reserver_id')
end
end
end
2 changes: 1 addition & 1 deletion app/views/equipment_models/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@
<%= @pending.checkoutable.count %>
</div>
<div class="col-md-3">
<%= @pending.future.count %>
<%= @future.count %>
</div>
</div>
<% if @pending.length > 0 %>
Expand Down
2 changes: 1 addition & 1 deletion lib/tasks/email_checkin_reminder.rake
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ desc 'Send email reminder about upcoming check-ins'
task email_checkin_reminder: :environment do
if AppConfig.first.upcoming_checkin_email_active?
# get all reservations that end today and aren't already checked in
upcoming_reservations = Reservation.due_soon
upcoming_reservations = Reservation.due_today
Rails.logger.info "Found #{upcoming_reservations.size} reservations due "\
'for check-in. Sending reminder emails...'
upcoming_reservations.each do |upcoming_reservation|
Expand Down
4 changes: 2 additions & 2 deletions lib/tasks/email_notes_to_admins.rake
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ desc 'Send email to admins on reservations with notes'
task email_notes_to_admins: :environment do
# gets all reservations with notes and sends an email to the admin of the
# application, to alert them.
notes_reservations_out = Reservation.has_notes.checked_out.notes_unsent
notes_reservations_in = Reservation.has_notes.checked_in.notes_unsent
notes_reservations_out = Reservation.checked_out.notes_unsent
notes_reservations_in = Reservation.returned.notes_unsent
Rails.logger.info "Found #{notes_reservations_out.size} reservations "\
"checked out with notes and #{notes_reservations_in.size} "\
'reservations checked in with notes.'
Expand Down
Loading