Skip to content

Instantly share code, notes, and snippets.

@mreq
Last active August 26, 2016 21:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mreq/2846000864a49c9b936dff77f224014e to your computer and use it in GitHub Desktop.
Save mreq/2846000864a49c9b936dff77f224014e to your computer and use it in GitHub Desktop.
require 'open-uri'
class YamlFixtureLoader
def load!(paths)
paths.each do |path|
load_path!(path)
end
end
private
def load_path!(path)
yaml_data = YAML::load_file(path)
CollectionLoader.new(yaml_data).load!
end
class CollectionLoader
def initialize(yaml_data)
@collection = yaml_data.first.second
@model = yaml_data.keys.first.constantize
end
def load!
@collection.each do |item|
ModelLoader.new(item, @model).load!
end
end
end
class ModelLoader
def initialize(data, model, build_from = nil)
@data = data
@model = model
if build_from
@instance = build_from.build
else
@instance = @model.new
end
end
def load!(should_save = true)
load_attributes!
load_translations!
load_attachment!
load_relations!
@instance.save! if should_save
@instance
end
private
def load_attributes!
columns = @model.column_names & @data.keys - ['attachment']
columns.each do |column|
@instance[column] = @data[column]
end
end
def load_translations!
return unless @data.keys.include? 'translations'
valid_keys = @model.translation_class.column_names
@data['translations'].each do |translation|
translation.select! { |key, _| valid_keys.include? key }
@instance.translations << @model.translation_class.new(translation)
end
end
def load_attachment!
return unless @data.keys.include? 'attachment'
path = @data['attachment']
if path =~ /http/
attachment = open(path).read
else
attachment = File.new(Rails.root.join(path))
end
@instance.attachment = attachment
end
def load_relations!
@model.reflect_on_all_associations.each do |reflection|
case reflection.class.to_s
when 'ActiveRecord::Reflection::HasManyReflection'
load_relations_has_many!(reflection)
when 'ActiveRecord::Reflection::BelongsToReflection'
load_relations_belongs_to!(reflection)
when 'ActiveRecord::Reflection::HasOneReflection'
load_relations_has_one!(reflection)
end
end
end
def load_relations_has_many!(reflection)
column = reflection.plural_name
return unless @data.keys.include? column
@data[column].each do |related_item|
model = ModelLoader.new(related_item,
reflection.class_name.constantize,
eval("@instance.#{column}")).load!(false)
eval("@instance.#{column} << model")
end
end
def load_relations_belongs_to!(reflection)
column = reflection.name.to_s
return unless @data.keys.include? column
eval("@instance.#{column} = reflection.class_name.constantize.find_by(@data[column])")
end
def load_relations_has_one!(reflection)
column = reflection.name.to_s
return unless @data.keys.include? column
eval("@instance.#{column} = ModelLoader.new(@data[column], reflection.class_name.constantize).load!(false)")
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment