Skip to content
This repository was archived by the owner on Mar 20, 2019. It is now read-only.

Commit 5b866f6

Browse files
committed
Initial user model cleanup
1 parent 6315a47 commit 5b866f6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+981
-644
lines changed

app/models/available_coupon.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ class AvailableCoupon < ActiveRecord::Base
22
end
33

44
# == Schema Information
5-
# Schema version: 20140713193201
65
#
76
# Table name: available_coupons
87
#
98
# id :integer not null, primary key
10-
# codeschool_coupon :string(255) indexed
11-
# peepcode_coupon :string(255) indexed
9+
# codeschool_coupon :string(255)
10+
# peepcode_coupon :string(255)
1211
# recipes_coupon :string(255)
1312
#
1413
# Indexes

app/models/badge.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,14 @@ def event_type
101101
end
102102

103103
# == Schema Information
104-
# Schema version: 20140713193201
105104
#
106105
# Table name: badges
107106
#
108107
# id :integer not null, primary key
109108
# created_at :datetime
110109
# updated_at :datetime
111-
# user_id :integer indexed, indexed => [badge_class_name]
112-
# badge_class_name :string(255) indexed => [user_id]
110+
# user_id :integer
111+
# badge_class_name :string(255)
113112
#
114113
# Indexes
115114
#

app/models/comment.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,16 +139,15 @@ def analyze_spam
139139
end
140140

141141
# == Schema Information
142-
# Schema version: 20140713193201
143142
#
144143
# Table name: comments
145144
#
146145
# id :integer not null, primary key
147146
# title :string(50) default("")
148147
# comment :text default("")
149-
# commentable_id :integer indexed
150-
# commentable_type :string(255) indexed
151-
# user_id :integer indexed
148+
# commentable_id :integer
149+
# commentable_type :string(255)
150+
# user_id :integer
152151
# likes_cache :integer default(0)
153152
# likes_value_cache :integer default(0)
154153
# created_at :datetime

app/models/concerns/user_award.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
module UserAward
2+
extend ActiveSupport::Concern
3+
included do
4+
def award(badge)
5+
new_badge = self.badges.of_type(badge).first || self.badges.build(badge_class_name: badge.class.name)
6+
end
7+
8+
def add_github_badge(badge)
9+
GithubBadge.new.add(badge, self.github)
10+
end
11+
12+
def remove_github_badge(badge)
13+
GithubBadge.new.remove(badge, self.github)
14+
end
15+
16+
def add_all_github_badges
17+
enqueue(GithubBadgeOrg, self.username, :add)
18+
end
19+
20+
def remove_all_github_badges
21+
enqueue(GithubBadgeOrg, self.username, :remove)
22+
end
23+
24+
def award_and_add_skill(badge)
25+
award badge
26+
if badge.respond_to? :skill
27+
add_skill(badge.skill)
28+
end
29+
end
30+
31+
def assign_badges(new_badges)
32+
new_badge_classes = new_badges.map { |b| b.class.name }
33+
old_badge_classes = self.badges.map(&:badge_class_name)
34+
35+
@badges_to_destroy = old_badge_classes - new_badge_classes
36+
37+
new_badges.each do |badge|
38+
award_and_add_skill(badge)
39+
end
40+
end
41+
end
42+
end

app/models/concerns/user_facts.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
module UserFacts
2+
extend ActiveSupport::Concern
3+
included do
4+
def build_facts(all)
5+
since = (all ? Time.at(0) : self.last_refresh_at)
6+
build_github_facts(since)
7+
build_lanyrd_facts
8+
build_linkedin_facts
9+
build_bitbucket_facts
10+
build_speakerdeck_facts
11+
build_slideshare_facts
12+
end
13+
14+
def build_speakerdeck_facts
15+
Speakerdeck.new(speakerdeck).facts if speakerdeck_identity
16+
end
17+
18+
def build_slideshare_facts
19+
Slideshare.new(slideshare).facts if slideshare_identity
20+
end
21+
22+
def build_lanyrd_facts
23+
Lanyrd.new(twitter).facts if lanyrd_identity
24+
end
25+
26+
def build_bitbucket_facts
27+
Bitbucket::V1.new(bitbucket).update_facts! unless bitbucket.blank?
28+
end
29+
30+
def build_github_facts(since=Time.at(0))
31+
GithubProfile.for_username(github, since).facts if github_identity and github_failures == 0
32+
end
33+
34+
def build_linkedin_facts
35+
LinkedInStream.new(linkedin_token + '::' + linkedin_secret).facts if linkedin_identity
36+
rescue => e
37+
logger.error(e.message + "\n " + e.backtrace.join("\n "))
38+
end
39+
40+
41+
def repo_facts
42+
self.facts.select { |fact| fact.tagged?('personal', 'repo', 'original') }
43+
end
44+
45+
def lanyrd_facts
46+
self.facts.select { |fact| fact.tagged?('lanyrd') }
47+
end
48+
49+
#Let put these here for now
50+
def bitbucket_identity
51+
"bitbucket:#{bitbucket}" unless bitbucket.blank?
52+
end
53+
54+
def speakerdeck_identity
55+
"speakerdeck:#{speakerdeck}" if speakerdeck
56+
end
57+
58+
def slideshare_identity
59+
"slideshare:#{slideshare}" if slideshare
60+
end
61+
62+
end
63+
end

