osem-fcy/app/models/track.rb
AEtherC0r3 b717018b31 Track related fixes
Make the message in admin/Tracks form more visible by making it bold and
adding links to venue and rooms
Make papertrail track changes for all the track's attributes
Add validation to require presence of description for self-organized
tracks
Add ID column to admin/Tracks#index
Make the cfp inclusion column sortable
Show success/error flash messages after toggling cfp inclusion
2017-08-11 16:25:21 +03:00

212 lines
6.4 KiB
Ruby

class Track < ActiveRecord::Base
include ActiveRecord::Transitions
include RevisionCount
resourcify :roles, dependent: :delete_all
belongs_to :program
belongs_to :submitter, class_name: 'User'
belongs_to :room
has_many :events, dependent: :nullify
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
before_create :generate_guid
validates :name, presence: true
validates :color, format: /\A#[0-9A-F]{6}\z/
validates :short_name,
presence: true,
format: /\A[a-zA-Z0-9_-]*\z/,
uniqueness: {
scope: :program
}
validates :state,
presence: true,
inclusion: { in: %w(new to_accept accepted confirmed to_reject rejected canceled withdrawn) }
validates :cfp_active, inclusion: { in: [true, false] }
validates :start_date, presence: true, if: :self_organized_and_accepted_or_confirmed?
validates :end_date, presence: true, if: :self_organized_and_accepted_or_confirmed?
validates :room, presence: true, if: :self_organized_and_accepted_or_confirmed?
validates :relevance, presence: true, if: :self_organized?
validates :description, presence: true, if: :self_organized?
validate :valid_dates
validate :valid_room, if: :self_organized_and_accepted_or_confirmed?
before_validation :capitalize_color
scope :confirmed, -> { where(state: 'confirmed') }
scope :cfp_active, -> { where(cfp_active: true) }
state_machine initial: :pending do
state :new
state :to_accept
state :accepted
state :confirmed
state :to_reject
state :rejected
state :canceled
state :withdrawn
event :restart do
transitions to: :new, from: [:rejected, :withdrawn, :canceled]
end
event :to_accept do
transitions to: :to_accept, from: [:new]
end
event :accept do
transitions to: :accepted, from: [:new, :to_accept], on_transition: :create_organizer_role
end
event :confirm do
transitions to: :confirmed, from: [:accepted], on_transition: :assign_role_to_submitter
end
event :to_reject do
transitions to: :to_reject, from: [:new]
end
event :reject do
transitions to: :rejected, from: [:new, :to_reject]
end
event :cancel do
transitions to: :canceled, from: [:to_accept, :to_reject, :accepted, :confirmed], on_transition: :revoke_role_and_cleanup
end
event :withdraw do
transitions to: :withdrawn, from: [:new, :to_accept, :to_reject, :accepted, :confirmed], on_transition: :revoke_role_and_cleanup
end
end
def conference
program.conference
end
##
# Checks if the track is self-organized
# ====Returns
# * +true+ -> If the track has a submitter
# * +false+ -> if the track doesn't have a submitter
def self_organized?
return true if submitter
false
end
def to_param
short_name
end
def transition_possible?(transition)
self.class.state_machine.events_for(current_state).include?(transition)
end
# Gives the role of the track_organizer to the submitter
def assign_role_to_submitter
submitter.add_role 'track_organizer', self
end
# Revokes the track organizer role and removes the track from events that have it set
def revoke_role_and_cleanup
role = Role.find_by(name: 'track_organizer', resource: self)
if role
role.users.each do |user|
user.remove_role 'track_organizer', self
end
end
events.each do |event|
event.track = nil
event.save!
end
end
##
# Checks if the track is accepted
# ====Returns
# * +true+ -> If the track's state is 'accepted'
# * +false+ -> If the track's state isn't 'accepted'
def accepted?
state == 'accepted'
end
##
# Checks if the track is confirmed
# ====Returns
# * +true+ -> If the track's state is 'confirmed'
# * +false+ -> If the track's state isn't 'confirmed'
def confirmed?
state == 'confirmed'
end
##
# Checks if a self-organized track is accepted or confirmed
# ====Returns
# * +true+ -> If the track's state is 'accepted' or 'confirmed'
# * +false+ -> If the track's state is neither 'accepted' nor 'confirmed'
def self_organized_and_accepted_or_confirmed?
self_organized? && (accepted? || confirmed?)
end
def update_state(transition)
error = ''
begin
send(transition)
rescue Transitions::InvalidTransition => e
error += "State update failed. #{e.message} "
end
error += errors.full_messages.join(', ') unless save
error
end
private
def generate_guid
guid = SecureRandom.urlsafe_base64
# begin
# guid = SecureRandom.urlsafe_base64
# end while Person.where(:guid => guid).exists?
self.guid = guid
end
def capitalize_color
self.color = color.upcase if color.present?
end
def conference_id
program.conference_id
end
##
# Creates the role of the track organizer
def create_organizer_role
Role.where(name: 'track_organizer', resource: self).first_or_create(description: 'For the organizers of the Track')
end
def valid_dates
if start_date && program && program.conference && program.conference.start_date && (start_date < program.conference.start_date)
errors.add(:start_date, "can't be before the conference start date (#{program.conference.start_date})")
end
if end_date && program && program.conference && program.conference.start_date && (end_date < program.conference.start_date)
errors.add(:end_date, "can't be before the conference start date (#{program.conference.start_date})")
end
if start_date && program && program.conference && program.conference.end_date && (start_date > program.conference.end_date)
errors.add(:start_date, "can't be after the conference end date (#{program.conference.end_date})")
end
if end_date && program && program.conference && program.conference.end_date && (end_date > program.conference.end_date)
errors.add(:end_date, "can't be after the conference end date (#{program.conference.end_date})")
end
if start_date && end_date && (start_date > end_date)
errors.add(:start_date, 'can\'t be after the end date')
end
end
##
# Verify that the room is a room of the conference
def valid_room
if room && room.venue && room.venue.conference && program && program.conference && (program.conference != room.venue.conference)
errors.add(:room, "must be a room of #{program.conference.venue.name}")
end
end
end