Staring at a blank VS code editor can be intimidating when approaching a new project and I'll be sharing some helpful tricks that I used to maximize my productivity for my attendance management app.
The primary functionality of this app goes as follows:
Users will be able to manage attendance for each lecture.
Once logged in the user will view the available lectures to the Teacher.Then after clicking the "Attendance log" under the lecture users will then have the ability to log attendance for the lecture with CRUD functionality.
Users will have sign in / out capability.
Users will only be able to view their own students unless they are an admin user.
Productivity Setup
I utilized notion as a primary source for managing my project listing my requirements and hosting my diagrams as well as any note taking with documentation I read during building my web app. I also created a Entity relationship diagram illustrate the relationships of my schema which you can see below:
Listing out requirements in notion
Entity Relationship Diagram
Schema
ActiveRecord::Schema.define(version: 2021_11_05_185536) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "attendances", force: :cascade do |t|
t.string "student_name"
t.integer "student_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.bigint "user_id"
t.string "status"
t.bigint "lectures_id"
t.index ["lectures_id"], name: "index_attendances_on_lectures_id"
t.index ["user_id"], name: "index_attendances_on_user_id"
end
create_table "lectures", force: :cascade do |t|
t.string "name"
t.string "description"
t.integer "classroom_number"
t.time "duration"
t.bigint "user_id"
t.index ["user_id"], name: "index_lectures_on_user_id"
end
create_table "students", force: :cascade do |t|
t.string "student_name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.bigint "lectures_id"
t.bigint "user_id", null: false
t.index ["lectures_id"], name: "index_students_on_lectures_id"
t.index ["user_id"], name: "index_students_on_user_id"
end
create_table "teachers", force: :cascade do |t|
t.string "teacher_name"
t.string "teacher_type"
t.bigint "user_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["user_id"], name: "index_teachers_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "provider"
t.string "uid"
t.string "name"
t.integer "role", default: 0
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
add_foreign_key "attendances", "lectures", column: "lectures_id"
add_foreign_key "students", "lectures", column: "lectures_id"
add_foreign_key "students", "users"
end
Ruby on Rails naming conventions
Here is a consolidated list of Naming Conventions in Ruby on Rails, that I have collected from the internet. I'm highlighting this because when you are creating your associations it's important to have the correct pluralization, otherwise your relationships between models will not work correctly.
Model -
Follows the convention of Class names of unbroken MixedCase letters
Always Singular format of the corresponding Table Name in database
file name for the Models should always be in lowercase. For Multiple words use '_'
eg.: Order (table name: orders | file name: /app/models/order.rb )
Database Table -
Table names have all lowercase letters and underscores between words, also all table names need to be plural
e.g. invoice_items, orders
Files & Directories -
Files and Directories are named using lowercase letters and '_' for multiple words formats
Proper naming and pluralization is mandatory for the conventional functioning of Rails
eg.: app/helpers/orders_helper.rb, app/models/order.rb
Creating migration associations
When you create an association, Rails makes two major assumptions – first, that the class of the model your association points to is based directly off of the name of the association, and, second, that the foreign key in any belongs_to relationship will be called yourassociationname_id. Any time you go away from these defaults, you just need to let Rails know what kind of class to look for and which foreign key to use. This especially was useful in building my user table / model and acknowledging only my teacher and admin roles.
Teachers using the attendy web app will only be able to view their own lectures and students. I was able to setup functionality in the lectures controller
class LecturesController < ApplicationController
before_action :set_lecture, only: %i[ show edit update destroy ]
# GET /lectures or /lectures.json
def index
if current_user == nil
redirect_to users_sign_in_path
else
@lectures = Lecture.teachers_lectures(current_user)
end
end
In the code above I edited the index function. I first created a conditional to check if the user is signed in and if the user is signed in to use a lambda function current_user to check the current user. These relationships would not be possible if I could lectures did not belong to user, a nested attribute. See code snippet below:
class Lecture < ApplicationRecord
has_many :attendances, dependent: :destroy, foreign_key: :lectures_id
belongs_to :user
validates :name, presence: true
scope :teachers_lectures, -> (user) { where(user_id: user.id) }
accepts_nested_attributes_for :attendances
end
Creating different Roles
If your app consist of utilizing multiple user types, chance are you are going to want to assign them different roles to allow and restrict access to certain functions. I only decided to give teachers access to this attendance app and have them log students into the portal. I assigned my users the role teacher and admin using the attribute enum. enum is an attribute where the values map to integers in the database and can be queried by name. See code snippet below.
class User < ApplicationRecord
enum role: {Teacher: 0, Admin: 1}
has_many :students
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
accepts_nested_attributes_for :students
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :omniauthable, omniauth_providers: [:google_oauth2]
def self.from_omniauth(auth)
where(email: auth.info.email).first_or_initialize do |user|
user.email = auth.info.email
user.password = user.password_confirmation = SecureRandom.hex
end
end
end
I decided to deploy my app to Heroku and if you would like to deploy your app to Heroku please feel free to check out some documentation /here
You can view my app live /here!
Top comments (0)