Skip to content

Instantly share code, notes, and snippets.

@vala
Created February 22, 2016 11:02
Show Gist options
  • Save vala/7c82ae8b8b5a354e2291 to your computer and use it in GitHub Desktop.
Save vala/7c82ae8b8b5a354e2291 to your computer and use it in GitHub Desktop.
Simple script to allowing to migrate hardcoded URLs in model fields to other hosts
#!/usr/bin/env ruby
#
# This script allows for parsing every models of your app, looking for string
# and text fields, then replacing every previous hardcoded URL with a new
# URL reflecting your new assets location
#
# Example usage :
#
# # Replace all URLs targeting an S3 bucket to a locale system URL
# rake replace_models_assets_url MATCHER="http://s3.amazonaws.com/mybucket/" REPLACEMENT="/system/"
#
class ModelsAssetsURLReplacer
def initialize
eager_load_models!
end
def run
ask_user_confirmation!
models.each do |model|
next unless model.table_name.present?
ModelReplacer.new(model).replace!
end
end
private
def eager_load_models!
# Eager load all models
$LOAD_PATH.each do |path|
next unless path.to_s.match(/\/models/)
Dir[File.join(path, '**', '*.rb')].each do |file|
load(file)
end
end
end
def models
@models ||= ActiveRecord::Base.descendants
end
def ask_user_confirmation!
answer = ask "Every string found in your models starting with \"#{ ENV['MATCHER'] }\" " +
"will be replaced with a starting \"#{ ENV['REPLACEMENT'] }\". " +
"Are you sure ? (y/n) "
if answer.match(/^y/i)
puts "\n" # Jump a line
else
puts "Aborted !"
Process.exit
end
end
def ask(question)
print question
STDIN.gets
end
end
class ModelReplacer
attr_reader :model, :changes_count
def initialize(model)
@model = model
@changes_count = 0
end
def replace!
print "Replace URLs for model : #{ model.name } ... "
model.find_each do |resource|
attributes = text_columns.each_with_object({}) do |column, hash|
if (value = resource.send(column)) && String === value
hash[column] = value.gsub(ENV['MATCHER'], ENV['REPLACEMENT'])
end
end
resource.assign_attributes(attributes)
@changes_count += 1 if resource.changed?
resource.save(validate: false)
end
puts "Done ! #{ changes_count } rows changed."
end
private
def text_columns
@text_columns ||= model.columns.select { |c|
c.type.in?([:string, :text])
}.map(&:name)
end
end
task replace_models_assets_url: :environment do |t, args|
# Run the script
ModelsAssetsURLReplacer.new.run
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment