read :next_two_days do
now = Timex.now()
start_time = now
end_time = Timex.shift(now, days: +2)
filter expr(start_time >= ^start_time and end_time <= ^end_time)
end
read :last_two_days do
now = Timex.now()
start_time = Timex.shift(now, days: -2)
end_time = now
filter expr(start_time >= ^start_time and end_time <= ^end_time)
end
Can i make a reusable filter ? Or call another action?
EDIT: ignore the fact that this is hard to test given the action is not pure
I feel like the first thing I should point out is that your now, start_time and end_time will be evaluated at compile time and never change at runtime.
You should instead do something like this:
read :next_two_days do
argument :start_time, :datetime, private?: true, default: &Timex.now/0
argument :end_time, :datetime, private?, true, default: fn -> Timex.shift(Timex.now(), days: +2) end
filter expr(start_time >= ^arg(:start_time) and end_time <= ^arg(:end_time))
end
but having said that I think it see a nice easy way to make this reusable:
read :next_two_days do
manual fn _, _, _, _ ->
start_time = Timex.now()
end_time = Timex.shift(start_time, days: +2)
# provided you added the code_interface, or you could construct a new query instead.
__MODULE__.within_datetime_range(%{start_time: start_time, end_time: end_time)
end
end
read :last_two_days do
manual fn _, _, _, _ ->
end_time = Timex.now()
start_time = Timex.shift(end_time, days: -2)
__MODULE__.within_datetime_range(%{start_time: start_time, end_time: end_time)
end
end
read :within_datetime_range do
argument :start_time, :datetime
argument :end_time, :datetime
filter expr(start_time >= ^arg(:start_time) and end_time <= ^arg(:end_time))
end
I would suggest making filters reusable with calculations generally, and in this specific case, use the from_now and ago expressions.
read :next_two_days do
filter expr(in_date_range(datetime: expr(from_now(2, :day))))
end
read :last_two_days do
filter expr(in_date_range(datetime: expr(ago(2, :day))))
end
calculate :in_date_range, :boolean, expr(start_time <= ^arg(:datetime) and end_time >= ^arg(:datetime)) do
private? true
argument :datetime, :datetime, allow_expr?: true # allow_expr allows nested expressions to be provided
end
Another thing to emphasize is that there are tools for regular functional composition. filter in the action, i.e
filter expr(foo == bar)
is a short-hand that in complex cases is often inconvenient compared to using a preparation (the standard way of customizing the query of an action.
For example:
read :next_two_days do
prepare fn query, _ ->
filter_between(query, Timex.shift(Timex.now(), days: 2))
end
end
read :last_two_days do
prepare fn query, _ ->
filter_between(query, Timex.shift(Timex.now(), days: -2))
end
end
defp filter_between(query, datetime) do
Ash.Query.filter(query, start_time <= ^datetime and end_time >= ^datetime)
end