app/models/concerns/user_github.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module UserGithub
2+
extend ActiveSupport::Concern
3+
4+
included do
5+
6+
def github_identity
7+
"github:#{github}" if github
8+
end
9+
10+
def clear_github!
11+
self.github_id = nil
12+
self.github = nil
13+
self.github_token = nil
14+
self.joined_github_on = nil
15+
self.github_failures = 0
16+
save!
17+
end
18+
end
19+
20+
module ClassMethods
21+
def stalest_github_profile(limit = nil)
22+
query = active.order("achievements_checked_at ASC")
23+
limit ? query.limit(limit) : query
24+
end
25+
end
26+
end

app/models/concerns/user_linkedin.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module UserLinkedin
2+
extend ActiveSupport::Concern
3+
4+
included do
5+
def linkedin_identity
6+
"linkedin:#{linkedin_token}::#{linkedin_secret}" if linkedin_token
7+
end
8+
9+
def clear_linkedin!
10+
self.linkedin = nil
11+
self.linkedin_id = nil
12+
self.linkedin_token = nil
13+
self.linkedin_secret = nil
14+
self.linkedin_public_url = nil
15+
self.linkedin_legacy = nil
16+
save!
17+
end
18+
end
19+
end

app/models/concerns/user_oauth.rb

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
module UserOauth
2+
extend ActiveSupport::Concern
3+
module ClassMethods
4+
def for_omniauth(auth)
5+
if user = find_with_oauth(auth)
6+
user.apply_oauth(auth)
7+
user.save! if user.changed?
8+
return user
9+
else
10+
user = new(
11+
name: auth[:info][:name],
12+
email: auth[:info][:email],
13+
backup_email: auth[:info][:email],
14+
location: location_from(auth),
15+
thumbnail_url: thumbnail_url_for(auth))
16+
user.apply_oauth(auth)
17+
user.username = auth[:info][:nickname]
18+
return user
19+
end
20+
end
21+
22+
def find_with_oauth(oauth)
23+
case oauth[:provider]
24+
when 'github'
25+
github_scope = (oauth[:uid] ? where(github_id: oauth[:uid]) : where(github: oauth[:info][:nickname]))
26+
raise "Not a unique github credential #{oauth[:uid] || oauth[:info][:nickname]}" if github_scope.count > 1
27+
return github_scope.first
28+
when 'linkedin'
29+
linkedin_scope = where(linkedin_id: oauth[:uid])
30+
raise "Not a unique linkedin credential #{oauth[:uid]}" if linkedin_scope.count > 1
31+
return linkedin_scope.first
32+
when 'twitter'
33+
twitter_scope = where(twitter_id: oauth[:uid])
34+
raise "Not a unique twitter credential #{oauth[:uid]}" if twitter_scope.count > 1
35+
return twitter_scope.first
36+
when 'developer'
37+
fail 'Developer Strategy must not be used in production.' if Rails.env.production?
38+
developer_scope = where(email: oauth[:uid])
39+
raise "Looks like there's duplicate users for the email '#{oauth[:uid]}'. Check user ids: #{developer_scope.map(&:id).join(', ')}" if developer_scope.count > 1
40+
return developer_scope.first
41+
else
42+
raise "Unexpected provider: #{oauth[:provider]}"
43+
end
44+
end
45+
46+
def location_from(oauth)
47+
if oauth[:extra] && oauth[:extra][:raw_info] && oauth[:extra][:raw_info][:location]
48+
(oauth[:extra][:raw_info][:location].is_a?(Hash) && oauth[:extra][:raw_info][:location][:name]) || oauth[:extra][:raw_info][:location]
49+
elsif oauth[:info]
50+
oauth[:info][:location]
51+
end
52+
end
53+
54+
def thumbnail_url_for(oauth)
55+
if github = oauth[:extra] && oauth[:extra][:raw_info] && oauth[:extra][:raw_info][:gravatar_id]
56+
"https://secure.gravatar.com/avatar/#{oauth[:extra][:raw_info][:gravatar_id]}"
57+
elsif oauth[:info]
58+
if oauth['provider'] == 'twitter'
59+
oauth[:extra][:raw_info][:profile_image_url_https]
60+
else
61+
oauth[:info][:image]
62+
end
63+
end
64+
end
65+
66+
def all_tokens
67+
with_tokens.select("github_token").collect(&:github_token)
68+
end
69+
70+
def apply_oauth(oauth)
71+
case oauth[:provider]
72+
when 'github'
73+
self.github = oauth[:info][:nickname]
74+
self.github_id = oauth[:uid]
75+
self.github_token = oauth[:credentials][:token]
76+
self.blog = oauth[:info][:urls][:Blog] if oauth[:info][:urls] && self.blog.blank?
77+
self.joined_github_on = extract_joined_on(oauth) if self.joined_github_on.blank?
78+
when 'linkedin'
79+
self.linkedin_id = oauth[:uid]
80+
self.linkedin_public_url = oauth[:info][:urls][:public_profile] if oauth[:info][:urls]
81+
self.linkedin_token = oauth[:credentials][:token]
82+
self.linkedin_secret = oauth[:credentials][:secret]
83+
when 'twitter'
84+
self.twitter = oauth[:info][:nickname]
85+
self.twitter_id = oauth[:uid]
86+
self.twitter_token = oauth[:credentials][:token]
87+
self.twitter_secret = oauth[:credentials][:secret]
88+
self.about = extract_from_oauth_extras(:description, oauth) if self.about.blank?
89+
self.joined_twitter_on = extract_joined_on(oauth) if self.joined_twitter_on.blank?
90+
when 'developer'
91+
logger.debug "Using the Developer Strategy for OmniAuth"
92+
logger.ap oauth, :debug
93+
else
94+
raise "Unexpected provider: #{oauth[:provider]}"
95+
end
96+
end
97+
98+
99+
def extract_joined_on(oauth)
100+
val = extract_from_oauth_extras(:created_at, oauth)
101+
return Date.parse(val) if val
102+
end
103+
104+
def extract_from_oauth_extras(field, oauth)
105+
oauth[:extra][:raw_info][field] if oauth[:extra] && oauth[:extra][:raw_info] && oauth[:extra][:raw_info][field]
106+
end
107+
108+
end
109+
end
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module UserRedisKeys
2+
extend ActiveSupport::Concern
3+
4+
included do
5+
def repo_cache_key
6+
username
7+
end
8+
9+
def daily_cache_key
10+
"#{username}/#{Date.today.to_time.to_i}"
11+
end
12+
13+
def timeline_key
14+
@timeline_key ||= "user:#{id}:timeline"
15+
end
16+
17+
def impressions_key
18+
"user:#{id}:impressions"
19+
end
20+
21+
def user_views_key
22+
"user:#{id}:views"
23+
end
24+
25+
def user_anon_views_key
26+
"user:#{id}:views:anon"
27+
end
28+
29+
def followed_repo_key
30+
"user:#{id}:following:repos"
31+
end
32+
33+
end
34+
end
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
module UserStatistics
2+
extend ActiveSupport::Concern
3+
4+
#OPTIMIZE
5+
module ClassMethods
6+
def signups_by_day
7+
find_by_sql("SELECT to_char(created_at, 'MM DD') AS day, count(*) AS signups from users group by to_char(created_at, 'MM DD') order by to_char(created_at, 'MM DD')").collect { |u| [u.day, u.signups] }
8+
end
9+
10+
def signups_by_hour
11+
find_by_sql("SELECT to_char(created_at, 'HH24') AS hour, count(*) AS signups from users where created_at > NOW() - interval '24 hours' group by to_char(created_at, 'HH24') order by to_char(created_at, 'HH24')").collect { |u| [u.hour, u.signups] }
12+
end
13+
14+
def signups_by_month
15+
find_by_sql("SELECT to_char(created_at, 'MON') AS day, count(*) AS signups from users group by to_char(created_at, 'MON') order by to_char(created_at, 'MON') DESC").collect { |u| [u.day, u.signups] }
16+
end
17+
18+
def repeat_visits_by_count
19+
find_by_sql("SELECT login_count, count(*) AS visits from users group by login_count").collect { |u| [u.login_count, u.visits] }
20+
end
21+
22+
def monthly_growth
23+
prior = where("created_at < ?", 31.days.ago).count
24+
month = where("created_at >= ?", 31.days.ago).count
25+
((month.to_f / prior.to_f) * 100)
26+
end
27+
28+
def weekly_growth
29+
prior = where("created_at < ?", 7.days.ago).count
30+
week = where("created_at >= ?", 7.days.ago).count
31+
((week.to_f / prior.to_f) * 100)
32+
end
33+
34+
def most_active_by_country(since=1.week.ago)
35+
select('country, count(distinct(id))').where('last_request_at > ?', since).group(:country).order('count(distinct(id)) DESC')
36+
end
37+
end
38+
end

0 commit comments

Comments
 (0)