Current section
Files
Jump to
Current section
Files
lib/fixturist.ex
if Mix.env == :test do
defmodule DevRepo do
use Ecto.Repo, otp_app: Mix.Project.config[:app]
end
defmodule Fixturist do
import Ecto.Query
def serialize(resource) do
relationships = resource.__struct__.__schema__(:associations)
Map.drop(resource, [:__meta__, :__struct__] ++ relationships)
end
def start_dev_repo do
DevRepo.start_link
end
def insert_all(model, array) do
belongs_to_relationships = find_belongs_to_relationships(model)
operation_list = form_operation_list(model, array, []) |> order_operation_list
Repo.transaction(fn ->
operation_list |> Enum.each(fn(operation) ->
struct_array = operation |> elem(1) |> Enum.map(fn(x) ->
serialize(x)
end)
Repo.insert_all(operation |> elem(0), struct_array, returning: true)
end)
array_data = array |> Enum.map(fn(record) ->
# NOTE: this shouldnt be very good what about twoWordRelationship attr?
# this should probably be cast/3 instead of serialize
record |> Map.put_new(:__struct__, model) |> serialize()
end)
Repo.insert_all(model, array_data, returning: true)
end)
end
def insert!(model, map) do
belongs_to_relationships = find_belongs_to_relationships(model)
operation_list = form_operation_list(model, [map], []) |> order_operation_list
Repo.transaction(fn ->
operation_list |> Enum.each(fn(operation) ->
struct_array = operation |> elem(1) |> Enum.map(fn(x) ->
serialize(x)
end)
Repo.insert_all(operation |> elem(0), struct_array, returning: true)
end)
ecto_map = map |> Map.put_new(:__struct__, model) |> serialize()
struct(model, map) |> Repo.insert!
end)
end
def order_operation_list(operation_list) do
score_list = operation_list |> Enum.map(fn(operation) ->
operation_model = operation |> elem(0)
{
operation_model,
operation |> elem(1),
find_belongs_to_relationships(operation_model) |> length
}
end) |> Enum.sort_by(fn(x) -> x |> elem(2) end)
end
def merge_new_operations_to_operation_list(new_list, operation_list) do
new_list |> Enum.reduce(operation_list, fn(list_tuple, accum) ->
reference_in_operation_list = operation_list |> Enum.find(fn(operation_list_tuple) ->
(operation_list_tuple |> elem(0)) == (list_tuple |> elem(0))
end)
case reference_in_operation_list do
nil -> [list_tuple | accum]
reference_in_operation_list ->
values = (
(reference_in_operation_list |> elem(1)) ++ (list_tuple |> elem(1))
) |> Enum.uniq
reference_model_key = reference_in_operation_list |> elem(0)
reference_index = Enum.find_index(operation_list, fn(operation) ->
operation |> elem(0) == reference_model_key
end)
List.replace_at(operation_list, reference_index, {reference_model_key, values})
end
end)
end
def form_operation_list(model, [], operation_list), do: operation_list
def form_operation_list(model, records_to_dissect, prior_operation_list) do
belongs_to_relationships = find_belongs_to_relationships(model)
belongs_to_relationships |> Enum.reduce(prior_operation_list, fn(relationship, accum) ->
relationship_model = get_relationship_model(model, relationship)
record_ids = records_to_dissect |> Enum.map(fn(x) ->
relationship_field = belongs_to_relationship_to_field(relationship)
x |> Map.get(relationship_field)
end) |> Enum.uniq
records_found = from(
record in relationship_model,
select: record,
where: record.id in ^record_ids
) |> DevRepo.all
case records_found do
[] -> accum
records_found ->
relationship_tuple = [{relationship_model, records_found}]
new_list = merge_new_operations_to_operation_list(relationship_tuple, accum)
form_operation_list(relationship_model, records_found, new_list)
end
end)
end
def find_belongs_to_relationship_fields(model) do
find_belongs_to_relationships(model) |> Enum.map(fn(relationship) ->
belongs_to_relationship_to_field(relationship)
end)
end
def belongs_to_relationship_to_field(relationship) do
field = (relationship |> Atom.to_string) <> "_id" |> String.to_atom
end
def find_belongs_to_relationships(model) do
model.__schema__(:fields) |> Enum.reduce([], fn(field, acc) ->
possible_relation = field |> Atom.to_string |> String.slice(0..-4) |> String.to_atom
case model.__schema__(:associations) |> Enum.member?(possible_relation) do
true -> acc ++ [possible_relation]
false -> acc
end
end)
end
def get_relationship_model(model, relationship) do
model.__schema__(:association, relationship).queryable
end
end
end