master
  1class User < ApplicationRecord
  2  include Flippable
  3  has_secure_password
  4  has_many :workouts, inverse_of: :user
  5  has_many :exercise_sets, through: :workouts
  6  has_many :user_sessions, dependent: :destroy, inverse_of: :user
  7  has_one :profile
  8  has_many :received_emails
  9  USERNAME_REGEX=/\A[-a-z0-9_.]*\z/i
 10
 11  validates :username, presence: true, format: { with: USERNAME_REGEX }, uniqueness: true
 12  validates :email, presence: true, email: true, uniqueness: true
 13  validates_acceptance_of :terms_and_conditions
 14
 15  after_create :create_profile!
 16  before_validation :lowercase_account_fields
 17  alias_method :sets, :exercise_sets
 18
 19  def time_zone
 20    @time_zone ||= ActiveSupport::TimeZone[profile.read_attribute(:time_zone)]
 21  end
 22
 23  def default_time_zone?
 24    "Etc/UTC" == time_zone.name
 25  end
 26
 27  def first_workout
 28    workouts.order(occurred_at: :asc).first
 29  end
 30
 31  def gravatar_id
 32    Digest::MD5::hexdigest(email.downcase)
 33  end
 34
 35  def to_param
 36    username
 37  end
 38
 39  def import_address
 40    "#{id}@stronglifters.com"
 41  end
 42
 43  def add_to_inbox(email)
 44    received_emails.create!(
 45      to: email.to,
 46      from: email.from,
 47      subject: email.subject,
 48      body: email.body
 49    )
 50    email.attachments.each do |attachment|
 51      BackupFile.new(self, attachment).process_later(Program.stronglifts)
 52    end
 53  end
 54
 55  def personal_record_for(exercise)
 56    history_for(exercise).personal_record
 57  end
 58
 59  def history_for(exercise)
 60    TrainingHistory.new(self, exercise)
 61  end
 62
 63  def begin_workout(routine, date, body_weight)
 64    matching_workouts = workouts.where(occurred_at: date)
 65    if matching_workouts.any?
 66      matching_workouts.first
 67    else
 68      workouts.create!(
 69        routine: routine,
 70        occurred_at: date,
 71        body_weight: body_weight.to_f
 72      )
 73    end
 74  end
 75
 76  def last_routine
 77    if workouts.any?
 78      last_workout.routine
 79    else
 80      current_program.routines.order(name: :desc).first
 81    end
 82  end
 83
 84  def next_routine
 85    last_routine.next_routine
 86  end
 87
 88  def preferred_units
 89    :lbs
 90  end
 91
 92  def next_workout_for(routine = next_routine)
 93    last_body_weight = last_workout.try(:body_weight).to(preferred_units)
 94    workout = workouts.build(routine: routine, body_weight: last_body_weight)
 95    routine.prepare_sets_for(self, workout)
 96  end
 97
 98  def last_workout(exercise = nil)
 99    if exercise.present?
100      workouts.recent.with_exercise(exercise).first
101    else
102      workouts.recent.first
103    end
104  end
105
106  def current_program
107    Program.stronglifts
108  end
109
110  class << self
111    def login(username, password)
112      user = User.find_by(
113        "email = :email OR username = :username",
114        username: username.downcase,
115        email: username.downcase
116      )
117      return false if user.blank?
118      user.user_sessions.create! if user.authenticate(password)
119    end
120  end
121
122  private
123
124  def lowercase_account_fields
125    username.downcase! if username.present?
126    email.downcase! if email.present?
127  end
128end