Skip to main content

Performing calculations using scopes

General • Asked by John Munyi

hello , hopefully this isn’t too ambitious but i am hoping there is a way to do simple summation using defined scopes example is i have these scopes :

      scope :present, -> { where(present: true) }
      scope :absent, -> { where(present: false) }
      scope :emergency_leave, -> { where(present: false) && where(reason: "Emergency Leave") }
      scope :sick_leave, -> { where(present: false) && where(reason: "Sick Leave") }
      scope :planned_leave, -> { where(present: false) && where(reason: "Planned Leave") }

is it possible to define a method within the same class that can take something like
def x
absent.count + emergency_leave.count ?
end

how would you re-use the scopes to do calculations ?


Hey John,

You can absolutely make a method that adds the counts like that. You wouldn't be able to turn that method into a scope, because it's not returning a relation, but rather a number.

Also I'd suggest combining your where clauses for cleanliness:

# Convert
where(present: false) && where(reason: "Emergency Leave")
# to
where(present: false, reason: "Emergency Leave")

super awesome thanks


Hi Chris,

The above scopes are in my attendance.rb but i would wish the method to be in attendance_sheet.rb , rem

  class AttendanceSheet < ActiveRecord::Base
    has_many :attendances, dependent: :destroy
    accepts_nested_attributes_for :attendances, reject_if: :all_blank, allow_destroy: true
    belongs_to :team
 end

is it even possible to call that method from outside attendance_sheet while the scopes live in attendance ?

cheers


You can access the scopes through the attendances association if that's what you're asking. It should look like this:

# First we need a sheet
@attendance_sheet = AttendanceSheet.first

# Give me all the present attendances for that sheet
@attendance_sheet.attendances.present

That is fine, I am do so currently , my question was where will the custom method be ? same class as scope or elsewhere

  def ps
       (attendances.planned_leave.count + b.attendances.maternity_leave.count)  / b.attendances.count.to_f * 100
  end

 #@attendance_sheet.attendaces.ps doesnt work 

I am assuming is in the attendance.rb .... then how do i call it form attendance_sheet view


Ah, so those methods should actually be class methods!

def self.ps
  (attendances.planned_leave.count + b.attendances.maternity_leave.count)  / b.attendances.count.to_f * 100
end

Note the self. there in the name. That makes it a class method which makes it work like a scope would.

This lets you do this:

@attendance_sheet.attendaces.ps

The reason being is that when you access a has_many association, it returns a Relation object that functions more like the model class instead of an individual record.


got yah !

the if its a class method in attendance.rb the it should read like this ?

  def self.planned_shrinkage
       (planned_leave.count + maternity_leave.count + paternal_leave.count)  / present.count.to_f * 100
   end

    no attendaces.planned_leave. count but planned leave .count 

Yeah, if it's in the Attendance model where the scopes are, you can just use those methods directly without having "attendances" first so just planned_leave.

If you do it in the AttendanceSheet model, you'll need to preface the scopes with the attendances association attendances.planned_leave.


Awesome works like magic .. and when referring to the model its-self i can just use the keyword self !!!

Chris You Rock \m/ :)



Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 27,623+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.