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