You’re not receiving notifications from this thread.
How do I calculate a computed value in a model when showing or indexing over that model in its controller?
I'm new to Rails but not new to programming or webdev.
I have a
Student model that uses a service object to pull data from Google Cloud Firestore for its
level attribute, an integer. I have hooked the service object's method into an
update_level method on the
Student model using the
before_save ActiveRecord callback. This method checks the last time the student's level was updated from a column in the database and if it's been more than 10 minutes it will fire the method to check Cloud Firestore. This works fine when creating or updating these objects, but one of the reasons for this Rails app is to present up-to-date information to teachers about their students. (I promise this isn't creepy learning analytics, it's for a bespoke game for a special curriculum.)
What is the best, most Rails-like way to hook this functionality into the
show controller methods, such that if I'm showing a
Student record or indexing over a list of Students, fire the same
update_level method (or one like it) for each student. Now, my mind immediately starts thinking about some kind of job queue or ActionCable solution to this, but that seems far too complicated. I'm trying to minimize unnecessary calls to Firestore, but I want to make sure the data I'm presenting is relatively up to date.
What is the Rails way of doing this?
If it helps, here's the gist of the code fire off to update a Student's level.
FirestoreGetter is my service object that wraps Google's Cloud Firestore gem with some formatting niceties.
def firestore_getter @firestore_getter ||= FirestoreGetter.new end def update_level if self.last_level_checked.nil? || self.last_level_checked < 10.minutes.ago # FIXME: abstract this to some setting retrieved_level = firestore_getter.retrieve_student_level username self.level = retrieved_level self.last_level_checked = DateTime.now end end
After sleeping on it, I believe the best way (and the way that requires the fewest queries to Cloud Firestore) is to just download the whole Firestore DB and update from that object every 10 or so minutes with a scheduler of some kind.
I believe the answer to my original question is something like: do it in the controller's index and show methods, but it will be bad and inefficient and slow and violate RESTful practices and smells bad.