Skip to content

Instantly share code, notes, and snippets.

@Harrisonl
Created December 16, 2015 05:57
Show Gist options
  • Save Harrisonl/d44b038248a41a42457c to your computer and use it in GitHub Desktop.
Save Harrisonl/d44b038248a41a42457c to your computer and use it in GitHub Desktop.
Code Examples + RSpec Example
## This is an extract from my online content platform. This model here deals with the Project object. The project object is used to
## describe a request for a new piece of content from a client. It is an important object in the application and is one which a lot
## of other models and objects depend on.This model also provides various methods which can be used throughout the application.
class Project < ActiveRecord::Base
## Validations
validates_presence_of :title, :brief, :project_tone, :client_email
## Relationships
belongs_to :client, class_name: "User", foreign_key: :client_id
belongs_to :freelancer, class_name: "Freelancer", foreign_key: :freelancer_id
has_many :payments
has_many :submissions
has_one :conversation, dependent: :delete
has_one :review, dependent: :delete
before_create :generate_uid
## Calculate the cost of the project depending on its length and price per word (PPW)
## Used in project#create
def calculate_project_cost(options={})
cpw = 3
quality = options[:quality]
type = options[:type]
length = options[:length]
tat = options[:tat]
if quality == "Normal" && type != "Ebook"
self.project_cost = cpw * length.to_i
elsif quality == "Premium" && type != "Ebook"
cpw = 5
self.project_cost = cpw * length.to_i
elsif quality == "Exceptional" && type != "Ebook"
cpw = 7
self.project_cost = cpw * length.to_i
elsif type == "Ebook"
cpw = 4
self.project_cost = cpw * length.to_i
end
self.project_cost = self.project_cost * 0.9 if length.to_i >= 6000 && tat == "normal"
self.project_cost = self.project_cost * 1.1 if tat == "fast" && length < 6000
self.save
end
# Creates a conversation when a new project is successfully created
# See ProjectsController#create for more
def create_conversation_for_project
c = Conversation.new
c.freelancer_id = self.freelancer_id
c.user_id = self.client_id
c.project_id = self.id
c.save
end
def mark_as_paid
self.paid = true
self.save
end
def in_progress?
self.in_progress
end
def completed?
self.completed
end
## Marks the project as complete and add's the earnt commission to the freelancers owed_commission attribute
def mark_project_complete
freelancer = self.freelancer
self.completed = true
self.completed_date = Date.today
self.in_progress = false
freelancer.owed_commission = freelancer.owed_commission + (self.project_cost * freelancer.earning_rate)
freelancer.save
self.save
end
# Checks if there is a freelancer assigned
def freelancer?
self.freelancer
end
# Checks if there are any submissions present
def any_submissions?
self.submissions.any?
end
def assign_writer(freelancer)
self.freelancer = freelancer
self.save
end
def request_due
created = self.created_at
tat = self.tat
if tat == "normal"
return "#{created + 3.days}"
elsif tat == "fast"
return "#{created + 1.days}"
end
end
private
## Create a random UID for the project
def generate_uid
self.uid = loop do
token = SecureRandom.urlsafe_base64
break token unless Project.exists?(uid: token)
end
end
end
## Here is the corresponding test file for Project Model.
require 'rails_helper'
RSpec.describe Project do
it { should validate_presence_of(:title) }
it { should validate_presence_of(:brief) }
it { should validate_presence_of(:project_type) }
it { should validate_presence_of(:project_length) }
it { should validate_presence_of(:project_quality) }
it { should validate_presence_of(:project_tone) }
describe "#calculate_project_cost(options={}" do
## ASSUME LENGTH IS 100 FOR ALL TESTS
it "sets cost to 300 for normal quality" do
project = Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Normal")
project.calculate_project_cost(quality: project.project_quality, length: project.project_length, tat: "normal", type: project.project_type)
project.reload
expect(project.project_cost).to eq(300)
end
it "sets the cost 500 for premium quality" do
project = Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Premium")
project.calculate_project_cost(quality: project.project_quality, length: project.project_length, tat: "normal", type: project.project_type)
project.reload
expect(project.project_cost).to eq(500)
end
it "sets the cost to 700 for exceptional quality" do
project = Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Exceptional")
project.calculate_project_cost(quality: project.project_quality, length: project.project_length, tat: "normal", type: project.project_type)
project.reload
expect(project.project_cost).to eq(700)
end
it "sets the cost to 400 for an ebook type" do
project = Project.create(title: "test", brief: "123", project_type: "Ebook", project_length: "100", project_tone: "123", project_quality: "Exceptional")
project.calculate_project_cost(quality: project.project_quality, length: project.project_length, tat: "normal", type: project.project_type)
project.reload
expect(project.project_cost).to eq(400)
end
it "adds 1000 to the cost if the tat is fast" do
project = Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Exceptional")
project.calculate_project_cost(quality: project.project_quality, length: project.project_length, tat: "fast", type: project.project_type)
project.reload
expect(project.project_cost).to eq(1700)
end
end
describe "#create_conversation_for_project" do
let(:alice) { FactoryGirl.create(:client) }
let(:bob) { FactoryGirl.create(:freelancer) }
let(:project) { Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Exceptional", freelancer_id: bob.id, client_id: alice.id) }
before do
project.create_conversation_for_project
end
it "should create a new conversation that belongs to the project" do
expect(project.conversation).to_not be_nil
end
it "should set the user id to the projects client" do
expect(Conversation.first.user_id).to eq(alice.id)
end
it "should set the freelancer id to the projects freelancer" do
expect(Conversation.first.freelancer_id).to eq(bob.id)
end
it "should set the project id to the projects id" do
expect(Conversation.first.project_id).to eq(project.id)
end
end
describe "#in_progress" do
let(:project) { Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Exceptional") }
it "returns true if in progress is true" do
project.in_progress = true
project.save
expect(project.in_progress?).to eq(true)
end
it "returns false if in progress is false" do
project.in_progress = false
project.save
expect(project.in_progress?).to eq(false)
end
end
describe "#completed?" do
let(:project) { Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Exceptional") }
it "returns true if completed is true" do
project.completed = true
project.save
expect(project.completed).to eq(true)
end
it "returns false if completed is false" do
project.completed = false
project.save
expect(project.completed).to eq(false)
end
end
describe "#mark_complete" do
let(:project) { Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Exceptional") }
it "sets the project's completed status to true" do
project.mark_complete
expect(project.completed).to eq(true)
end
it "sets the completed date to todays date" do
project.mark_complete
expect(project.completed_date).to eq(Date.today)
end
end
describe "#freelancer?" do
let(:bob) { FactoryGirl.create(:freelancer) }
let(:project) { Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Exceptional", freelancer_id: bob.id) }
it "returns the freelancer if one is assigned" do
expect(project.freelancer?).to eq(bob)
end
it "returns nil if no freelancer is assigned" do
project.freelancer = nil
project.save
expect(project.freelancer?).to be_nil
end
end
describe "#any_submissions?" do
let(:project) { Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Exceptional") }
it "returns true if there are submissions" do
submission = FactoryGirl.create(:submission, project_id: project.id)
expect(project.any_submissions?).to eq(true)
end
it "returns false if there are no submissions" do
expect(project.any_submissions?).to eq(false)
end
end
describe "#assign_writer(freelancer)" do
let(:project) { Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Exceptional") }
it "assigns the projects freelancer to the passed in freelancer" do
bob = FactoryGirl.create(:freelancer)
project.assign_writer(bob)
expect(Project.first.freelancer).to eq(bob)
end
end
describe "#request_due" do
let(:project) { Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Exceptional", tat: "normal") }
it "returns 3 days from today if the tat is normal" do
expect(project.request_due).to eq("#{project.created_at + 3.days}")
end
it "returns 1 day from today if the tat is fast" do
project.tat = "fast"
project.save
expect(project.request_due).to eq("#{project.created_at + 1.days}")
end
end
describe "#generate_uid" do
let(:project) { Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Exceptional", tat: "normal") }
let(:project2) { Project.create(title: "test", brief: "123", project_type: "article", project_length: "100", project_tone: "123", project_quality: "Exceptional", tat: "normal", uid: project.uid) }
it "should set the projects uid" do
expect(project.uid).to_not be_blank
end
it "should make sure it does not equal any other proejcts uid" do
expect(project2.uid).to_not eq(project.uid)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment