@michalmuskala Warszawa, 9.06.2016 Ecto.Schema defmodule Weather do use Ecto.Schema schema "weather" do belongs_to :city, City field :wdate, Ecto.Date field :temp_lo, :integer field :temp_hi, :integer field :prcp, :float, default: 0.0 timestamps end end
@michalmuskala Warszawa, 9.06.2016 Ecto.Schema declares fields - no SELECT * FROM foos allows for custom types thin wrapper around Elixir’s structs defines data - not behaviour
@michalmuskala Warszawa, 9.06.2016 Ecto.Query from w in Weather, where: w.prcp <= 0.0 or is_nil(w.prcp), select: w from s in Search, where: ilike(fragment("?::text", s.name), ^name_search_term) or fragment("to_tsvector(?) @@ to_tsquery(?)", s.description, ^term)
@michalmuskala Warszawa, 9.06.2016 Ecto.Query from p in Post, where: fragment(position: ["$geoWithin": [...]]) def all(filter) do filter.q |> sanitize |> search |> preload(:location) |> order_by([s] asc: s.date, desc: s.type) end
@michalmuskala Warszawa, 9.06.2016 Ecto.Query defmacrop geo_search(coordinates, geo_point, radius) do quote do fragment("ST_DWithin(?, ?, ?)", unquote(coordinates), unquote(geo_point), unquote(radius) ) end end
@michalmuskala Warszawa, 9.06.2016 Ecto.Query query = from p in Post, select: [:visits], order_by: [desc: :visits], limit: 10 TestRepo.all(from p in subquery(query), select: avg(p.visits))
@michalmuskala Warszawa, 9.06.2016 Ecto.Query Two syntaxes - keyword and pipeline No lazy-loading, explicit preloads Easily extensible via fragments and macros Translated by adapter Composable
@michalmuskala Warszawa, 9.06.2016 Ecto.Changeset Encodes data changes as a data structure No validations are global Multiple changieret functions for different circumstances Easily extensible with functions
@michalmuskala Warszawa, 9.06.2016 Ecto.Multi Encodes transaction as a data structure Changesets for transactions You can test your transaction without database!
@michalmuskala Warszawa, 9.06.2016 Schema less queries from u in "users", join: a in "activities", on: a.user_id == u.id, where: a.start_at > type(^start_at, Ecto.DateTime) and a.end_at < type(^end_at, Ecto.DateTime), group_by: a.user_id, select: %{user_id: a.user_id, interval: a.start_at - a.end_at, count: count(u.id)}
@michalmuskala Warszawa, 9.06.2016 Schema less queries # insert data [%{id: id}] = MyApp.Repo.insert_all("posts", [[title: "hello"]], returning: [:id]) # use query for updates post = from p in "posts", where: p.id == ^id {1, _} = MyApp.Repo.update_all(post, set: [title: "new title"]) # and deletes {1, _} = MyApp.Repo.delete_all post
@michalmuskala Warszawa, 9.06.2016 Table less schemas defmoudule RegistrationSchema do use Ecto.Schema schema "" do field :foo, :string field :bar, :integer embeds_one :resource, Resource end # ... end
@michalmuskala Warszawa, 9.06.2016 Concurrent, transactional tests In 1.1 - database tests sequential, 2.0 - concurrent Works with postgres, mysql has wired transaction semantics Works with Wallaby and Hound
@michalmuskala Warszawa, 9.06.2016 No models, no callbacks Ecto 1.1 deprecated models, embraced schemas, 2.0 removes models Ecto 1.1 deprecated callbacks, 2.0 removed them I’m forbidden by José to use the world “model” Phoenix will switch away from the model nomenclature
@michalmuskala Warszawa, 9.06.2016 KISS Plain CRUD interfaces are easy When you need more power - you have it We want not to force anything on the users, but keep the simplicity
@michalmuskala Warszawa, 9.06.2016 –José Valim “I am completely OK with taking the blame regarding Ecto 1.0. We did push folks to the wrong direction. But Ecto 2.0 no longer puts you in this place[…]. If you are using structs as your domain models, then it will be more on you than on me, since you have everything to stop doing that[…].”