Ecto 2.2.0-rc.0 released

See the release notes: https://github.com/elixir-ecto/ecto/releases/tag/2.2.0-rc.0

To try it in your projects: {:ecto, "~> 2.2.0-rc", override: true}.

14 Likes

Hah, I was just typing up a post!

My post was:

Just wanted to note that an awesome feature has been added to Ecto 2.2.0-rc.0 that was just released. select_merge (and select(blah, merge(bloop)).

This is a feature that has been wanted a few times here and so just want to point it out (I’ll be rewriting and simplifying a lot of my complex queries soon!). :slight_smile:

See the docs for it at: https://hexdocs.pm/ecto/2.2.0-rc.0/Ecto.Query.html#select_merge/3

2 Likes

Also, is it just me or are the docs showing “Toggle Sidebar” floating on the top sidebar button? It looks like the sr-only css is missing…

Do a hard refresh on the docs page. :slight_smile: And I would love some feedback on the select_merge feature.

1 Like

Hmm, just did. Also told chrome to ignore the cache and fetch on every request and it still is not getting a css where .sr-only exists. it is currently requesting https://hexdocs.pm/ecto/2.2.0-rc.0/dist/app-091c05798a.css if that helps.

Initially it looks awesome! It will so very much simplify a lot of my complex monstrous builders to this old Oracle horror, plus I can return less data in many areas now too instead of dummy data! :slight_smile:

Also, have you thought about supporting this syntax for merging selects? It seems much more readable to me (select_merge can get lost in the keyword lists in my eyes now that I’m using it and merge seems foreign):

query = from p in Post, select: %{}

query =
  if include_title? do
    from p in query, select: %{p | title: p.title}
  else
    query
  end

query =
  if include_visits? do
    from p in query, select: %{p | visits: p.visits}
  else
    query
  end
1 Like

Yayyyy - Having on_conflict support a constraint name is going to replace a bunch of manual upserting in my codebase, and being about to use associations with put_change is also excellent.

Thank you :tada:

1 Like

I love this change the most:

Ecto now will also warn at compile time of invalid relationships, such as a belongs_to that points to a schema that does not exist.

Thanks for the hard work!

3 Likes

It’s fixed now, probably just had to propagate through the cloudflare CDN or so. ^.^

[Ecto.Migration] Add reversible execute/2 to migrations

Blew my mind. Is Ecto able to automatically determine if the arbitrary SQL is reversible? Or does it just skip that execution on rollback?

Edit: nevermind. I see that it is execute/2, the second argument is what you execute on rollback. Makes sense.

3 Likes

while you are rewriting already will you please mention here? one of use case as well? that how and where it helped you?

type/2 in select is great.

One use case came up that is still a bit awkward: converting a sum(x) into a Money.Ecto.Type:
The workaround I found was to wrap it in a subquery:

from account_balance in subquery(
  from t in Transaction,
  group_by: [t.account_id],
  select: %{account_id: t.account_id, balance: sum(t.amount)})
select %{account_id: account_balance.account_id, balance: type(account_balance.balance, Money.Ecto.Type)}

If the subquery layer could be removed it would be amazing!

1 Like

@mbuhot please open up an issue, we can easily support aggregates inside type/2 as well.

2 Likes

I build some utterly massive queries to get information from an old Oracle database. If I were to return everything then it would be beyond huge (it has hundreds of columns in some cases), so I return data massaged into a better format (getting some information like ethnicity involves querying 5 tables, or 6 depending on the detail wanted), however some information is only available depending on what was passed in, and the sheer combination of options that can be passed in would be thousands large if I were to make a custom query for each combination of input and return information, so instead I’ve been building information to generate a select as it ramps down the whole line of things, changing it from thousands of total combinations to the 9 or so from the inputs and just branch based on their combinations for specific shared outputs. This means that I can reduce it to a linear set of code instead of my prior N*M combinations, thus making it substantially easier to read and follow.

I’ve not rewritten any of the older ones yet, they are a bit of a many-many-screen horrors each, but sometime… >.>
(I don’t want to break them, they are brittle, this will reduce a lot of the brittleness though once I do it.)

Thanks @josevalim, #2163 opened.

Related, but slightly different is when a schema declares a virtual field that is populated in a query:

  schema "accounts" do
    field :name, :string
    field :balance, Money.Ecto.Type, virtual: true
    has_many :transactions, Transaction
    timestamps()
  end

accounts_with_balance = Repo.all(from a in Account, select: %{a | balance: 123})

The current behaviour doesn’t load the value through the declared custom type.
Would you be open to automatically casting the virtual field to the type declared in the schema?

1 Like

Please open up an issue as well.

1 Like