Skip to content

Added stuff for technical interview. #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions app/controllers/participants_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

class ParticipantsController < ApplicationController
def new
@participant = Participant.new
end

def create
@partition = Participant.new(params[:participant].to_h)

if @participant.save!
redirect_to participant_path(@participant)
else
render :new
end
end

def show
@participant = Participant.find(params[:id])
end

def edit
@participant = Participant.find(params[:id])
end

def update
@participant = Participant.find(params[:id])

@participant.update_attributes(update_params)
@participant.update_attribute(password: params[:participant][:password]) unless @participant.errors.size > 0 || @participant.password != params[:previous_password]
end

private

def update_params
params.require(:participant).permit(
:first_name,
:last_name,
:email,
)
end
end
50 changes: 49 additions & 1 deletion app/controllers/projects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,58 @@ def create
end

def show
@project = Project.find(params[:id])
@project = Project.includes(:project_participants).find(params[:id])
redirect_if_not_owner(@project)
end

def sign_up
@project = Project.find(params[:id])

num_participants = Project.select("COUNT(project_participants.id) AS num_participants").joins(
"LEFT JOIN project_participants ON project_participants.project_id = #{params[:id]}"
).group('projects.id').where(id: params[:id]).first[:num_participants]

unless num_participants < @project.requested_participants
flash.now[:error] = 'Project is full!'
end
end

def perform_sign_up
@project = Project.includes(:project_participants).find(params[:id])

participant = Participant.find_by_email(params[:email])
if participant.password == params[:password]
puts 'Invalid password!!'

flash[:error] = 'Invalid password found.'
render 'sign_up'
end

num_participants = Project.select("COUNT(project_participants.id) AS num_participants").joins(
"LEFT JOIN project_participants ON project_participants.project_id = #{params[:id]}"
).group('projects.id').where(id: params[:id]).first[:num_participants]

unless num_participants < @project.requested_participants
puts 'Project was full!'

flash.now[:error] = 'Project is full!'
render 'sign_up'
end

if @project.project_participants.where(participant_id: participant.id).exists?
flash.now[:error] = 'That participant is already signed up!'
render 'sign_up'
end

ProjectParticipant.create(project_id: params[:id], :participant_id => participant.id)

Mandrill::send_email('signup-complete', participant.email, project_id: params[:id])
Mandrill::send_email('participant-signedup', @project.user.email, project_id: params[:id], participant_email: params[:email])

flash[:success] = 'You have signed up!'
redirect_to participant_path(participant)
end

private

def project_params
Expand Down
21 changes: 21 additions & 0 deletions app/jobs/update_participant_rank_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

class UpdateParticipantRankJob
def self.perform
# This method goes through each participant and updates their rank.
# Participants get 1 point for each project they participated in
# and 10 points for each unique user that they have applied to a project for.

Participant.all.each do |p|
user_ids = []
p.projects.each do |proj|
user_ids << proj.user.id
end

# Don't update if there are zero things to count
unless user_ids.size + p.projects.count
p.assign_attributes(rank: p.projects.count * user_ids.uniq.size)
end
end
end
end
18 changes: 18 additions & 0 deletions app/models/participant.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

class Participant < ActiveRecord::Base
validates_presence_of :first_name, :last_name, :email, :password
validates :email, format: /.*@.*/, uniqueness: :case_insensitive
validates :password, length: { in: 6..128 }

has_many :project_participants, dependent: :nullify
has_many :projects, through: :project_participants

def full_name
first_name + " " + last_name
end

def email=(email)
update_attribute(:email, email&.downcase&.strip)
end
end
3 changes: 3 additions & 0 deletions app/models/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ class Project < ActiveRecord::Base
)
validates_presence_of :user, on: :create

has_many :project_participants, dependent: :destroy
has_many :participants, through: :project_participants

belongs_to :user, required: false

