Last active
February 4, 2016 16:55
-
-
Save paulcsmith/b7ad3f40b20e1fd15cc1 to your computer and use it in GitHub Desktop.
Building queries using plain functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def index(conn, params) do | |
Post | |
|> filter_upcoming(params) | |
|> filter_attributes(params, whitelist: ~w(title body) | |
|> filter_timespan(params) | |
# Or simplify it if it's used in multiple controllers | |
Post |> filter_post_params(params) | |
end | |
def filter_post_params(query, params) do | |
query | |
|> filter_upcoming(params) | |
|> filter_attributes(params, whitelist: ~w(title body) | |
|> filter_timespan(params) | |
end | |
def filter_upcoming(query, %{"upcoming" => "true") do | |
from row in query, where: row.publish_at > Ecto.DateTime.utc | |
end | |
def filter_upcoming(query, _params), do: query | |
def filter_timespan(query, %{"start_time" => start_time, "end_time" => end_time}) do | |
# You'll need to cast the times somehow. Probably with Ecto.DateTime.cast! | |
from row in query, | |
where: row.published_at > cast(start_time), | |
where: row.published_at < cast(end_time) | |
end | |
def filter_dates(query, _params), do: query | |
def filter_attributes(query, params, whitelist: whitelist) do | |
params = Map.take(params, whitelist) | |
Enum.reduce params, query, fn({attr, value}, query) -> | |
from row in query, where: field(row, ^String.to_atom(attr)) == ^value | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The good thing about using regular function is that you can easily use just some of these if you want to use them in different controllers. You can also use the same function for different models if they have similar functionality (like a Post and a Tweet that both have a
published_at
field)