1,260 karma · joined February 3, 2011
Users.all()
|> Enum.filter(&Users.is_expired?(&1, Date.utc_today()))
|> Enum.map(&generate_expiry_email/1)
|> tap(&IO.inspect(label: "Expiry Email"))
|> Enum.reject(&is_nil/1)
|> bulk_send()
The nice thing here is that we can easily log to the console, and also filter out nil expiry emails. In production code, `generate_expiry_email/1` would likely return a Result (a tuple of `{:ok, email}` or `{:error, reason}`), so we could complicate this a bit further and collect the errors to send to a logger, or to update some flag in the db.It just becomes so easy to incrementally add functionality here.
---
Quick syntax reference for anyone reading:
- Pipelines apply the previous result as the first argument of the next function
- The `/1` after a function name indicates the arity, since Elixir supports multiple dispatch
- `&fun/1` expands to `fn arg -> fun(arg) end`
- `&fun(&1, "something")` expands to `fn arg -> fun(arg, "something") end`
There are certainly new compelling projects like Sorbet to add type checking, and the ecosystem itself is very mature, it's just that the average codebase is not going to live up the experience you might have with a brand new one.
.map(g => { return { key: g.key, rows: g.rows.map(r => r[1]) }})
you can write .map(g => ({ key: g.key, rows: g.rows.map(r => r[1]) }))Simple doesn't mean "I should be able to intuitively understand this with under a minute of reading"...
Auth0 is complete overkill if you don't need their advanced features IMO.
[0] https://dev.mysql.com/doc/refman/8.0/en/memory-storage-engin...