Basically a user joins a challenge. Each challenge has a goal like 300000 steps in 30 days. I want keep a track on the user of his daily activities for the next 30 days.
Is this the best design and also is this the right show method in the challenges controller ?
The show method is called when the current_user clicks on a particular challenge.
def show
@challenge = Challenge.find(params[:id])
@user_activity = UserActivity.find_by(user:current_user,challenge:@challenge)
end
User
has_many :user_activities
has_many :challenges, through: :user_activities
class Challenge < ActiveRecord::Base
has_many :user_activities
has_many :user, through: :user_activities
class UserActivity < ActiveRecord::Base
belongs_to :challenge
belongs_to :user
I would try to keep as much logic out of the controller as possible. In that vein I would do something like:
class ChallengesController < ApplicationController
...
def show
@challenge = Challenge.find(params[:id])
@user_activity = @challenge.activity_for(current_user)
end
...
end
User < ActiveRecord::Base
has_many :user_activities
has_many :challenges, through: :user_activities
...
end
class Challenge < ActiveRecord::Base
has_many :user_activities
has_many :user, through: :user_activities
def activity_for(user)
self.user_activities.where(user: user)
end
...
end
class UserActivity < ActiveRecord::Base
belongs_to :challenge
belongs_to :user
...
end
The activity_for method will call self (in this case, @challenge), then get the user_activities for that challenge where the user is current_user.
Putting the activity_for on the user vs challenge class is a matter of preference. I put it on the challenge class so I could call it on @challenge.
In terms of indices, [user_id,challenge_id] isnāt a bad one. Generally you want to put indices on all your relationships. Is the request slow?
Otherwise the code will provide the user_activities that is related to the current_user and the @challenge as expected.
Also using where will return all the models that match the condition. Using find will only return the first model it finds. So while find would technically be quicker, you want to use where if you want all the user_activites. It seems like you wouldnāt just want the first one.
Actually at one time user can participate in many challenges at the same like Walking Challenge, Cycling Challenge, Diet Challenge. But for each challenge there can be only on UserActivity.
So Charlie has joined the challengge WalkingChallenge and User Activity for that challenge keeps a track on Charlieās daily actiivity.