Reputation: 978
I have two models, User and TrainingSession:
class User < ActiveRecord::Base
has_many :training_sessions
end
class TrainingSession < ActiveRecord::Base
belongs_to :user
end
Each User has a certain number of points based on the sum of the durations of their accumulated training_sessions (in TrainingSession model):
class TrainingSession
def points
sum(:duration) / 6
end
Currently, after a user creates a new training_session, I am updating the points attribute in the User model as follows (from TrainingSession controller):
# POST /training_sessions
# POST /training_sessions.json
def create
@user = User.find_by_id(session[:user_id])
@training_session = @user.training_sessions.new(params[:training_session])
@points = @user.training_sessions.points
@user.update_attribute(:points, @points)
...
The problem is that each time a training_session is created, it doesn't include the points that were just accrued by the user from the most recently created training_session. For example, if a user has 160 points, then they go for a 60 minute run, they will have gained 10 points to reach 170 points. But after creating that 60 minute run training_session, the User model updates it to 160 points. So it is always one step behind, so to speak. I tried using an after_save callback on the TrainingSession model, like so:
class TrainingSession < ActiveRecord::Base
after_save :update_points
private
def update_points
count = @user.training_sessions.sum(:duration)
if count >= 1
points = count / 6
end
@user.update_attribute(:points, points)
end
but then I get this error when trying to create a new training_session:
undefined method `training_sessions' for nil:NilClass
So, my question is, how do I keep up to date the :points attribute on my user model with the inclusion of the most recently created training_session?
Upvotes: 2
Views: 1458
Reputation: 43298
@user
is undefined in your model. That's why you get the error.
A training session belongs to a user, so in your model you can get the user via self.user
or simply user
. This code should work:
def update_points
count = self.user.training_sessions.sum(:duration)
points = count / 6 if count >= 1
self.user.update_attribute(:points, points)
end
Upvotes: 3