Last active
September 27, 2016 20:32
-
-
Save wiseleyb/aab8474ef87d7c5d25070e3e83969ca3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=begin | |
This is a somewhat hacky user-recovery script that I hacked out at 3am after accidently deleting a bunch of users. | |
To use: | |
* get a good copy of the prod-db before you fucked up | |
* an array of user-ids you want to restore | |
* run users_to_yaml(user-ids) | |
* create a secret gist for each yml file created | |
* plug the urls of the gists into the Gists class | |
* paste this entire script into prod-con and pray | |
* delete the secret gists | |
Notes: The reason I'm using RecoverClass's instead of the normal class is we don't want to spam users and have all the validations/events fire. The remove const nonsense is necessary because of beloved STI Rails bullshit. | |
To get a prod db: | |
* heroku pg:backups --app zeemee-prod | |
* heroku pg:backups public-url a732 --app zeemee-prod | |
=end | |
require 'open-uri' | |
def users_to_yaml(uids) | |
users = User.where(id: uids) | |
f = File.open("tmp/recover/users.yml", 'w') | |
f << YAML::dump(users) | |
f.close | |
mim = MediaItemMetadata.where(user_id: uids) | |
f = File.open("tmp/recover/media_item_metadata.yml", 'w') | |
f << YAML::dump(mim) | |
f.close | |
p = Portfolio.where(user_id: uids) | |
f = File.open("tmp/recover/portfolios.yml", 'w') | |
f << YAML::dump(p) | |
f.close | |
pl = Placement.where(portfolio_id: p.map(&:id)) | |
f = File.open("tmp/recover/placements.yml", 'w') | |
f << YAML::dump(pl) | |
f.close | |
# Photo, Video, Document | |
mim = MediaItemMetadata.where(user_id: uids) | |
mi = mim.map(&:media_item) | |
res = {} | |
[Photo, Video, Document].each do |klass| | |
res[klass.to_s.underscore] = mi.select {|r| r.is_a?(klass)} | |
end | |
res.each do |k, v| | |
f = File.open("tmp/recover/#{k}.yml", 'w') | |
f << YAML::dump(v) | |
f.close | |
end | |
s = Shoutout.where(user_id: uids) | |
f = File.open("tmp/recover/shoutouts.yml", 'w') | |
f << YAML::dump(s) | |
f.close | |
uos = UserOrganizationStatus.where(user_id: uids) | |
f = File.open("tmp/recover/uos.yml", 'w') | |
f << YAML::dump(uos) | |
f.close | |
end | |
class Gists | |
class << self | |
def media_item_metadata | |
'https://gist.githubusercontent.com/wiseleyb/eaf8c369c18ba6948978db59513e5b3a/raw/1d40064259c501b5abfb8e26bae26836c75ca5ee/media_item_metadata.yml' | |
end | |
def document | |
'https://gist.githubusercontent.com/wiseleyb/256dd15420aa1f3fed03342eb0d032f9/raw/90051f0dbfaa93754fffc16b8e1c46ddf44b7c8e/document.yml' | |
end | |
def photo | |
'https://gist.githubusercontent.com/wiseleyb/c40813ebd6575e772ee15c6154e67f49/raw/b2f27d166c088ad8b108b44aebc321bcc1de5c9a/photo.yml' | |
end | |
def video | |
'https://gist.githubusercontent.com/wiseleyb/ecc727401a7a8462edde9964ba279903/raw/b00c251210f5d7458dbdabb667cf9ed7cac45274/video.yml' | |
end | |
def placement | |
'https://gist.githubusercontent.com/wiseleyb/26ecf289c2263fa6dff73e3afb3af6f9/raw/8f356a75e9a4a9934e8eb9f8b7be6c2d6fe7e468/placements.yml' | |
end | |
def portfolio | |
'https://gist.githubusercontent.com/wiseleyb/28fe7853fc5f3885b4b163d437b497b5/raw/163c0272f8182076de9b1eb01fb3aaa1d237dcce/portfolios.yml' | |
end | |
def shoutout | |
'https://gist.githubusercontent.com/wiseleyb/12c705191f4309109268811dc6081430/raw/f08afea34c2b224ec2bf539a91cb32d65fffb329/shoutouts.yml' | |
end | |
def user_organization_status | |
'https://gist.githubusercontent.com/wiseleyb/f806ab86569772659022782e63c5d359/raw/66487736969165b8dc693c5759d2007ec1c8e682/uos.yml' | |
end | |
def user | |
'https://gist.githubusercontent.com/wiseleyb/c0028c57a5532f7050f0a9c762be6545/raw/b21f957a89516188ccf1a0f7fc45eff5ae547f44/users.yml' | |
end | |
end | |
end | |
def load_from_yaml(klass_name) | |
klass = "Recover#{klass_name}".constantize | |
url = Gists.send(klass_name.underscore) | |
objs = load_from_gist(url, klass_name).map do |r| | |
klass.new(r.attributes) | |
end | |
objs.each do |obj| | |
puts "#{klass_name}: #{obj.id}" | |
next if klass_name == 'User' && klass.find_by_slug(obj.slug) | |
next if klass.find_by_id(obj.id) | |
obj.save! | |
end | |
end | |
def load_from_gist(url, fname) | |
open("tmp/#{fname}.yml", 'wb') do |f| | |
f << open(url).read | |
end | |
YAML.load_file("tmp/#{fname}.yml") | |
end | |
class RecoverUser < ActiveRecord::Base | |
self.table_name = User.table_name | |
# MailchimpSubscribe.perform_later email, first_name, last_name | |
end | |
class Student < RecoverUser; end | |
class AdmissionsRep < RecoverUser; end | |
class RecoverMediaItemMetadata < ActiveRecord::Base | |
self.table_name = MediaItemMetadata.table_name | |
end | |
class RecoverPhoto < ActiveRecord::Base | |
self.table_name = Photo.table_name | |
end | |
class RecoverVideo < ActiveRecord::Base | |
self.table_name = Video.table_name | |
end | |
class RecoverDocument < ActiveRecord::Base | |
self.table_name = Document.table_name | |
end | |
class RecoverPlacement < ActiveRecord::Base | |
self.table_name = Placement.table_name | |
end | |
class RecoverPortfolio < ActiveRecord::Base | |
self.table_name = Portfolio.table_name | |
end | |
class RecoverShoutout < ActiveRecord::Base | |
self.table_name = Shoutout.table_name | |
end | |
class RecoverUserOrganizationStatus < ActiveRecord::Base | |
attr_accessor :pending_accepted, :acceptance_letter_url | |
self.table_name = UserOrganizationStatus.table_name | |
end | |
Object.send(:remove_const, Student.to_s) | |
class Student < RecoverUser; end | |
Object.send(:remove_const, AdmissionsRep.to_s) | |
class AdmissionsRep < RecoverUser; end | |
[User, UserOrganizationStatus, Shoutout, | |
Portfolio, Placement, Photo, Document, | |
MediaItemMetadata].each do |klass| | |
puts '*' * 80 | |
puts "Loading #{klass.to_s}" | |
load_from_yaml(klass.to_s) | |
puts '*' * 80 | |
puts '' | |
puts '' | |
end | |
def undelete(klass_name) | |
klass = "#{klass_name}".constantize | |
url = Gists.send(klass_name.underscore) | |
objs = load_from_gist(url, klass_name).map do |r| | |
if obj = klass.unscoped.find_by_id(r.id) | |
obj.deleted_at = nil | |
obj.save! | |
end | |
end | |
end | |
[Portfolio, Photo, Video].each do |klass| | |
undelete(klass.to_s) | |
end | |
def video_load_from_yaml | |
klass_name = 'Video' | |
klass = Video | |
url = Gists.send(klass_name.underscore) | |
objs = load_from_gist(url, klass_name).map { |r| klass.new(r.attributes) } | |
objs.each do |obj| | |
puts "#{klass_name}: #{obj.id}" | |
next if klass_name == 'User' && klass.find_by_slug(obj.slug) | |
next if klass.unscoped.find_by_id(obj.id) | |
obj.save! | |
end | |
end | |
video_load_from_yaml | |
users = User.where(id: uid) | |
users.each do |u| | |
MailchimpSubscribe.perform_later u.email, u.first_name, u.last_name | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment