tasafo/palestras-coletivas

View on GitHub
app/models/user.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
98%
class User
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::Slug

  field :name, type: String
  field :username, type: String
  field :email, type: String
  field :password_hash, type: String
  field :auth_token, type: String
  field :password_reset_token, type: String
  field :password_reset_sent_at, type: DateTime
  field :counter_public_talks, type: Integer, default: 0
  field :counter_watched_talks, type: Integer, default: 0
  field :counter_organizing_events, type: Integer, default: 0
  field :counter_presentation_events, type: Integer, default: 0
  field :counter_enrollment_events, type: Integer, default: 0
  field :counter_participation_events, type: Integer, default: 0
  field :gravatar_photo, type: String

  mount_uploader :avatar, AvatarUploader

  has_and_belongs_to_many :talks, inverse_of: :talks, index: true, dependent: :restrict_with_error
  has_and_belongs_to_many :watched_talks, class_name: 'Talk', inverse_of: :watched_user, index: true
  has_and_belongs_to_many :events, inverse_of: :users, index: true, dependent: :restrict_with_error
  has_many :enrollments, dependent: :restrict_with_error
  has_many :votes

  slug :name

  attr_reader :password

  validates_presence_of :name, :username
  validates_length_of :name, minimum: 3
  validates_uniqueness_of :email, :username
  validates_format_of :email, with: /\A[^@][\w.-]+@[\w.-]+[.][a-z]{2,4}\z/
  validates_format_of :username, with: /\A@[a-z]\w{2}\w+\z/
  validates_presence_of :password, if: :require_password?
  validates_confirmation_of :password, if: :require_password?

  index({ email: 1 }, { unique: true, background: true })
  index({ username: 1 }, { unique: true, background: true })

  scope :with_relations, -> { includes(:talks, :events) }

  after_save do
    @password = nil
    @password_confirmation = nil
    @validate_password = false
  end

  before_create do
    generate_token(:auth_token)
  end

  before_save do
    self.gravatar_photo = Gravatar.new(email).thumbnail_url
  end

  before_validation do
    self.username = '@' << username if !username.blank? && username[0] != '@'
  end

  def password=(password)
    if password.blank?
      @validate_password = false
    else
      self.password_hash = PasswordEncryptor.encrypt(password.to_s)
      @validate_password = true
      @password = password
    end
  end

  def generate_token(column)
    self[column] = SecureRandom.urlsafe_base64 while User.where(column => self[column]).exists?
  end

  def send_password_reset
    generate_token(:password_reset_token)
    self.password_reset_sent_at = Time.now
    save!
    UserMailer.password_reset(id.to_s).deliver_later
  end

  def arrived_at(event)
    enrollment = enrollments.find_by(event: event)
    enrollment ||= enroll_at(event)
    enrollment.present = true

    EnrollmentDecorator.new(enrollment, 'present').update
  end

  def enroll_at(event)
    enrollment = enrollments.new(event: event, active: true)

    EnrollmentDecorator.new(enrollment, 'active').create
  end

  def present_at?(event)
    enrollment = enrollments.find_by(event: event)

    enrollment ? enrollment.present : false
  end

  def watch_talk(talk)
    return if watched_talk? talk

    watched_talks << talk

    inc(counter_watched_talks: 1)
  end

  def unwatch_talk(talk)
    watched_talks.delete talk

    inc(counter_watched_talks: -1)
  end

  def watched_talk?(talk)
    watched_talks.include? talk
  end

  def thumbnail
    if avatar?
      Utility.https(avatar.url)
    elsif gravatar_photo?
      Utility.https(gravatar_photo)
    end
  end

  def destroy_avatar
    image_file = avatar.file

    ImageFile.remove(image_file) if image_file
  end

  private

  def require_password?
    new_record? || @validate_password
  end
end