module SocialNetworking # Something to be completed by a Participant. class Goal < ActiveRecord::Base # create a mini DSL for types of Goal actions ACTION_TYPES = %w( created completed did_not_complete ) Actions = Struct.new(*ACTION_TYPES.map(&:to_sym)) .new(*(ACTION_TYPES.map { |t| t.gsub(/_/, " ") })) belongs_to :participant has_many :comments, as: "item" has_many :likes, as: "item" validates :participant, :description, presence: true validate :not_due_in_the_past, on: :create validate :due_before_membership_ends, on: :create # Within the last day, used for shared item generation scope :did_not_complete, (lambda do where(deleted_at: nil, completed_at: nil) .where(arel_table[:due_on].lt(Time.zone.today)) .where(arel_table[:due_on].gteq(Time.zone.today - 1.day)) end) def to_serialized if due_on { description: description, dueOn: due_on.to_s(:participant_date) } else {} end end def shared_description "Goal: #{description}" end # Necessary for legacy front-end code. # rubocop:disable Style/PredicateName def is_completed completed_at? end # rubocop:enable Style/PredicateName # Necessary for legacy front-end code. # rubocop:disable Style/PredicateName def is_deleted deleted_at? end # rubocop:enable Style/PredicateName def action if is_completed "Completed" elsif due_on && due_on < Time.zone.today "Did Not Complete" else "Created" end end private def not_due_in_the_past return if due_on.nil? || due_on >= Date.today errors.add :due_on, "must not be in the past" end def due_before_membership_ends return if due_on.nil? || participant_id.nil? || participant.active_membership_end_date.nil? || due_on <= participant.active_membership_end_date errors.add :due_on, "must be during study enrollment" end scope :for_today, lambda { where(arel_table[:created_at] .gteq(Date.today.beginning_of_day) .and(arel_table[:created_at].lteq(Date.today.end_of_day))) } scope :for_week, lambda { where(arel_table[:created_at] .gteq(Time.current.advance(days: -7).beginning_of_day)) } end end