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

Commit 785bb8c

Browse files
committed
Allow user to have multiple identities
1 parent 5a3865e commit 785bb8c

File tree

14 files changed

+192
-56
lines changed

14 files changed

+192
-56
lines changed

app/controllers/events_controller.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ def create
1616

1717
def show
1818
@event = Event.where(id: params[:id]).includes(responses: [ :user ]).first
19+
redirect_to root_path if @event.nil?
20+
1921
@response = @event.response_for(current_user).presence || Response.new rescue nil
2022
end
2123

app/controllers/profiles_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ class ProfilesController < ApplicationController
33

44
def edit
55
@user = current_user
6-
@user.update_column(:prompted_for_details, true)
6+
@user.update_column(:profile_complete, true)
77
end
88

99
def update

app/controllers/sessions_controller.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ def destroy
1515

1616
# GET /auth/:provider/callback?param=a98xh0xeui2sc
1717
def create
18-
@user = User.authorize(auth)
18+
@identity = Identity.authorize(auth, user: current_user)
19+
@user = @identity.user
1920
sign_in_as(@user)
2021

21-
unless @user.email.present? || @user.prompted_for_details?
22+
unless @user.email.present? || @user.profile_complete?
2223
redirect_to(edit_profile_path) and return
2324
end
2425

app/models/identity.rb

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
class Identity < ActiveRecord::Base
2+
belongs_to :user
3+
4+
before_save :assign_user
5+
after_save :merge_cleanup
6+
7+
def assign_empty_attributes(attrs)
8+
old_attributes = attributes.compact
9+
new_attributes = attrs.compact
10+
11+
assign_attributes(new_attributes.merge(old_attributes))
12+
13+
self
14+
end
15+
16+
def assign_user
17+
if user_id.blank?
18+
create_user(full_name: full_name, email: email)
19+
end
20+
end
21+
22+
def destroy_merged_user
23+
orphaned_user.destroy if orphaned_user.present?
24+
end
25+
26+
def destroy_duplicate_responses
27+
user.responses.group_by(&:event_id).each do |event_id, responses|
28+
if responses.count > 1
29+
responses.first.additional_guests ||= responses.last.additional_guests
30+
responses.first.comments ||= responses.last.comments
31+
responses.last.destroy
32+
end
33+
end
34+
end
35+
36+
def full_name
37+
[ first_name, last_name ].compact.join(" ").presence
38+
end
39+
40+
def full_name=(new_name)
41+
names = new_name.to_s.split(" ")
42+
self.first_name = names.shift
43+
self.last_name = names.join(" ")
44+
end
45+
46+
def merge_cleanup
47+
destroy_merged_user
48+
destroy_duplicate_responses
49+
end
50+
51+
def merge_users(new_user)
52+
return user unless new_user.present?
53+
self.user = new_user and return if user.nil?
54+
55+
unless new_user.id == user_id
56+
new_attributes = new_user.attributes.compact.except("id")
57+
old_attributes = user.attributes.compact.except("id")
58+
59+
new_user.assign_attributes(new_attributes.merge(old_attributes))
60+
61+
user.responses.update_all(user_id: new_user.id)
62+
user.created_events.update_all(created_by: new_user.id)
63+
64+
self.user = new_user
65+
end
66+
end
67+
68+
def orphaned_user
69+
User.where(id: orphaned_user_id).first
70+
end
71+
72+
def orphaned_user_id
73+
orphaned_user_id = changes.fetch(:user_id, []).first
74+
orphaned_user_id ||= previous_changes.fetch(:user_id, []).first
75+
end
76+
77+
def self.authorize(auth, options = {})
78+
identity = Identity.where(provider: auth.provider, uid: auth.uid).first_or_initialize
79+
80+
identity.assign_empty_attributes({
81+
full_name: auth.info.name,
82+
first_name: auth.info.first_name,
83+
last_name: auth.info.last_name,
84+
email: auth.info.email,
85+
avatar_url: auth.info.image,
86+
token: auth.credentials.token,
87+
auth_hash: auth.to_h,
88+
})
89+
90+
identity.merge_users(options[:user])
91+
identity.save
92+
93+
identity
94+
end
95+
96+
97+
end
98+

app/models/user.rb

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ class User < ActiveRecord::Base
22
has_many :responses
33
has_many :events, through: :responses
44
has_many :created_events, class_name: "Event", foreign_key: :created_by
5+
has_many :identities
56

