jam-cloud/ruby/lib/jam_ruby/models/teacher.rb

259 lines
12 KiB
Ruby

module JamRuby
class Teacher < ActiveRecord::Base
include HtmlSanitize
html_sanitize strict: [:biography, :website]
attr_accessor :validate_introduction, :validate_basics, :validate_pricing
attr_accessible :genres, :teacher_experiences, :experiences_teaching, :experiences_education, :experiences_award
has_and_belongs_to_many :genres, :class_name => "JamRuby::Genre", :join_table => "teachers_genres", :order=>"description"
has_and_belongs_to_many :instruments, :class_name => "JamRuby::Instrument", :join_table => "teachers_instruments", :order=>"description"
has_and_belongs_to_many :subjects, :class_name => "JamRuby::Subject", :join_table => "teachers_subjects", :order=>"description"
has_and_belongs_to_many :languages, :class_name => "JamRuby::Language", :join_table => "teachers_languages", :order=>"description"
has_many :teacher_experiences, :class_name => "JamRuby::TeacherExperience"
has_many :experiences_teaching, :class_name => "JamRuby::TeacherExperience", conditions: {experience_type: 'teaching'}
has_many :experiences_education, :class_name => "JamRuby::TeacherExperience", conditions: {experience_type: 'education'}
has_many :experiences_award, :class_name => "JamRuby::TeacherExperience", conditions: {experience_type: 'award'}
has_many :reviews, :class_name => "JamRuby::Review", as: :target
has_one :review_summary, :class_name => "JamRuby::ReviewSummary", as: :target
has_one :user, :class_name => 'JamRuby::User'
validates :user, :presence => true
validates :biography, length: {minimum: 5, maximum: 4096}, :if => :validate_introduction
validates :introductory_video, :format=> {:with=> /^(?:https?:\/\/)?(?:www\.)?youtu(?:\.be|be\.com)\/(?:watch\?v=)?([\w-]{10,})/, message: "is not a valid youtube URL"}, :allow_blank => true, :if => :validate_introduction
validates :years_teaching, :presence => true, :if => :validate_introduction
validates :years_playing, :presence => true, :if => :validate_introduction
validates :teaches_test_drive, inclusion: {in: [true, false]}, :if => :validate_pricing
validates :test_drives_per_week, numericality: {only_integer: true, minimum: 2, maximum: 10}, :if => :validate_pricing
validates :instruments, :length => { minimum:1, message:"At least one instrument or subject is required"}, if: :validate_basics, unless: ->(teacher){teacher.subjects.length>0}
validates :subjects, :length => { minimum:1, message:"At least one instrument or subject is required"}, if: :validate_basics, unless: ->(teacher){teacher.instruments.length>0}
validates :genres, :length => { minimum:1, message:"At least one genre is required"}, if: :validate_basics
validates :languages, :length => { minimum:1, message:"At least one language is required"}, if: :validate_basics
validate :offer_pricing, :if => :validate_pricing
validate :offer_duration, :if => :validate_pricing
validate :teaches_ages, :if => :validate_basics
default_scope { includes(:genres) }
def self.index(user, params = {})
limit = params[:per_page]
limit ||= 20
limit = limit.to_i
query = User.joins(:teacher)
instruments = params[:instruments]
if instruments && !instruments.blank? && instruments.length > 0
query = query.joins("inner JOIN teachers_instruments AS tinst ON tinst.teacher_id = teachers.id")
.where("tinst.instrument_id IN (?)", instruments)
end
subjects = params[:subjects]
if subjects && !subjects.blank? && subjects.length > 0
query = query.joins("inner JOIN teachers_subjects AS tsubjs ON tsubjs.teacher_id = teachers.id")
.where('tsubjs.subject_id IN (?)', subjects)
end
genres = params[:genres]
if genres && !genres.blank? && genres.length > 0
query = query.joins("inner JOIN teachers_genres AS tgenres ON tgenres.teacher_id = teachers.id")
.where('tgenres.genre_id IN (?)', genres)
end
country = params[:country]
if country && country.length > 0
query = query.where(country: country)
end
region = params[:region]
if region && region.length > 0
query = query.where(state: region)
end
languages = params[:languages]
if languages && !languages.blank? && languages.length > 0
query= query.joins("inner JOIN teachers_languages AS tlang ON tlang.teacher_id = teachers.id")
.where('tlang.language_id IN (?)', languages)
end
years_teaching = params[:years_teaching].to_i
if years_teaching && years_teaching > 0
query = query.where('years_teaching >= ?', years_teaching)
end
teaches_beginner = params[:teaches_beginner]
teaches_intermediate = params[:teaches_intermediate]
teaches_advanced = params[:teaches_advanced]
if teaches_beginner || teaches_intermediate || teaches_advanced
clause = ''
if teaches_beginner
clause << 'teaches_beginner = true'
end
if teaches_intermediate
if clause.length > 0
clause << ' OR '
end
clause << 'teaches_intermediate = true'
end
if teaches_advanced
if clause.length > 0
clause << ' OR '
end
clause << 'teaches_advanced = true'
end
query = query.where(clause)
end
student_age = params[:student_age].to_i
if student_age && student_age > 0
query = query.where("teaches_age_lower <= ? AND (CASE WHEN teaches_age_upper = 0 THEN true ELSE teaches_age_upper >= ? END)", student_age, student_age)
end
current_page = params[:page].nil? ? 1 : params[:page].to_i
next_page = current_page + 1
# will_paginate gem
query = query.paginate(:page => current_page, :per_page => limit)
if query.length == 0 # no more results
{ query: query, next_page: nil}
elsif query.length < limit # no more results
{ query: query, next_page: nil}
else
{ query: query, next_page: next_page }
end
end
def self.save_teacher(user, params)
teacher = build_teacher(user, params)
teacher.save
teacher
end
def self.build_teacher(user, params)
# ensure person creating this Teacher is a Musician
unless user && user.musician?
raise JamPermissionError, "must be a musician"
end
teacher = user.teacher
teacher ||= user.build_teacher()
teacher.user = user
teacher.website = params[:website] if params.key?(:website)
teacher.biography = params[:biography] if params.key?(:biography)
teacher.introductory_video = params[:introductory_video] if params.key?(:introductory_video)
teacher.introductory_video = params[:introductory_video] if params.key?(:introductory_video)
teacher.years_teaching = params[:years_teaching] if params.key?(:years_teaching)
teacher.years_playing = params[:years_playing] if params.key?(:years_playing)
teacher.teaches_age_lower = params[:teaches_age_lower] if params.key?(:teaches_age_lower)
teacher.teaches_age_upper = params[:teaches_age_upper] if params.key?(:teaches_age_upper)
teacher.website = params[:website] if params.key?(:website)
teacher.biography = params[:biography] if params.key?(:biography)
teacher.teaches_beginner = params[:teaches_beginner] if params.key?(:teaches_beginner)
teacher.teaches_intermediate = params[:teaches_intermediate] if params.key?(:teaches_intermediate)
teacher.teaches_advanced = params[:teaches_advanced] if params.key?(:teaches_advanced)
teacher.prices_per_lesson = params[:prices_per_lesson] if params.key?(:prices_per_lesson)
teacher.prices_per_month = params[:prices_per_month] if params.key?(:prices_per_month)
teacher.lesson_duration_30 = params[:lesson_duration_30] if params.key?(:lesson_duration_30)
teacher.lesson_duration_45 = params[:lesson_duration_45] if params.key?(:lesson_duration_45)
teacher.lesson_duration_60 = params[:lesson_duration_60] if params.key?(:lesson_duration_60)
teacher.lesson_duration_90 = params[:lesson_duration_90] if params.key?(:lesson_duration_90)
teacher.lesson_duration_120 = params[:lesson_duration_120] if params.key?(:lesson_duration_120)
teacher.price_per_lesson_30_cents = params[:price_per_lesson_30_cents] if params.key?(:price_per_lesson_30_cents)
teacher.price_per_lesson_45_cents = params[:price_per_lesson_45_cents] if params.key?(:price_per_lesson_45_cents)
teacher.price_per_lesson_60_cents = params[:price_per_lesson_60_cents] if params.key?(:price_per_lesson_60_cents)
teacher.price_per_lesson_90_cents = params[:price_per_lesson_90_cents] if params.key?(:price_per_lesson_90_cents)
teacher.price_per_lesson_120_cents = params[:price_per_lesson_120_cents] if params.key?(:price_per_lesson_120_cents)
teacher.price_per_month_30_cents = params[:price_per_month_30_cents] if params.key?(:price_per_month_30_cents)
teacher.price_per_month_45_cents = params[:price_per_month_45_cents] if params.key?(:price_per_month_45_cents)
teacher.price_per_month_60_cents = params[:price_per_month_60_cents] if params.key?(:price_per_month_60_cents)
teacher.price_per_month_90_cents = params[:price_per_month_90_cents] if params.key?(:price_per_month_90_cents)
teacher.price_per_month_120_cents = params[:price_per_month_120_cents] if params.key?(:price_per_month_120_cents)
teacher.teaches_test_drive = params[:teaches_test_drive] if params.key?(:teaches_test_drive)
teacher.test_drives_per_week = params[:test_drives_per_week] if params.key?(:test_drives_per_week)
# Many-to-many relations:
if params.key?(:genres)
genres = params[:genres]
genres = [] if genres.nil?
teacher.genres = genres.collect{|genre_id| Genre.find(genre_id)}
end
if params.key?(:instruments)
instruments = params[:instruments]
instruments = [] if instruments.nil?
teacher.instruments = instruments.collect{|instrument_id| Instrument.find(instrument_id)}
end
if params.key?(:subjects)
subjects = params[:subjects]
subjects = [] if subjects.nil?
teacher.subjects = subjects.collect{|subject_id| Subject.find(subject_id)}
end
if params.key?(:languages)
languages = params[:languages]
languages = [] if languages.nil?
teacher.languages = languages.collect{|language_id| Language.find(language_id)}
end
# Experience:
[:teaching, :education, :award].each do |experience_type|
key = "experiences_#{experience_type}".to_sym
if params.key?(key)
list = params[key]
list = [] if list.nil?
experiences = list.collect do |exp|
TeacherExperience.new(
name: exp[:name],
experience_type: experience_type,
organization: exp[:organization],
start_year: exp[:start_year],
end_year: exp[:end_year]
)
end # collect
# we blindly destroy/recreate on every resubmit
previous = teacher.send("#{key.to_s}")
previous.destroy_all
# Dynamically call the appropriate method (just setting the
# value doesn't result in the behavior we need)
teacher.send("#{key.to_s}=", experiences)
end # if
end # do
# How to validate:
teacher.validate_introduction = !!params[:validate_introduction]
teacher.validate_basics = !!params[:validate_basics]
teacher.validate_pricing = !!params[:validate_pricing]
teacher
end
def offer_pricing
unless prices_per_lesson.present? || prices_per_month.present?
errors.add(:offer_pricing, "Must choose to price per lesson or per month")
end
end
def offer_duration
unless lesson_duration_30.present? || lesson_duration_45.present? || lesson_duration_60.present? || lesson_duration_90.present? || lesson_duration_120.present?
errors.add(:offer_duration, "Must offer at least one duration")
end
end
def teaches_ages
if teaches_age_lower > 0 && teaches_age_upper > 0 && (teaches_age_upper < teaches_age_lower)
errors.add(:ages_taught, "Age range is backwards")
end
end
def recent_reviews
reviews.order('created_at desc').limit(20)
end
end
end