agenda-libre-ruby/app/models/event.rb

130 lines
3.9 KiB
Ruby
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

require 'schedule'
# This is the central ADL class, where are managed all events
class Event < ApplicationRecord
extend SimpleCalendar
include Schedule
acts_as_taggable
strip_attributes
has_paper_trail ignore: %i[last_updated lock_version secret submitter
decision_time latitude longitude]
belongs_to :region
# This is the eventual scheduled first event
belongs_to :event, optional: true
has_many :notes, dependent: :destroy
has_many :events, dependent: :destroy
validates :title, presence: true
validate :end_after_start
RULES = %w[daily weekly monthly monthly_day].freeze
validates :rule, inclusion: RULES, allow_nil: true
validates :description, presence: true
validates :city, presence: true
validates :region, presence: true
validates :url, allow_nil: true, format: %r{\Ahttps?:\/\/.*\..*\z}
validates :contact, email: true, allow_nil: true
validates :submitter, email: true, presence: true
geocoded_by :full_address
after_validation :geocode, if: (lambda do |obj|
obj.address_changed? || obj.city_changed? || latitude.nil?
end)
# Mechanism to store some reason which can be used when sending notifications
attr_accessor :reason
before_create EventCallbacks
after_create EventCallbacks
before_update EventCallbacks
after_update EventCallbacks
after_destroy EventCallbacks
scope :moderated, ->(*) { where moderated: true }
scope :unmoderated, ->(*) { where moderated: false }
scope :past, -> { where 'start_time <= ?', Time.zone.now }
scope :future, -> { where '? <= end_time', Time.zone.now }
scope :daylimit, ->(nb) { where 'end_time <= ?', nb.to_i.days.from_now }
scope :year, (lambda do |year|
where '? <= end_time and start_time <= ?',
Date.new(year.to_i, 1, 1).beginning_of_week,
Date.new(year.to_i, 12, 31).end_of_week.end_of_day
end)
scope :month, (lambda do |start_date|
where '? <= end_time and start_time <= ?',
start_date.to_date.beginning_of_month.beginning_of_week,
start_date.to_date.end_of_month.end_of_week.end_of_day
end)
scope :period, (lambda do |year, week|
start_date = Date.commercial(
year.to_i,
(week || (Time.zone.today + 7.days).cweek).to_i
)
where '? <= end_time and start_time <= ?',
start_date, start_date.end_of_week.end_of_day
end)
scope :region, (lambda do |region|
return if region == 'all'
temp = Region.find region
where region: [temp, temp.regions].flatten
end)
scope :locality, ->(locality) { where locality: locality }
scope :tag, ->(tag) { tagged_with tag }
scope :geo, -> { where 'latitude is not null and longitude is not null' }
before_validation on: :create do
self.submission_time = Time.zone.now
self.decision_time = Time.zone.now
# Populate submitter using contact info if absent
self.submitter ||= contact
end
before_validation on: :update do
self.latitude = nil if address_changed?
self.longitude = nil if address_changed?
end
def full_address
# Only uses the region if it is a sub-region and not a country
[address, city, region.try(:region).present? ? region : nil,
region.try(:region)].compact.join ', '
end
def hashtags
tag_list.map { |tag| "##{tag.tr('-', '_').camelize :lower}" }
end
def description
# Remove empty paragraphs, which are added by tinymce
self[:description]&.remove '<p> </p>'
end
def to_s
"#{start_time.to_date} #{city}: #{title} #{hashtags.join(' ')}"
end
def to_tweet
url = Rails.application.routes.url_helpers.event_url(
self,
host: ActionMailer::Base.default_url_options[:host]
)
tweet = "#{self} #{url}"
if tweet.size >= 140
tweet = "#{tweet[0, tweet.rindex(/\s/, 140 - url.size)]} #{url}"
end
tweet
end
private
def end_after_start
errors.add :end_time, :before_start if
end_time.present? && start_time.present? && end_time <= start_time
end
end