Last active
November 21, 2023 13:21
-
-
Save Yorgg/cba16d8cfdc3ffc85ae2 to your computer and use it in GitHub Desktop.
Creating badge and achievements functionality in Ruby on Rails
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Step 1 - Create achievement, badge, and user models | |
#Create an Achivement model | |
#This will contain all of the achievements | |
#model | |
class Achievement < ActiveRecord::Base | |
has_many :badges | |
has_many :users, through: :badges | |
end | |
#table | |
class CreateAchievements < ActiveRecord::Migration | |
def change | |
create_table :achievements do |t| | |
t.text :identity, unique: true, index: true #this is so you dont have to memorize index values | |
t.text :name | |
t.timestamps null: false | |
end | |
end | |
end | |
#Create Badge model | |
#As achievements can belong to many users, and users can have many achievements, | |
#the badge model will serve as the join table | |
#(a user gets a badge when an achievement is met, so I chose the word badge to represent this) | |
class Badge < ActiveRecord::Base | |
belongs_to :user | |
belongs_to :achievement | |
end | |
#table | |
class CreateBadges < ActiveRecord::Migration | |
def change | |
create_table :badges do |t| | |
t.references :user | |
t.references :achievement | |
t.timestamps null: false | |
end | |
end | |
end | |
#Create a User model: | |
class User < ActiveRecord::Base | |
has_many :badges, dependent: :destroy | |
has_many :achievements, through: :badges | |
end | |
#Step 2 - Create a module in Controller concerns directory | |
#Achievements are typically created inside controller actions, | |
#For example, if a user completes x amount of goals, or tasks. | |
#This module checks the conditions needed to create a new badge, if they are met, | |
#the badge is created and a message is added to flash. Include the module in | |
#the controllers and call it with check_achievement(type) - the 'type' argument is the name of the controller. | |
module BadgeCreator | |
def check_achievements(type) | |
send((type + '_achievements').to_sym) | |
end | |
def create_badge(type, name) | |
return if achievement_already_reached?(type) | |
id = Achievement.find_by_identity(type).id | |
current_user.badges.create(achievement_id: id) | |
flash[:achievement] = name | |
end | |
def achievement_already_reached?(type) | |
current_user.achievements.exists?(identity: type) | |
end | |
#This is where you create the custom achievement logic - each method corresponds to a controller | |
#to do: relocate this section - to their own files/module? | |
def task_achievements() | |
#condition(s) | |
task_count = current_user.tasks.count_completed(current_user) | |
#achievements | |
create_badge('10 tasks', 'Complete 10 tasks') if task_count >= 10 | |
create_badge('100 tasks', 'Complete 100 tasks') if task_count >= 100 | |
create_badge('1000 tasks', 'Complete 1000 tasks') if task_count >= 1000 | |
end | |
end | |
class TasksController < ApplicationController | |
include BadgeCreator | |
... | |
def update | |
... | |
if @task.save | |
#Achievement | |
check_achievements("task") #call the method wherever it is needed inside your controller. | |
#the argument is needed to identify the controller. In this example | |
#the #task_achievements() method would be called | |
... | |
end | |
... | |
end | |
... | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment