3 ms·
For everyone complaining about orm-something - take a look at elixir's Ecto. It basically allows writing sql via native code. Good for composability, type casti
by out_of_protocol 7y ago
For everyone complaining about orm-something - take a look at elixir's Ecto. It basically allows writing sql via native code. Good for composability, type casting, stuff like that.
Account
|> where(active: true)
|> join(:left, [a], p in Post, on: p.account_id == a.id)
|> where([a, p], a.foo == "bar" or p.bar == "foo")
|> group_by([a, p], a.id)
|> select(...)
|> limit(10)
...
|> Repo.all()
Plus there are changesets for data validations (can e.g. catch and return uniquness errors via unique index)
P.S. For update/insert queries it doesn't make sense to write UPDATE statement by hand
UPDATE accounts SET ... 50 fields ... WHERE id = 1
P.P.S. changeset example:
def changeset(record, attrs) do
record
|> cast(attrs, [:number, :note])
|> validate_required([:number])
|> validate_format(:number, number_format())
|> unique_constraint(:number, name: "foo_bar_index")
end
will return nice error if number is missing (_before_ running sql query) or already taken (_after_ running a query, on DB error)
- kyllo 7y agoThis is my preferred approach--a fluent, composable query builder API that uses pipes. When I do data analysis with R, this is what I use--same concept: https://dbplyr.tidyverse.org/ https://dbplyr.tidyverse.org/ The somewhat tricky part can be converting the tabular result set into a graph of objects, but I think it's better to handle this in your application code as needed, rather than delegate it to a library.
- kiliancs 7y agoThis is the best solution I've found so far. Bring sql to the language instead of abstracting it. Plus changesets, migrations, etc.
- udfalkso 7y agoCame here to say this. Ecto is solid. Also, the results come back as elixir structs and not bloated objects so it’s much faster than ORMs in many other languages. Additionally, the functional approach makes everything much less magical. Changesets can take a little while to grok, but they work.
- campl3r 7y agoHow is this different from Linq/EntityFramework for C#? Seems pretty similar at first.
- namelosw 7y agoIMO this is the best approach for most scenarios. 9 out of 10 it's lightweight enough and powerful enough. ORMs tries to hide the impedance mismatch, but the underlying paradigm is still relational, which always leads to a leaky abstraction. In contrast, the query builder approach builds DSL to address relational paradigm so that programmer can work with relational paradigm better.
- joshlemer 7y agoWith code snippets like this: |> where([a, p], a.foo == "bar" or p.bar == "foo") are these predicates being pushed down to the data base? How can the code expressions be inspected for optimization? Is it using some kind of macro?