← Back to Upcase

Keeping Track of a Attribute for a Period of Time Each Year for Many Users


(Kevin Lozandier) #1

##Keeping Track of a Attribute for a Period of Time Each Year

I’m trying to make a Rails 4 app for a scholarship organization, but having a hard time with a few things involving the volunteer hours needed by the scholarship recipients years.

There are two types of scholars: undergraduate scholars and graduate scholars.

Things I see as model candiates I’ve put in bold, while things I see as attributes are italicized

  • Each scholar (what I’m calling my user model for this example) has many volunteer hours each scholar_year

  • Each scholar year has a beginning date, ending date, mandatory hours for undergraduate scholars, and mandatory hours for graduate-level scholars.

  • The scholar who completes their volunteer hours the fastest needs to be tracked (the prize/thing isn’t necessary to be recorded on the table, but I sort of want to know how to do this as well)

I’m trying to conceptualize doing the following but having a hard time planning out keeping track of the progress the two types of scholars will have towards completing their volunteer hours given the fact they can get hours for volunteering specific events or attending specific events, but I’ll temporarily abstract that for a moment. ;

##How I’ve attempted to Solve the Problem

Based on this information, I figured I’ll have to use a has_many :through relationship, with a table called scholar_year_assignments. Considering I have to track what volunteerable ‘thing’ and what year each scholar has completed it in order use the Ruby on Rails :calculate API

###scholar_year_assignments table

|id(int)| scholar_id (int)| scholar_year_id (int) | completed_volunteer_hours (decimal) | successfully_completed_hours_on (datetime)

With table in mine, I did the following

###Simpliified Scholar & Scholar_year Tables (Rails 4)


#NOTE: More than likely abstracting scholars out to two, UndergraduateScholarProfile, GraduateScholarProfile due to the many types of users I have to deal with and they don't exactly have the same data that'll lead to a LOT of `nil` tables.

class Scholar < ActiveRecord::Base 

  has_many :scholar_years, through: :scholar_year_assignments, dependent: :destroy 
  has_one :volunteer_history 
  #belongs to :scholarable, polymorphic: true may be needed here when abstracted

  #My attempt of implementing eligibility without considering scholar type 
  def eligible_this_year(year = Time.now.year -1)  
    if ScholarYear.where(year: year).nil? || ScholarYear.where(year: year).hours > volunteer_hours
      false 
    else 
      true 
  end

  def volunteer_hours 
    #Have no clue or now braindead: Doing something like  VolunteerHistory.where(user_id: self).calculate(:sum, 'volunteer_hours') or something similar to the association table seems very wrong. 
  end
 
end

class VolunteerHistory < ActiveRecord::Base 
  belongs_to :Scholar
  belongs_to :Scholar_year 
  belongs_to :volunteerable, polymorphic: true #I'm guessing this is correct, probably wrong
end

class ScholarYear < ActiveRecord::Base
  has_many :scholars, through: :scholar_year_assignments, dependent: :destroy
end

# I want to able to the following assuming the scholar is scoped from user

@scholar.elgibile_this_year #true or false if the scholar met the volunteer hours this past year


##What I’m confused about with my attempt of understanding this scenario.

I’m confused on how I’m going to populate the completed_id hours part if I’m correct on approaching this problem with a volunteer history record. I’m assuming a before_save or other before_action filters, but unsure on which ones to utilize t.

In addition, I’m having hard time figuring out whether it makes sense to think about using :delegate methods to help me simplify solving this scenario.


(Jonathan twaddell) #2

Hmm… a lot of this is personal preference but the idea of year seems like an attribute of an item and not a separate table. Isn’t VolunteerHistory a calculated value? I think you might be making this more complex than it needs to be.


(Kevin Lozandier) #3

I may be; though I’m sort of confused by year attribute comment. Everything is going through :scholar_years; year, which is propably a bad arbitrary variable name, I’ve only used to refer to one class method which wasn’t entirely implemented.

When it comes to actual years a scholar was or wasn’t a scholar throughout their academic career it would be retrieveable simply by

 @scholar.scholar_years 

Since the scholar class has a has_many :scholar_years association stated. My problem is implementing the volunteeer hours and comparing it to the required scholar hours each year will have different, along with keeping track of it within the year.

Once I have the model association correct with that sorted out it would be simple to do things such as

  @scholar.volunteer_hours
  @scholar.volunteer_hour_progress_for_scholar_year(2013) 
  @scholar.completed_hours_for_year(2012) 
  @scholar.elgible_this_year? #ignoring the fact they could have graduated which is easy 

My problem is sorting out the volunteer_hours logic in the middle of the has_many :through association between scholars and each scholar year.


(Jonathan twaddell) #4

Hmm… why not just add a total_hours on scholar_year_assignments? In some place, you are going to need the per-scholar discrete value. Based upon how it is currently setup, this would seem to be the most logical place.


(Kevin Lozandier) #5

I see; I’ll try that out, but I think I have a gap on getting the values from the join table. I’m sure you would need to take advantage of the calculate() from the Rails API, but having trouble on understanding how to get that from a JOIN table column that represents the relationships between two other models.

Perhaps someone from Thoughtbots such as @halogenandtoast can help me here…


(Chad Pytel) #6

We discussed this at length on the chat room, Kevin is going to continue to work on the direction we started on.

@kevinlozandier, as you may progress, it would be great if you could update this thread for the benefit of everyone.


(Kevin Lozandier) #7

Just to follow up, I am still working on this. Will resume working on resolving this tomorrow and Thursday.

I deal with INNER JOIN and LEFT JOIN operations with my SQL statements all the time in plain PHP (MYSQLi), but didn’t put much thought it shouldn’t be any different of considering them when necessary with the use of ActiveRecord throughout a Ruby on Rails app.

You really made me have a lightbulb moment when you mentioned I probably wasn’t considering JOIN commands in the context of this problem when I should have.

I also wasn’t aware I should use state machine logic with what I want accomplished with this app.