Skip to content

Commit

Permalink
Merge b9f6c94 into 9cdf956
Browse files Browse the repository at this point in the history
  • Loading branch information
thebugcatcher committed Jan 11, 2019
2 parents 9cdf956 + b9f6c94 commit d6c3af9
Show file tree
Hide file tree
Showing 12 changed files with 52 additions and 41 deletions.
1 change: 0 additions & 1 deletion config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ config :rummage_ecto, Rummage.Ecto,
config :rummage_ecto, ecto_repos: [Rummage.Ecto.Repo]

config :rummage_ecto, Rummage.Ecto.Repo,
adapter: Ecto.Adapters.Postgres,
username: System.get_env("POSTGRES_USER"),
password: System.get_env("POSTGRES_PASSWORD"),
database: "rummage_ecto_test",
Expand Down
17 changes: 9 additions & 8 deletions lib/rummage_ecto.ex
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ defmodule Rummage.Ecto do
iex> opts = [paginate: Rummage.Ecto.Hook.Paginate, repo: repo]
iex> {queryable, rummage} = rummage(Product, rummage, opts)
iex> rummage
%{paginate: %{max_page: 0, page: 1, per_page: 10, total_count: 0}}
%{paginate: %{max_page: 1, page: 1, per_page: 10, total_count: 0}}
iex> queryable
#Ecto.Query<from p in Rummage.Ecto.Product, limit: ^10, offset: ^0>
Expand Down Expand Up @@ -157,10 +157,11 @@ defmodule Rummage.Ecto do
sort: Keyword.get(opts, :sort, RConfig.sort()),
paginate: Keyword.get(opts, :paginate, RConfig.paginate())]

rummage =
Enum.reduce(hooks, rummage, &format_hook_params(&1, &2, queryable, opts))

{Enum.reduce(hooks, queryable, &run_hook(&1, &2, rummage)), rummage}
Enum.reduce(hooks, {queryable, rummage}, fn(hook, {queryable, rummage}) ->
rummage = format_hook_params(hook, rummage, queryable, opts)
queryable = run_hook(hook, queryable, rummage)
{queryable, rummage}
end)
end

defp format_hook_params({_, nil}, rummage, _, _), do: rummage
Expand Down Expand Up @@ -229,14 +230,14 @@ defmodule Rummage.Ecto do
alias Rummage.Ecto.Config, as: RConfig

def rummage(rummage, opts \\ []) do
Rummage.Ecto.rummage(__MODULE__, rummage, uniq_merge(opts, defaults()))
Rummage.Ecto.rummage(__MODULE__, rummage, uniq_merge(opts, __rummage_defaults__()))
end

def rummageq(queryable, rummage, opts \\ []) do
Rummage.Ecto.rummage(queryable, rummage, uniq_merge(opts, defaults()))
Rummage.Ecto.rummage(queryable, rummage, uniq_merge(opts, __rummage_defaults__()))
end

defp defaults() do
def __rummage_defaults__ do
keys = ~w{repo per_page search sort paginate}a
Enum.map(keys, &get_defs/1)
end
Expand Down
3 changes: 3 additions & 0 deletions lib/rummage_ecto/hook.ex
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,7 @@ defmodule Rummage.Ecto.Hook do
def get_module({_, module}) when is_atom(module), do: module
def get_module(%Ecto.Query{from: _from} = query), do: get_module(query.from)
def get_module(%Ecto.SubQuery{query: query}), do: get_module(query)
if Code.ensure_compiled?(Ecto.Query.FromExpr) do
def get_module(%Ecto.Query.FromExpr{source: source}), do: get_module(source)
end
end
12 changes: 6 additions & 6 deletions lib/rummage_ecto/hooks/custom_sort.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ defmodule Rummage.Ecto.Hook.CustomSort do

# Helper function which handles addition of paginated query on top of
# the sent queryable variable
defp handle_sort(queryable, {field, order}) do
defp handle_sort(queryable, %{scope: scope, order: order}) do
module = get_module(queryable)
name = :"__rummage_custom_sort_#{field}"
name = :"__rummage_custom_sort_#{scope}"

case function_exported?(module, name, 1) do
true -> apply(module, name, [{queryable, order}])
_ -> "No scope `#{field}` of type custom_sort defined in #{module}"
_ -> "No scope `#{scope}` of type custom_sort defined in #{module}"
end
end

