Skip to content
This repository has been archived by the owner on Jun 11, 2023. It is now read-only.

Commit

Permalink
Improvements on Hector
Browse files Browse the repository at this point in the history
  • Loading branch information
renatomassaro committed Oct 13, 2017
1 parent 907e330 commit b7bf1a8
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 15 deletions.
55 changes: 46 additions & 9 deletions lib/hell/hell/hector.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule HELL.Hector do
defmodule Hector do
@moduledoc """
Hector is a helper to:
Expand Down Expand Up @@ -217,6 +217,22 @@ defmodule HELL.Hector do
result
end

defp format_str(sql) do
sql
|> String.replace("\n", " ") # Remove newlines
|> remove_extra_spaces()
end

defp remove_extra_spaces(sql) do
if String.contains?(sql, " ") do
sql
|> String.replace(" ", " ")
|> remove_extra_spaces()
else
sql
end
end

@spec query(String.t, [term], term) ::
{:ok, query :: String.t}
| {:error, reason :: term}
Expand All @@ -228,6 +244,7 @@ defmodule HELL.Hector do
def query(sql, params, caster \\ &std_caster/2) do
{first, splits} =
sql
|> format_str()
|> String.split("##")
|> List.pop_at(0)

Expand Down Expand Up @@ -273,6 +290,11 @@ defmodule HELL.Hector do
end
end

def query!(sql, params, caster \\ &std_caster/2) do
{:ok, query} = query(sql, params, caster)
query
end

@doc """
Hector default caster. It simply, naively and blindly ensures the given
value is a string. This does not protect you against potential attacks. Read
Expand Down Expand Up @@ -300,7 +322,11 @@ defmodule HELL.Hector do
columns = atomize_columns(result.columns)

Enum.map(result.rows, fn row ->
apply(repo, :load, [module, {columns, row}])
if :erlang.function_exported(module, :hector_loader, 2) do
apply(module, :hector_loader, [repo, {columns, row}])
else
apply(repo, :load, [module, {columns, row}])
end
end)
end

Expand Down Expand Up @@ -336,17 +362,28 @@ defmodule HELL.Hector do
end

defp get_type(type) do

next_parens = Enum.find_index(type, &(&1 == List.first(')')))
next_space = Enum.find_index(type, &(&1 == List.first(' ')))

cond do
next_parens != nil ->
Enum.split(type, next_parens)
next_space != nil ->
Enum.split(type, next_space)
true ->
next_split =
if is_integer(next_parens) and is_integer(next_space) do
Enum.min([next_parens] ++ [next_space])
else
cond do
next_parens ->
next_parens
next_space ->
next_space
true ->
:norest
end
end

case next_split do
:norest ->
{type, :norest}
split_index ->
Enum.split(type, split_index)
end
end
end
26 changes: 26 additions & 0 deletions lib/hell/hell/hector_caster.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
defmodule HELL.Hector do

alias HELL.Utils
alias Helix.Server.Model.Server

def caster(type, value) do
case type do
:server_id ->
cast(Server.ID, value)
_ ->
has_id? = Utils.atom_contains?(value, "_id")

if has_id? do
raise "Unhandled id of type #{inspect type} for #{inspect value}"
else
Hector.std_caster(type, value)
end
end
end

def cast(module, value) do
with {:ok, _} <- apply(module, :cast, [value]) do
to_string(value)
end
end
end
6 changes: 6 additions & 0 deletions lib/hell/hell/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,10 @@ defmodule HELL.Utils do
"""
def concat(a, b) when is_binary(a) and is_binary(b),
do: a <> b

def atom_contains?(a, value) when is_atom(a) do
a
|> Atom.to_string()
|> String.contains?(value)
end
end
33 changes: 27 additions & 6 deletions test/hell/hector_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ defmodule HectorTest do

use Helix.Test.Case.Integration

alias HELL.Hector

alias Hector
alias Helix.Network.Repo, as: NetworkRepo
alias Helix.Server.Model.Server
alias Helix.Software.Model.File
Expand Down Expand Up @@ -92,8 +91,13 @@ defmodule HectorTest do
assert entry.path == file.path
assert entry.inserted_at == file.inserted_at

# Except for the the associations...
refute entry.modules == file.modules
# The File association were loaded because the File schema has the method
# `hector_loader`.
assert entry.modules == file.modules

# But other associations, which are not handled by `hector_loader`, were
# not loaded
assert %Ecto.Association.NotLoaded{} = entry.storage
end

test "with simple loader (2)" do
Expand Down Expand Up @@ -318,11 +322,28 @@ defmodule HectorTest do
assert q3 == r3
assert q4 == r4
assert q5 == r5
assert q6 == r6
assert q7 == r7
assert q6 == format_sql(r6)
assert q7 == format_sql(r7)
assert q8 == r8
assert q9 == r9
assert q10 == r10
end

# Removes unnecessary spaces and line breaks. "trim on asteroids"
defp format_sql(sql) do
sql
|> String.replace("\n", " ")
|> remove_extra_spaces()
end

defp remove_extra_spaces(sql) do
if String.contains?(sql, " ") do
sql
|> String.replace(" ", " ")
|> remove_extra_spaces()
else
sql
end
end
end
end

0 comments on commit b7bf1a8

Please sign in to comment.