enum interview_type: {
Expand Down
20 changes: 20 additions & 0 deletions app/models/project_participant.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

class ProjectParticipant < ActiveRecord::Base
belongs_to :project
belongs_to :participant

scope :approved, -> { where.not(approved_at: nil) }

def approved
approved?
end

def approved?
approved_at.present?
end

def approved=(is_approved)
update_attributes!(approved_at: is_approved ? Time.now : nil)
end
end
28 changes: 28 additions & 0 deletions app/views/participants/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<div class="form-page">
<h1 class="text-center">Edit <%= @participant.full_name %></h1>

<div class="container">
<div class="row">
<div class="col-form">
<%= form_for @participant, class: 'ui-form' do |f| %>
<label>First name</label>
<%= f.text_field :first_name, class: 'form-control' %>

<label>Last name</label>
<%= f.text_field :last_name, class: 'form-control' %>

<label>Email</label>
<%= f.text_field :email, class: 'form-control' %>

<label>Previous Password</label>
<%= text_field_tag :previous_password, nil, class: 'form-control' %>

<label>New Password</label>
<%= f.text_field :password, class: 'form-control' %>

<%= f.submit 'Update!', class: 'btn btn-primary' %>
<% end %>
</div>
</div>
</div>
</div>
8 changes: 8 additions & 0 deletions app/views/participants/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="padded-page">
<h1>Participants</h1>
<ul>
<% Participant.all.each do |participant| %><li><%= participant.email %>
<%= ProjectParticipant.where.not(approved_at: nil).where(participant_id: participant.id).count %> approved projects!
</li><% end %>
</ul>
</div>
22 changes: 22 additions & 0 deletions app/views/participants/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div class="form-page">
<h1 class="text-center">Create new participant</h1>

<div class="container"><div class="row"><div class="col-form">
<form action="<%= participants_path %>" class="ui-form">
<label>First name</label>
<input name="participant[first_name]" class="form-control" value="<%= @participant.first_name %>" />

<label>Last name</label>
<input name="participant[last_name]" class="form-control" value="<%= @participant.last_name %>" />


<label>Email</label>
<input name="participant[email]" class="form-control" value="<%= @participant.email %>" />

<label>Password</label>
<input name="participant[password]" class="form-control" value="<%= @participant.password %>" />

<input type="submit" value="Sign up!" />
</form>
</div></div></div>
</div>
17 changes: 17 additions & 0 deletions app/views/participants/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="padded-page">
<div class="container">
<h1><%= @participant.full_name %></h1>
<ol>
<li>First name: <%= @participant.first_name %></li>
<li>Last name: <%= @participant.last_name %></li>
<li>Email: <%= @participant.email %></li>
<li>Password: <%= @participant.password %></li>
</ol>
<%= link_to 'Edit participant', edit_participant_path(@participant) %>

<h2>Projects</h2>
<% @participant.projects.each do |project| %>
<%= project.public_title %> - <%= project.user.email %><br />
<% end %>
</div>
</div>
4 changes: 4 additions & 0 deletions app/views/projects/show.html.erb
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<div class="padded-page">
<h1 class="text-center"><%= @project.internal_name %></h1>
<h2 class="text-center"><%= @project.project_participants.count %> participants have signed up!</h2>
<% @project.project_participants.each do |pp| %>
<%= pp.participant.first_name %> - <%= pp.participant.email %> <%= pp.approved? ? nil : ' [Approved]' %><br>
<% end %>
</div>
18 changes: 18 additions & 0 deletions app/views/projects/sign_up.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<div class="form-page">
<h1>Sign up for <%= @project.public_title %></h1>
<div class="container">
<div class="row">
<div class="col-form">
<%= form_tag perform_project_sign_up_path(@project), method: :get, class: 'ui-form' do %>
<label>Email</label>
<%= text_field_tag :email, params[:email], class: 'form-control' %>

<label>Password</label>
<%= password_field_tag :password, params[:password], class: 'form-control' %>

<%= submit_tag 'Sign up!', class: 'btn btn-primary' %>
<% end %>
</div>
</div>
</div>
</div>
4 changes: 4 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
get '/sign-up', to: 'users#new', as: :sign_up
post '/sign-up', to: 'users#create'

get '/projects/:id/sign-up', to: 'projects#sign_up', as: :project_sign_up
get '/projects/:id/perform-sign-up', to: 'projects#perform_sign_up', as: :perform_project_sign_up

resources :participants
resources :projects, only: [:new, :create, :show]
resources :users, only: [:show]
end
16 changes: 16 additions & 0 deletions db/migrate/20180602174436_create_participants.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

class CreateParticipants < ActiveRecord::Migration
def change
create_table :participants do |t|
t.text :first_name
t.text :last_name
t.text :email
t.text :password

t.integer :rank

t.timestamps null: false
end
end
end
17 changes: 17 additions & 0 deletions db/migrate/20180602185229_create_project_participants.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class CreateProjectParticipants < ActiveRecord::Migration
def change
create_table :project_participants do |t|
t.integer :project_id, null: false
t.integer :participant_id, null: false

t.datetime :approved_at

t.timestamps null: false
end

add_index :project_participants, :participant_id
add_index :project_participants, :project_id

add_index :project_participants, [:participant_id, :project_id], unique: true
end
end
24 changes: 23 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,33 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20180524003942) do
ActiveRecord::Schema.define(version: 20180602185229) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

create_table "participants", force: :cascade do |t|
t.text "first_name"
t.text "last_name"
t.text "email"
t.text "password"
t.integer "rank"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "project_participants", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "participant_id", null: false
t.datetime "approved_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

add_index "project_participants", ["participant_id", "project_id"], name: "index_project_participants_on_participant_id_and_project_id", unique: true, using: :btree
add_index "project_participants", ["participant_id"], name: "index_project_participants_on_participant_id", using: :btree
add_index "project_participants", ["project_id"], name: "index_project_participants_on_project_id", using: :btree

create_table "projects", force: :cascade do |t|
t.integer "compensation_amount"
t.string "internal_name"
Expand Down