Radan Skorić
Business logic that changes
the state of the system
class JobsController < ApplicationController
#...
def create
@job = current_user.post_job(job_params)
if @job.persisted?
redirect_to jobs_path,
notice: 'Job was successfully created.'
else
render :new
end
end
def apply
if current_user.apply_for_job(@job)
redirect_to jobs_path,
notice: 'You successfully applied to the job'
else
redirect_to jobs_path,
alert: "You don't have the necessary skills"
end
end
#...
end
class User < ActiveRecord::Base
has_many :jobs
has_many :user_skills
has_many :skills, through: :user_skills
def post_job(job_params)
job_params[:skills] &&= Skill.where(id: job_params.delete(:skills)).load
jobs.create(job_params).tap do |job|
if job.persisted?
#Notify users with matching skills
end
end
end
def apply_for_job(job)
return false if (self.skills & job.skills).size != job.skills.size
#Notify job owner about application
true
end
end
module JobPoster
def post_job(job_params)
job_params[:skills] &&= Skill.where(id: job_params.delete(:skills)).load
jobs.create(job_params).tap do |job|
if job.persisted?
#Notify users with matching skills
end
end
end
end
module JobApplicant
def apply_for_job(job)
return false if (self.skills & job.skills).size != job.skills.size
#Notify job owner about application
true
end
end
class User < ActiveRecord::Base
has_many :jobs
has_many :user_skills
has_many :skills, through: :user_skills
include JopPoster
include JobApplicant
end
class Job < ActiveRecord::Base
...
after_create :notify_users_with_matching_skills
...
end
class JobApplication < ActiveRecord::Base
...
validate :user_has_necessary_skills
...
after_create :notify_job_owner
...
end
class JobsController < ApplicationController
#...
def create
job_params[:skills] &&=
Skill.where(id: job_params.delete(:skills)).load
@job = current_user.jobs.create(job_params)
if @job.persisted?
#Notify users with matching skills
redirect_to jobs_path,
notice: 'Job was successfully created.'
else
render :new
end
end
def apply
if (current_user.skills & job.skills).size == job.skills.size
#Notify job owner about application
redirect_to jobs_path,
notice: 'You successfully applied to the job'
else
redirect_to jobs_path,
alert: "You don't have the necessary skills"
end
end
end
class User < ActiveRecord::Base
has_many :jobs
has_many :user_skills
has_many :skills,
through: :user_skills
end
#app/forms/job_application_form.rb
class JobApplicationForm
include ActiveModel::Model
attr_accessor :user, :job
validates :user_has_necessary_skills
def save
# Notify job owner
# ...
# Create/Update real models as needed
end
private
def user_has_necessary_skills
(@user.skills & @job.skills).size != @job.skills.size
end
end
#app/controller/jobs_controller.rb
def apply
@form = JobApplicationForm.new(job_application_form_params).save
if @form.persisted?
redirect_to jobs_path, notice: 'Job was successfully created.'
else
render :new
end
end
#app/models/job.rb
class Job < ActiveRecord::Base
belongs_to :user
has_many :job_skills
has_many :skills, through: :job_skills
validates_presence_of :description
end
#app/controller/jobs_controller.rb
def create
@job = JobPostingService.new(current_user).post(job_params)
if @job.persisted?
redirect_to jobs_path, notice: 'Job was successfully created.'
else
render :new
end
end
def apply
if JobApplicationService.new(current_user, @job).apply
redirect_to jobs_path, notice: 'You successfully applied to the job'
else
redirect_to jobs_path, alert: "You don't have the necessary skills"
end
end
#app/models/user.rb
class User < ActiveRecord::Base
has_many :jobs
has_many :user_skills
has_many :skills, through: :user_skills
end
#app/models/job.rb
class Job < ActiveRecord::Base
belongs_to :user
has_many :job_skills
has_many :skills, through: :job_skills
validates_presence_of :description
end
#app/managers/base_service.rb
class BaseService
def initialize(performer)
@performer = performer
end
end
#app/managers/job_posting_service.rb
class JobPostingService < BaseService
def post(job_params)
job_params[:skills] &&= Skill.where(id: job_params.delete(:skills)).load
@performer.jobs.create(job_params).tap do |job|
if job.persisted?
#Notify users with matching skills
end
end
end
end
#app/managers/job_application_service.rb
class JobApplicationService < BaseService
def initialize(performer, job)
@job = job
super(performer)
end
def apply
return false if (@performer.skills & @job.skills).size != @job.skills.size
#Notify job owner about application
true
end
end
class JobsController < ApplicationController
#...
def create
@job = JobCreationContext.new(current_user, job_params).post_new_job
if @job.persisted?
redirect_to jobs_path,
notice: 'Job was successfully created.'
else
render :new
end
end
def apply
if EmploymentNegotiationContext.new(current_user, @job).apply
redirect_to jobs_path,
notice: 'You successfully applied to the job'
else
redirect_to jobs_path,
alert: "You don't have the necessary skills"
end
end
#...
end
#app/models/user.rb
class User < ActiveRecord::Base
has_many :jobs
has_many :user_skills
has_many :skills, through: :user_skills
end
#app/models/job.rb
class Job < ActiveRecord::Base
belongs_to :user
has_many :job_skills
has_many :skills, through: :job_skills
validates_presence_of :description
end
#app/contexts/post_job_context.rb
class JobCreationContext
def initialize(user, job_params)
@user, @job_params = user, job_params
@user.extend Employer
end
def post_new_job
@user.post_job(@job_params)
end
end
#app/contexts/apply_to_job_context.rb
class EmploymentNegotiationContext
def initialize(user, job)
@user, @job = user, job
@user.extend Developer
end
def apply
@user.apply_for_job(@job)
end
end
#app/roles/employer.rb
module Employer
def post_job(job_params)
job_params[:skills] &&= Skill.where(id: job_params.delete(:skills)).load
jobs.create(job_params).tap do |job|
if job.persisted?
#Notify users with matching skills
end
end
end
end
#app/roles/developer.rb
module Developer
def apply_for_job(job)
return false if (self.skills & job.skills).size != job.skills.size
#Notify job owner about application
true
end
end