Expand All @@ -34,8 +34,8 @@ defmodule Rummage.Ecto.Hook.CustomSort do
iex> Sort.format_params(Parent, %{}, [])
%{assoc: [], order: :asc}
"""
@spec format_params(Ecto.Query.t(), map() | tuple(), keyword()) :: map()
def format_params(queryable, {sort_scope, order}, opts) do
@spec format_params(Ecto.Query.t(), map(), keyword()) :: map()
def format_params(queryable, %{scope: sort_scope, order: order}, opts) do
module = get_module(queryable)
name = :"__rummage_sort_#{sort_scope}"

Expand All @@ -44,7 +44,7 @@ defmodule Rummage.Ecto.Hook.CustomSort do
format_params(queryable, sort_params, opts)
_ ->
case function_exported?(module, :"__rummage_custom_sort_#{sort_scope}", 1) do
true -> {sort_scope, order}
true -> %{scope: sort_scope, order: order}
_ -> raise "No scope `#{sort_scope}` of type custom_sort defined in the #{module}"
end
end
Expand Down
8 changes: 6 additions & 2 deletions lib/rummage_ecto/hooks/paginate.ex
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ defmodule Rummage.Ecto.Hook.Paginate do
iex> alias Rummage.Ecto.Category
iex> Ecto.Adapters.SQL.Sandbox.checkout(Rummage.Ecto.Repo)
iex> Paginate.format_params(Category, %{}, [repo: Rummage.Ecto.Repo])
%{max_page: 0, page: 1, per_page: 10, total_count: 0}
%{max_page: 1, page: 1, per_page: 10, total_count: 0}
When `paginate_params` and `opts` given are valid:
Expand All @@ -230,7 +230,7 @@ defmodule Rummage.Ecto.Hook.Paginate do
iex> repo = Rummage.Ecto.Repo
iex> Ecto.Adapters.SQL.Sandbox.checkout(repo)
iex> Paginate.format_params(Category, paginate_params, [repo: repo])
%{max_page: 0, page: 1, per_page: 1, total_count: 0}
%{max_page: 1, page: 1, per_page: 1, total_count: 0}
When `paginate_params` and `opts` given are valid:
Expand Down Expand Up @@ -351,6 +351,7 @@ defmodule Rummage.Ecto.Hook.Paginate do
|> (& &1 / per_page).()
|> Float.ceil()
|> trunc()
max_page = max_page == 0 && 1 || max_page

%{page: Map.get(paginate_params, :page),
per_page: per_page, total_count: total_count, max_page: max_page}
Expand All @@ -377,6 +378,7 @@ defmodule Rummage.Ecto.Hook.Paginate do
|> apply(:all, [distinct(query, :true)])
|> Enum.count()
end

defp get_count(query, repo, pk) do
query = select(query, [s], count(field(s, ^pk), :distinct))
hd(apply(repo, :all, [query]))
Expand All @@ -397,6 +399,8 @@ defmodule Rummage.Ecto.Hook.Paginate do
case queryable do
%{from: %{query: subquery}} -> schema_from_query(subquery)
%{from: {_, schema}} -> schema
%{from: %{source: {_, schema}}} -> schema
%{from: %{source: %{query: subquery}}} -> schema_from_query(subquery)
_ -> queryable
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/rummage_ecto/hooks/sort.ex
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,8 @@ defmodule Rummage.Ecto.Hook.Sort do
iex> Sort.format_params(Parent, %{}, [])
%{assoc: [], order: :asc}
"""
@spec format_params(Ecto.Query.t(), map() | tuple(), keyword()) :: map()
def format_params(queryable, {sort_scope, order}, opts) do
@spec format_params(Ecto.Query.t(), map(), keyword()) :: map()
def format_params(queryable, %{scope: sort_scope, order: order}, opts) do
module = get_module(queryable)
name = :"__rummage_sort_#{sort_scope}"
sort_params = case function_exported?(module, name, 1) do
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ defmodule Rummage.Ecto.Mixfile do
defp deps do
[
# Development Dependency
{:ecto, "~> 2.2"},
{:ecto_sql, "~> 2.2 or ~> 3.0"},

# Other Dependencies
{:credo, "~> 0.9.1", only: [:dev, :test], runtime: false},
Expand Down
10 changes: 6 additions & 4 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
"certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], [], "hexpm"},
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
"credo": {:hex, :credo, "0.9.2", "841d316612f568beb22ba310d816353dddf31c2d94aa488ae5a27bb53760d0bf", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:poison, ">= 0.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
"db_connection": {:hex, :db_connection, "1.1.3", "89b30ca1ef0a3b469b1c779579590688561d586694a3ce8792985d4d7e575a61", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
"decimal": {:hex, :decimal, "1.5.0", "b0433a36d0e2430e3d50291b1c65f53c37d56f83665b43d79963684865beab68", [:mix], [], "hexpm"},
"db_connection": {:hex, :db_connection, "2.0.2", "440c05518b0bdca0469dafaf45403597430448c1281def14ef9ccaa41833ea1e", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"},
"decimal": {:hex, :decimal, "1.6.0", "bfd84d90ff966e1f5d4370bdd3943432d8f65f07d3bab48001aebd7030590dcc", [:mix], [], "hexpm"},
"earmark": {:hex, :earmark, "1.2.4", "99b637c62a4d65a20a9fb674b8cffb8baa771c04605a80c911c4418c69b75439", [:mix], [], "hexpm"},
"ecto": {:hex, :ecto, "2.2.10", "e7366dc82f48f8dd78fcbf3ab50985ceeb11cb3dc93435147c6e13f2cda0992e", [:mix], [{:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
"ecto": {:hex, :ecto, "3.0.3", "018a3df0956636f84eb3033d807485a7d3dea8474f47b90da5cb8073444c4384", [:mix], [{:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm"},
"ecto_sql": {:hex, :ecto_sql, "3.0.2", "0e04cbc183b91ea0085c502226befcd237a4ac31c204fd4be8d4db6676b5f10d", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.0.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.9.1", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.14.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.2.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
"esqlite": {:hex, :esqlite, "0.2.3", "1a8b60877fdd3d50a8a84b342db04032c0231cc27ecff4ddd0d934485d4c0cd5", [], [], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.18.1", "37c69d2ef62f24928c1f4fdc7c724ea04aecfdf500c4329185f8e3649c915baf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"},
"excoveralls": {:hex, :excoveralls, "0.8.0", "99d2691d3edf8612f128be3f9869c4d44b91c67cec92186ce49470ae7a7404cf", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
Expand All @@ -19,10 +20,11 @@
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
"poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], [], "hexpm"},
"postgrex": {:hex, :postgrex, "0.13.5", "3d931aba29363e1443da167a4b12f06dcd171103c424de15e5f3fc2ba3e6d9c5", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"},
"postgrex": {:hex, :postgrex, "0.14.0", "f3d6ffea1ca8a156e0633900a5338a3d17b00435227726baed8982718232b694", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
"sbroker": {:hex, :sbroker, "1.0.0", "28ff1b5e58887c5098539f236307b36fe1d3edaa2acff9d6a3d17c2dcafebbd0", [], [], "hexpm"},
"sqlite_ecto2": {:hex, :sqlite_ecto2, "2.2.2", "7a3e5c0521e1cb6e30a4907ba4d952b97db9b2ab5d1a4806ceeb66a10b23ba65", [], [{:connection, "~> 1.0.3", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 1.1.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 2.2.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:esqlite, "~> 0.2.3", [hex: :esqlite, repo: "hexpm", optional: false]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: false]}, {:sqlitex, "~> 1.3.2 or ~> 1.4", [hex: :sqlitex, repo: "hexpm", optional: false]}], "hexpm"},
"sqlitex": {:hex, :sqlitex, "1.3.3", "3aac5fd702be346f71d9de6e01702c9954484cd0971aa443490bb3bde045d919", [], [{:decimal, "~> 1.1", [hex: :decimal, repo: "hexpm", optional: false]}, {:esqlite, "~> 0.2.3", [hex: :esqlite, repo: "hexpm", optional: false]}], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
"telemetry": {:hex, :telemetry, "0.2.0", "5b40caa3efe4deb30fb12d7cd8ed4f556f6d6bd15c374c2366772161311ce377", [:mix], [], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},
}
28 changes: 14 additions & 14 deletions test/rummage_ecto_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ defmodule Rummage.EctoTest do
search: %{price: %{search_type: :lteq, search_term: 10, assoc: [],
search_expr: :where}},
sort: %{field: :name, order: :asc, assoc: []},
paginate: %{per_page: 2, page: 2, max_page: 4, total_count: 8},
paginate: %{per_page: 2, page: 2, max_page: 1, total_count: 2},
}
end

Expand Down Expand Up @@ -263,7 +263,7 @@ defmodule Rummage.EctoTest do
search: %{name: %{assoc: [inner: :category], search_term: "1",
search_type: :like, search_expr: :where}},
sort: %{field: :name, order: :asc, assoc: [inner: :category]},
paginate: %{per_page: 2, page: 1, max_page: 4, total_count: 8}
paginate: %{per_page: 2, page: 1, max_page: 1, total_count: 2}
}
end

Expand Down Expand Up @@ -380,7 +380,7 @@ defmodule Rummage.EctoTest do

rummage = %{search: %{category_name: "Category 1"}}

{queryable, rummage} = Product.rummage(rummage)
{queryable, _rummage} = Product.rummage(rummage)

products = Repo.all(queryable)

Expand All @@ -398,9 +398,9 @@ defmodule Rummage.EctoTest do
test "rummage call with sort scope" do
create_categories_and_products()

rummage = %{sort: {:category_name, :asc}}
rummage = %{sort: %{scope: :category_name, order: :asc}}

{queryable, rummage} = Product.rummage(rummage)
{queryable, _rummage} = Product.rummage(rummage)

products = Repo.all(queryable)

Expand All @@ -413,7 +413,7 @@ defmodule Rummage.EctoTest do
"Product 2->3", "Product 1->3",
"Product 2->4", "Product 1->4"]
)
rummage = %{sort: {:invalid_scope, :asc}}
rummage = %{sort: %{scope: :invalid_scope, order: :asc}}

assert_raise RuntimeError, ~r/No scope `invalid_scope`/, fn ->
Product.rummage(rummage)
Expand All @@ -425,7 +425,7 @@ defmodule Rummage.EctoTest do

rummage = %{paginate: {:category_show, 1}}

{queryable, rummage} = Product.rummage(rummage)
{queryable, _rummage} = Product.rummage(rummage)

products = Repo.all(queryable)

Expand All @@ -446,7 +446,7 @@ defmodule Rummage.EctoTest do

rummage = %{search: %{category_quarter: Float.ceil(Date.utc_today().month / 3)}}

{queryable, rummage} = Product.rummage(rummage)
{queryable, _rummage} = Product.rummage(rummage)

products = Repo.all(queryable)

Expand All @@ -467,9 +467,9 @@ defmodule Rummage.EctoTest do
test "rummage call with custom sort scope" do
create_categories_and_products()

rummage = %{sort: {:category_microseconds, :desc}}
rummage = %{sort: %{scope: :category_microseconds, order: :desc}}

{queryable, rummage} = Product.rummage(rummage)
{queryable, _rummage} = Product.rummage(rummage)

products = Repo.all(queryable)

Expand All @@ -483,7 +483,7 @@ defmodule Rummage.EctoTest do
"Product 2->4", "Product 1->4"]
)

rummage = %{sort: {:category_milliseconds, :desc}}
rummage = %{sort: %{scope: :category_milliseconds, order: :desc}}

assert_raise RuntimeError, ~r/No scope `category_milliseconds`/, fn ->
Product.rummage(rummage)
Expand All @@ -495,7 +495,7 @@ defmodule Rummage.EctoTest do

rummage = %{paginate: {:small_page, 1}}

{queryable, rummage} = Product.rummage(rummage)
{queryable, _rummage} = Product.rummage(rummage)

products = Repo.all(queryable)

Expand All @@ -517,7 +517,7 @@ defmodule Rummage.EctoTest do

rummage = %{search: %{created_at_year: %{search_type: :eq, search_term: Date.utc_today.year}}}

{queryable, rummage} = Product.rummage(rummage)
{queryable, _rummage} = Product.rummage(rummage)

products = Repo.all(queryable)

Expand All @@ -534,7 +534,7 @@ defmodule Rummage.EctoTest do

rummage = %{sort: %{field: :created_at_year, order: :asc}}

{queryable, rummage} = Product.rummage(rummage)
{queryable, _rummage} = Product.rummage(rummage)

products = Repo.all(queryable)

Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions test/support/product.ex
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ defmodule Rummage.Ecto.Product do

rummage_scope :category_quarter, [type: :custom_search], fn({query, term}) ->
query
|> join(:inner, [q], c in Rummage.Ecto.Category, q.category_id == c.id)
|> join(:inner, [q], c in Rummage.Ecto.Category, on: q.category_id == c.id)
|> where([..., c], fragment("date_part('quarter', ?)", c.inserted_at) == ^term)
end

rummage_scope :category_microseconds, [type: :custom_sort], fn({query, order}) ->
query
|> join(:inner, [q], c in Rummage.Ecto.Category, q.category_id == c.id)
|> join(:inner, [q], c in Rummage.Ecto.Category, on: q.category_id == c.id)
|> order_by([..., c], [{^order, fragment("date_part('microseconds', ?)", c.inserted_at)}])
end

Expand Down
4 changes: 3 additions & 1 deletion test/support/repo.ex
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
defmodule Rummage.Ecto.Repo do
use Ecto.Repo, otp_app: :rummage_ecto
use Ecto.Repo,
otp_app: :rummage_ecto,
adapter: Ecto.Adapters.Postgres
end

0 comments on commit d6c3af9

Please sign in to comment.