All threads / Performing calculations using scopes

Ask A Question

Notifications

You’re not receiving notifications from this thread.

Performing calculations using scopes

John Munyi asked in General

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")

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/ :)

Join the discussion

Want to stay up-to-date with Ruby on Rails?

Join 35,095+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    logo Created with Sketch.

    Ruby on Rails tutorials, guides, and screencasts for web developers learning Ruby, Rails, Javascript, Turbolinks, Stimulus.js, Vue.js, and more. Icons by Icons8

    © 2020 GoRails, LLC. All rights reserved.