67
def attending?(event)
78
events.include?(event)
@@ -23,31 +24,6 @@ def gravatar(size = 500)
2324
avatar_url.presence || random_avatar
2425
end
2526

26-
def assign_nil_attributes(attrs)
27-
old_attributes = attributes.reject { |key, value| value.blank? }
28-
new_attributes = attrs.reject { |key, value| value.blank? }
29-
30-
assign_attributes(new_attributes.merge(old_attributes))
31-
32-
self
33-
end
34-
35-
def self.authorize(auth)
36-
user = User.where(provider: auth.provider, uid: auth.uid).first_or_initialize
37-
38-
user.assign_nil_attributes({
39-
full_name: auth.info.name,
40-
first_name: auth.info.first_name,
41-
last_name: auth.info.last_name,
42-
email: auth.info.email,
43-
avatar_url: auth.info.image,
44-
token: auth.credentials.token,
45-
auth_hash: auth.to_h
46-
})
47-
48-
user.tap(&:save)
49-
end
50-
5127
protected
5228

5329
def random_avatar(size = 500)

bin/rails

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
#!/usr/bin/env ruby
2-
begin
3-
load File.expand_path("../spring", __FILE__)
4-
rescue LoadError
5-
end
62
APP_PATH = File.expand_path('../../config/application', __FILE__)
73
require_relative '../config/boot'
84
require 'rails/commands'

bin/rake

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
#!/usr/bin/env ruby
2-
begin
3-
load File.expand_path("../spring", __FILE__)
4-
rescue LoadError
5-
end
62
require_relative '../config/boot'
73
require 'rake'
84
Rake.application.run

config/initializers/core_ext.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require "./lib/core_ext/hash.rb"
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
require './app/models/event.rb'
2+
require './app/models/identity.rb'
3+
require './app/models/response.rb'
4+
require './app/models/user.rb'
5+
6+
class ChangeUsersToIdentities < ActiveRecord::Migration
7+
def change
8+
rename_table :users, :identities
9+
add_column :identities, :user_id, :integer
10+
11+
create_table :users do |t|
12+
t.string :first_name
13+
t.string :last_name
14+
t.string :email
15+
t.string :avatar_url
16+
t.string :timezone
17+
18+
t.boolean :profile_complete
19+
20+
t.timestamps
21+
end
22+
23+
Identity.all.each do |identity|
24+
identity.assign_user
25+
identity.save
26+
27+
Response.where(user_id: identity.id).update_all(user_id: identity.user.id)
28+
Event.where(created_by: identity.id).update_all(created_by: identity.user.id)
29+
end
30+
end
31+
end

db/schema.rb

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#
1212
# It's strongly recommended that you check this file into your version control system.
1313

14-
ActiveRecord::Schema.define(version: 20140206150758) do
14+
ActiveRecord::Schema.define(version: 20140207134315) do
1515

1616
# These are extensions that must be enabled in order to support this database
1717
enable_extension "plpgsql"
@@ -28,6 +28,21 @@
2828
t.datetime "updated_at"
2929
end
3030

31+
create_table "identities", force: true do |t|
32+
t.string "provider"
33+
t.string "uid"
34+
t.string "token"
35+
t.hstore "auth_hash"
36+
t.string "first_name"
37+
t.string "last_name"
38+
t.string "email"
39+
t.datetime "created_at"
40+
t.datetime "updated_at"
41+
t.string "avatar_url"
42+
t.boolean "prompted_for_details", default: false
43+
t.integer "user_id"
44+
end
45+
3146
create_table "responses", force: true do |t|
3247
t.integer "user_id"
3348
t.string "organization"
@@ -41,17 +56,14 @@
4156
add_index "responses", ["event_id"], name: "index_responses_on_event_id", using: :btree
4257

4358
create_table "users", force: true do |t|
44-
t.string "provider"
45-
t.string "uid"
46-
t.string "token"
47-
t.hstore "auth_hash"
4859
t.string "first_name"
4960
t.string "last_name"
5061
t.string "email"
62+
t.string "avatar_url"
63+
t.string "timezone"
64+
t.boolean "profile_complete"
5165
t.datetime "created_at"
5266
t.datetime "updated_at"
53-
t.string "avatar_url"
54-
t.boolean "prompted_for_details", default: false
5567
end
5668

5769
end

0 commit comments

Comments
 (0)