Upgrade to Pro — share decks privately, control downloads, hide ads and more …

What's New In Ecto 3

Wu Qing
March 06, 2019

What's New In Ecto 3

Talked about what's new in Ecto 3, with the perspective of how to upgrade from Ecto 2 to Ecto 3 for an existing app
Presented at March 2019 meetup of Elixir Sydney
https://www.meetup.com/sydney-ex/events/kznqrpyzfbjb/

Wu Qing

March 06, 2019
Tweet

More Decks by Wu Qing

Other Decks in Programming

Transcript

  1. Background » Ecto 3.0.0 released in Oct 2018 (latest 3.0.7

    as of March 2019) » We upgraded to Ecto 3 in Jan 2019
  2. Overview » Split Ecto into ecto and ecto_sql » Configuration

    changes » JSON handling changes » Added named bindings for better join composition » DateTime related changes » Instrumentation for Prometheus » Other changes ...
  3. Split Ecto into ecto and ecto_sql How to update deps()

    function in mix.exs: » with database: remove :ecto; add {:ecto_sql, "~> 3.0"} » without database: just update :ecto to ~> 3.0
  4. Configuration changes # Ecto 2, in config.ex config :my_app, MyApp.Repo,

    - adapter: Ecto.Adapters.Postgres, url: System.get_env("DATABASE_URL"), pool_size: 10, - loggers: [MyApp.Repo.Instrumenter, Ecto.LogEntry] # Ecto 3 in repo.ex defmodule MyApp.Repo do use Ecto.Repo, otp_app: :my_app, adapter: Ecto.Adapters.Postgres . . end
  5. JSON handling » Management of JSON library moved to adapters.

    » JSON library in all adapters default to Jason.
  6. JSON example # Use Poison For Postgres # Ecto 2

    config :ecto, :json_library, Poison # Ecto 3 config :postgrex, :json_library, Poison
  7. Added named bindings for better join composition » Ecto 2:

    bindings in join queries are positional » Ecto 3: bindings can be optionally named
  8. Ecto 2 example query = from p in Post, join:

    c in Comment, on: p.id == c.post_id from [p, c] in query, where: c.public
  9. Ecto 3 example query = from p in Post, +

    as: :posts, join: c in Comment, + as: :comments, on: p.id == c.post_id, select: c from [comments: c] in query, where: c.public from [posts: p] in query, where: p.published
  10. Ecto.Query.join/5 changes » Ecto.Query.join/5 accepts keyword list as fifth argument

    #Ecto 2 join(Post, :inner, [p], c in Comment, p.id == c.post_id) #Ecto 3 join(Post, :inner, [p], c in Comment, on: p.id == c.post_id)
  11. DateTime related changes Deprecated types removed » Ecto.Date, Ecto.Time and

    Ecto.DateTime removed » use Date, Time, DateTime and NaiveDateTime instead
  12. DateTime related changes Drop support for microseconds by default »

    Ecto will raise when inserting timestamp field with microseconds » truncate to remove microseconds part DateTime.truncate(dt, :second) NaiveDateTime.truncate(dt, :second)
  13. DateTime related changes Want support for microseconds? # configure for

    repository: config :my_app, MyApp.Repo, migration_timestamps: [type: :naive_datetime_usec] # then in schema: @timestamps_opts [type: :naive_datetime_usec]
  14. DateTime related changes default for timestamps updated to :naive_datetime Want

    to use :utc_datetime instead? # in schema schema "projects" do field(:str_field, :string) . . timestamps(type: :utc_datetime) end
  15. Instrumentation for Prometheus in Ecto 3 # create Instrumenter module

    defmodule MyApp.Repo.Instrumenter do use Prometheus.EctoInstrumenter end
  16. # in repo.ex defmodule MyApp.Repo do ... def init(_, opts)

    do MyApp.Repo.Instrumenter.setup() :telemetry.attach( "prometheus-ecto-myapp", [:my_app, :repo, :query], &MyApp.Repo.Instrumenter.handle_event/4, %{} ) {:ok, opts} end end
  17. Connection instrumentation for Prometheus » Ecto 2 connection pool provided

    by :poolboy library » We created ConnectionInstrumenter modules to get connection info from :poolboy
  18. Connection instrumentation for Prometheus » Ecto 3 depends on DBConnection

    2 » DBConnection 2 added ConnectionPool module to manage connection pool » Dropped support for external pools » The built-in connection pool does not offer API for getting connection info
  19. %Ecto.Query{} struct updated #Ecto 2 defp resolve_query( %{from: {_source, schema}}

    = query ) do ... #Ecto 3 defp resolve_query( %Ecto.Query{from: %Ecto.Query.FromExpr{source: {_, schema}}} = query ) do ...
  20. more strict when :source option exists for a field »

    In Ecto.Query.select/3, Ecto 3 requires you to use the field name defined in schema when source: :orignal presents for that field
  21. Example in Ecto 2 # in Project schema schema "projects"

    do ... field(:title, :string, source: :description) ... end select(Project, [p], %{ id: p.id, description: p.description }
  22. Example in Ecto 3 # in Project schema schema "projects"

    do ... field(:title, :string, source: :description) ... end select(Project, [p], %{ id: p.id, description: p.title }
  23. What I learned » Try not to rely on internal

    implementation of a library » Unexpected things happen
  24. References » A sneak peek at Ecto 3.0 http://bit.do/peek-ecto »

    Ecto Changelog https://github.com/elixir-ecto/ecto/blob/ master/CHANGELOG.md