Elixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicit
Elixir and Phoenix
fast, concurrent and explicit
Tobias Pfeiffer
@PragTob
pragtob.info
Elixir and Phoenix
fast, concurrent and explicit
Tobias Pfeiffer
@PragTob
pragtob.info
Elixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicit
defmodule MyMap do
def map([], _func), do: []
def map([head | tail], func) do
[func.(head) | map(tail, func)]
end
end
MyMap.map [1, 2, 3, 4], fn(i) -> i * i end
defmodule MyMap do
def map([], _func), do: []
def map([head | tail], func) do
[func.(head) | map(tail, func)]
end
end
MyMap.map [1, 2, 3, 4], fn(i) -> i * i end
Ruby-like Syntax
defmodule MyMap do
def map([], _func), do: []
def map([head | tail], func) do
[func.(head) | map(tail, func)]
end
end
MyMap.map [1, 2, 3, 4], fn(i) -> i * i end
Pattern Matching
defmodule Patterns do
def greet(%{name: name, age: age}) do
IO.puts "Hi there #{name}, what's up at #{age}?"
end
def greet(%{name: name}) do
IO.puts "Hi there #{name}"
end
def greet(_) do
IO.puts "Hi"
end
end
Patterns.greet %{name: "Tobi", age: 26}
Patterns.greet %{name: "Tobi"}
Patterns.greet ["Mop"]
Pattern Matching
people = DB.find_customers
orders = Orders.for_customers(people)
tax = sales_tax(orders, 2013)
filing = prepare_filing(tax)
Pipe
filing = DB.find_customers
|> Orders.for_customers
|> sales_tax(2013)
|> prepare_filing
Pipe
filing =
prepare_filing(sales_tax(Orders.for_cusstomers(DB.find_c
ustomers), 2013))
Pipe
filing = DB.find_customers
|> Orders.for_customers
|> sales_tax(2013)
|> prepare_filing
Pipe
@spec all?(t) :: boolean
@spec all?(t, (element -> as_boolean(term))) :: boolean
def all?(enumerable, fun  fn(x) -> x end)
def all?(enumerable, fun) when is_list(enumerable) do
do_all?(enumerable, fun)
end
Optional Type Annotations
defmacro plug(plug, opts  []) do
quote do
@plugs {unquote(plug), unquote(opts), true}
end
end
Meta Programming
Functional Programming?
Elixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicit
2.2.2 :001 > [1, 2, 3, 4].map { |i| i + 1 }
=> [2, 3, 4, 5]
iex(2)> Enum.map [1, 2, 3, 4], fn(i) -> i + 1 end
[2, 3, 4, 5]
vs
Where to call functions
Transformation of
Data
Minimize state
vs
Hiding State
Same Input,
Same Output
Testing++
variable = 10
do_something(variable)
insert_in_db(variable)
Immutable Data
person = Person.new(attributes)
do_something(person)
insert_in_db(person)
Immutable Data
person = Person.new(attributes)
person = do_something(person)
insert_in_db(person)
Immutable Data
First class actor support
Elixir & Phoenix - fast, concurrent and explicit
connection
|> endpoint
|> router
|> pipelines
|> controller
|> model
|> view
Flow
def new(conn, _params) do
changeset = User.new_changeset(%User{})
render conn, "new.html", changeset: changeset
end
Controller
defmodule Rumbl.User do
use Rumbl.Web, :model
schema "users" do
field :name, :string
field :username, :string
field :password, :string, virtual: true
field :password_hash, :string
has_many :videos, Rumbl.Video
timestamps
end
# ...
end
Model
defmodule Rumbl.UserView do
use Rumbl.Web, :view
alias Rumbl.User
def first_name(%{name: name}) do
name
|> String.split(" ")
|> Enum.at(0)
end
end
View
<%= form_for @changeset, user_path(@conn, :create), fn
form -> %>
<div class="form-group">
<%= text_input form, :name, placeholder: "Name",
class: "form-control" %>
<%= error_tag form, :name %>
</div>
<div class="form-group">
<%= text_input form, :username, placeholder:
"Username", class: "form-control" %>
<%= error_tag form, :username %>
</div>
<div class="form-group">
<%= password_input form, :password, placeholder:
"Password", class: "form-control" %>
<%= error_tag form, :password %>
</div>
<%= submit "Create User", class: "btn btn-primary" %>
<% end %>
Template
Elixir & Phoenix - fast, concurrent and explicit
def new_changeset(model, params  :empty) do
model
|> cast(params, ~w(name username), [])
|> unique_constraint(:username)
|> validate_length(:username, min: 1, max: 20)
end
def registration_changeset(model, params) do
model
|> new_changeset(params)
|> cast(params, ~w(password), [])
|> validate_length(:password, min: 6, max: 100)
|> put_pass_hash()
end
Changesets
def create(conn, %{"user" => user_params}) do
changeset = User.registration_changeset(%User{},
user_params)
case Repo.insert changeset do
{:ok, user} ->
conn
|> Rumbl.Auth.login(user)
|> put_flash(:info, "You successfully registered
as #{user.name}!")
|> redirect(to: user_path(conn, :index))
{:error, changeset}->
render conn, "new.html", changeset: changeset
end
end
Changesets
defmodule Rumbl.VideoChannel do
use Rumbl.Web, :channel
def join("videos:" <> video_id, _params, socket) do
{:ok, socket}
end
def handle_in("new_annotation", params, socket) do
broadcast! socket, "new_annotation", %{
user: %{username: "anon"},
body: params["body"],
at: params["at"]
}
{:reply, :ok, socket}
end
end
Channels
Elixir & Phoenix - fast, concurrent and explicit
iex(13)> user = Repo.get_by(User, name: "Homer")
iex(14)> user.videos
#Ecto.Association.NotLoaded<association :videos is not
loaded>
iex(15)> Repo.preload(user, :videos)
iex(16)> user.videos
#Ecto.Association.NotLoaded<association :videos is not
loaded>
iex(17)> user = Repo.preload(user, :videos)
iex(18)> user.videos
[%Rumbl.Video{__meta__: #Ecto.Schema.Metadata<:loaded>,
category: #Ecto.Association.NotLoaded<association
:category is not loaded>,
category_id: nil, description: "such great many wow", id:
3,
inserted_at: #Ecto.DateTime<2016-02-28T18:42:41Z>, title:
"Hubidubiee",
updated_at: #Ecto.DateTime<2016-02-28T18:42:41Z>, url:
"www.lol.com",
user: #Ecto.Association.NotLoaded<association :user is
not loaded>,
user_id: 5}]
Explicit preloading
iex(13)> user = Repo.get_by(User, name: "Homer")
iex(14)> user.videos
#Ecto.Association.NotLoaded<association :videos is not
loaded>
iex(15)> Repo.preload(user, :videos)
iex(16)> user.videos
#Ecto.Association.NotLoaded<association :videos is not
loaded>
iex(17)> user = Repo.preload(user, :videos)
iex(18)> user.videos
[%Rumbl.Video{__meta__: #Ecto.Schema.Metadata<:loaded>,
category: #Ecto.Association.NotLoaded<association
:category is not loaded>,
category_id: nil, description: "such great many wow", id:
3,
inserted_at: #Ecto.DateTime<2016-02-28T18:42:41Z>, title:
"Hubidubiee",
updated_at: #Ecto.DateTime<2016-02-28T18:42:41Z>, url:
"www.lol.com",
user: #Ecto.Association.NotLoaded<association :user is
not loaded>,
user_id: 5}]
Explicit preloading
iex(13)> user = Repo.get_by(User, name: "Homer")
iex(14)> user.videos
#Ecto.Association.NotLoaded<association :videos is not
loaded>
iex(15)> Repo.preload(user, :videos)
iex(16)> user.videos
#Ecto.Association.NotLoaded<association :videos is not
loaded>
iex(17)> user = Repo.preload(user, :videos)
iex(18)> user.videos
[%Rumbl.Video{__meta__: #Ecto.Schema.Metadata<:loaded>,
category: #Ecto.Association.NotLoaded<association
:category is not loaded>,
category_id: nil, description: "such great many wow", id:
3,
inserted_at: #Ecto.DateTime<2016-02-28T18:42:41Z>, title:
"Hubidubiee",
updated_at: #Ecto.DateTime<2016-02-28T18:42:41Z>, url:
"www.lol.com",
user: #Ecto.Association.NotLoaded<association :user is
not loaded>,
user_id: 5}]
Explicit preloading
Umbrella apps
So we all go and do Elixir
and Phoenix now?
Baggage
Eco-System
Thanks & Enjoy Elixir
Tobias Pfeiffer
@PragTob
pragtob.info
Photo Attribution
● CC BY-ND 2.0
– https://www.flickr.com/photos/mmmswan/8918529543/
● CC BY 2.0
– https://flic.kr/p/eKGRRJ
● CC BY-NC 2.0
– https://www.flickr.com/photos/-jule/2728475835/
● CC BY-NC-ND 2.0
– https://flic.kr/p/eyC7ZT
● CC BY-SA 2.0
– https://commons.wikimedia.org/wiki/File:Heckert_GNU_white.svg

More Related Content

PDF
Ruby to Elixir - what's great and what you might miss
PDF
What's New in PHP 5.5
KEY
An introduction to Ruby
KEY
Clojure入門
PPTX
Filesystem abstractions and msg queue sergeev - symfony camp 2018
PDF
Ruby 1.9
PDF
Go for the paranoid network programmer, 2nd edition
PDF
GenStage and Flow - Jose Valim
Ruby to Elixir - what's great and what you might miss
What's New in PHP 5.5
An introduction to Ruby
Clojure入門
Filesystem abstractions and msg queue sergeev - symfony camp 2018
Ruby 1.9
Go for the paranoid network programmer, 2nd edition
GenStage and Flow - Jose Valim

What's hot (20)

KEY
Tres Gemas De Ruby
PDF
FPBrno 2018-05-22: Benchmarking in elixir
PDF
PDF
Neotool (using py2neo from the command line)
PPTX
The Art, Joy, and Power of Creating Musical Programs (JFugue at SXSW Interact...
PDF
Hello Go
PPTX
JFugue, Music, and the Future of Java [JavaOne 2016, CON1851]
PDF
Functional Pattern Matching on Python
PDF
Elixir @ Paris.rb
PPTX
Build a compiler in 2hrs - NCrafts Paris 2015
DOCX
RedHat/CentOs Commands for administrative works
PDF
(Fun clojure)
PDF
Micropage in microtime using microframework
PPTX
Process monitoring in UNIX shell scripting
PDF
Stop Guessing and Start Measuring - Benchmarking in Practice (Lambdadays)
PDF
Alessandro sf 2010
PDF
tensorflow/keras model coding tutorial 勉強会
PDF
Javascript ES6 generators
PDF
Functional Programming inside OOP? It’s possible with Python
Tres Gemas De Ruby
FPBrno 2018-05-22: Benchmarking in elixir
Neotool (using py2neo from the command line)
The Art, Joy, and Power of Creating Musical Programs (JFugue at SXSW Interact...
Hello Go
JFugue, Music, and the Future of Java [JavaOne 2016, CON1851]
Functional Pattern Matching on Python
Elixir @ Paris.rb
Build a compiler in 2hrs - NCrafts Paris 2015
RedHat/CentOs Commands for administrative works
(Fun clojure)
Micropage in microtime using microframework
Process monitoring in UNIX shell scripting
Stop Guessing and Start Measuring - Benchmarking in Practice (Lambdadays)
Alessandro sf 2010
tensorflow/keras model coding tutorial 勉強会
Javascript ES6 generators
Functional Programming inside OOP? It’s possible with Python

Viewers also liked (6)

PDF
Elixir
PDF
What did AlphaGo do to beat the strongest human Go player?
PDF
Introduction to Elixir
PDF
Replacing ActiveRecord callbacks with Pub/Sub
PDF
Microservices vs. The First Law of Distributed Objects - GOTO Nights Chicago ...
PDF
Annabel Lee
Elixir
What did AlphaGo do to beat the strongest human Go player?
Introduction to Elixir
Replacing ActiveRecord callbacks with Pub/Sub
Microservices vs. The First Law of Distributed Objects - GOTO Nights Chicago ...
Annabel Lee

Similar to Elixir & Phoenix - fast, concurrent and explicit (20)

PDF
Phoenix for laravel developers
PDF
Elixir & Phoenix – fast, concurrent and explicit
PDF
Introducing Elixir and OTP at the Erlang BASH
PDF
Re-Design with Elixir/OTP
PDF
Elixir & Phoenix – fast, concurrent and explicit
PDF
Yurii Bodarev - OTP, Phoenix & Ecto: Three Pillars of Elixir
PDF
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
PDF
Elixir formatter Internals
PDF
Migrating legacy data
ODP
Very basic functional design patterns
PDF
Clojure: Functional Concurrency for the JVM (presented at OSCON)
ODP
The secrets of inverse brogramming
PDF
Ruby on Rails at PROMPT ISEL '11
PDF
Play vs Rails
PPTX
DevOps with Fabric
PPTX
Groovy vs Boilerplate and Ceremony Code
PDF
function* - ES6, generators, and all that (JSRomandie meetup, February 2014)
KEY
Desarrollando aplicaciones web en minutos
ZIP
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
PDF
Marrow: A Meta-Framework for Python 2.6+ and 3.1+
Phoenix for laravel developers
Elixir & Phoenix – fast, concurrent and explicit
Introducing Elixir and OTP at the Erlang BASH
Re-Design with Elixir/OTP
Elixir & Phoenix – fast, concurrent and explicit
Yurii Bodarev - OTP, Phoenix & Ecto: Three Pillars of Elixir
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
Elixir formatter Internals
Migrating legacy data
Very basic functional design patterns
Clojure: Functional Concurrency for the JVM (presented at OSCON)
The secrets of inverse brogramming
Ruby on Rails at PROMPT ISEL '11
Play vs Rails
DevOps with Fabric
Groovy vs Boilerplate and Ceremony Code
function* - ES6, generators, and all that (JSRomandie meetup, February 2014)
Desarrollando aplicaciones web en minutos
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Marrow: A Meta-Framework for Python 2.6+ and 3.1+

More from Tobias Pfeiffer (20)

PDF
Going Staff - Keynote @ CodeBEAM EU edition
PDF
Going Staff
PDF
Stories in Open SOurce
PDF
Metaphors are everywhere: Ideas to Improve Software Development
PDF
Stories in Open Source
PDF
Elixir & Phoenix – Fast, Concurrent and Explicit
PDF
Functioning Among Humans
PDF
Functioning Among Humans
PDF
Do You Need That Validation? Let Me Call You Back About It
PDF
Elixir, your Monolith and You
PDF
Where do Rubyists go?
PDF
It's About the Humans, Stupid (Lightning)
PDF
Stop Guessing and Start Measuring - Benchmarking Practice (Poly Version)
PDF
Code, Comments, Concepts, Comprehension – Conclusion?
PDF
How fast is it really? Benchmarking in Practice (Ruby Version)
PDF
How fast ist it really? Benchmarking in practice
PDF
Introducing Elixir the easy way
PDF
What did AlphaGo do to beat the strongest human Go player?
PDF
What did AlphaGo do to beat the strongest human Go player? (Strange Group Ver...
PDF
Beating Go Thanks to the Power of Randomness
Going Staff - Keynote @ CodeBEAM EU edition
Going Staff
Stories in Open SOurce
Metaphors are everywhere: Ideas to Improve Software Development
Stories in Open Source
Elixir & Phoenix – Fast, Concurrent and Explicit
Functioning Among Humans
Functioning Among Humans
Do You Need That Validation? Let Me Call You Back About It
Elixir, your Monolith and You
Where do Rubyists go?
It's About the Humans, Stupid (Lightning)
Stop Guessing and Start Measuring - Benchmarking Practice (Poly Version)
Code, Comments, Concepts, Comprehension – Conclusion?
How fast is it really? Benchmarking in Practice (Ruby Version)
How fast ist it really? Benchmarking in practice
Introducing Elixir the easy way
What did AlphaGo do to beat the strongest human Go player?
What did AlphaGo do to beat the strongest human Go player? (Strange Group Ver...
Beating Go Thanks to the Power of Randomness

Recently uploaded (20)

PDF
Internet of Things (IoT) – Definition, Types, and Uses
PDF
State of AI in Business 2025 - MIT NANDA
PPTX
From XAI to XEE through Influence and Provenance.Controlling model fairness o...
PDF
The AI Revolution in Customer Service - 2025
PDF
“Introduction to Designing with AI Agents,” a Presentation from Amazon Web Se...
PDF
Decision Optimization - From Theory to Practice
PDF
Addressing the challenges of harmonizing law and artificial intelligence tech...
PDF
Streamline Vulnerability Management From Minimal Images to SBOMs
PPT
Overviiew on Intellectual property right
PDF
Human Computer Interaction Miterm Lesson
PDF
TicketRoot: Event Tech Solutions Deck 2025
PDF
NewMind AI Journal Monthly Chronicles - August 2025
PDF
CCUS-as-the-Missing-Link-to-Net-Zero_AksCurious.pdf
PPTX
AQUEEL MUSHTAQUE FAKIH COMPUTER CENTER .
PDF
Child-friendly e-learning for artificial intelligence education in Indonesia:...
PDF
Domain-specific knowledge and context in large language models: challenges, c...
PDF
CEH Module 2 Footprinting CEH V13, concepts
PDF
Altius execution marketplace concept.pdf
PDF
GDG Cloud Southlake #45: Patrick Debois: The Impact of GenAI on Development a...
PDF
Technical Debt in the AI Coding Era - By Antonio Bianco
Internet of Things (IoT) – Definition, Types, and Uses
State of AI in Business 2025 - MIT NANDA
From XAI to XEE through Influence and Provenance.Controlling model fairness o...
The AI Revolution in Customer Service - 2025
“Introduction to Designing with AI Agents,” a Presentation from Amazon Web Se...
Decision Optimization - From Theory to Practice
Addressing the challenges of harmonizing law and artificial intelligence tech...
Streamline Vulnerability Management From Minimal Images to SBOMs
Overviiew on Intellectual property right
Human Computer Interaction Miterm Lesson
TicketRoot: Event Tech Solutions Deck 2025
NewMind AI Journal Monthly Chronicles - August 2025
CCUS-as-the-Missing-Link-to-Net-Zero_AksCurious.pdf
AQUEEL MUSHTAQUE FAKIH COMPUTER CENTER .
Child-friendly e-learning for artificial intelligence education in Indonesia:...
Domain-specific knowledge and context in large language models: challenges, c...
CEH Module 2 Footprinting CEH V13, concepts
Altius execution marketplace concept.pdf
GDG Cloud Southlake #45: Patrick Debois: The Impact of GenAI on Development a...
Technical Debt in the AI Coding Era - By Antonio Bianco

Elixir & Phoenix - fast, concurrent and explicit

  • 5. Elixir and Phoenix fast, concurrent and explicit Tobias Pfeiffer @PragTob pragtob.info
  • 6. Elixir and Phoenix fast, concurrent and explicit Tobias Pfeiffer @PragTob pragtob.info
  • 10. defmodule MyMap do def map([], _func), do: [] def map([head | tail], func) do [func.(head) | map(tail, func)] end end MyMap.map [1, 2, 3, 4], fn(i) -> i * i end
  • 11. defmodule MyMap do def map([], _func), do: [] def map([head | tail], func) do [func.(head) | map(tail, func)] end end MyMap.map [1, 2, 3, 4], fn(i) -> i * i end Ruby-like Syntax
  • 12. defmodule MyMap do def map([], _func), do: [] def map([head | tail], func) do [func.(head) | map(tail, func)] end end MyMap.map [1, 2, 3, 4], fn(i) -> i * i end Pattern Matching
  • 13. defmodule Patterns do def greet(%{name: name, age: age}) do IO.puts "Hi there #{name}, what's up at #{age}?" end def greet(%{name: name}) do IO.puts "Hi there #{name}" end def greet(_) do IO.puts "Hi" end end Patterns.greet %{name: "Tobi", age: 26} Patterns.greet %{name: "Tobi"} Patterns.greet ["Mop"] Pattern Matching
  • 14. people = DB.find_customers orders = Orders.for_customers(people) tax = sales_tax(orders, 2013) filing = prepare_filing(tax) Pipe
  • 15. filing = DB.find_customers |> Orders.for_customers |> sales_tax(2013) |> prepare_filing Pipe
  • 17. filing = DB.find_customers |> Orders.for_customers |> sales_tax(2013) |> prepare_filing Pipe
  • 18. @spec all?(t) :: boolean @spec all?(t, (element -> as_boolean(term))) :: boolean def all?(enumerable, fun fn(x) -> x end) def all?(enumerable, fun) when is_list(enumerable) do do_all?(enumerable, fun) end Optional Type Annotations
  • 19. defmacro plug(plug, opts []) do quote do @plugs {unquote(plug), unquote(opts), true} end end Meta Programming
  • 24. 2.2.2 :001 > [1, 2, 3, 4].map { |i| i + 1 } => [2, 3, 4, 5] iex(2)> Enum.map [1, 2, 3, 4], fn(i) -> i + 1 end [2, 3, 4, 5] vs Where to call functions
  • 31. person = Person.new(attributes) person = do_something(person) insert_in_db(person) Immutable Data
  • 32. First class actor support
  • 34. connection |> endpoint |> router |> pipelines |> controller |> model |> view Flow
  • 35. def new(conn, _params) do changeset = User.new_changeset(%User{}) render conn, "new.html", changeset: changeset end Controller
  • 36. defmodule Rumbl.User do use Rumbl.Web, :model schema "users" do field :name, :string field :username, :string field :password, :string, virtual: true field :password_hash, :string has_many :videos, Rumbl.Video timestamps end # ... end Model
  • 37. defmodule Rumbl.UserView do use Rumbl.Web, :view alias Rumbl.User def first_name(%{name: name}) do name |> String.split(" ") |> Enum.at(0) end end View
  • 38. <%= form_for @changeset, user_path(@conn, :create), fn form -> %> <div class="form-group"> <%= text_input form, :name, placeholder: "Name", class: "form-control" %> <%= error_tag form, :name %> </div> <div class="form-group"> <%= text_input form, :username, placeholder: "Username", class: "form-control" %> <%= error_tag form, :username %> </div> <div class="form-group"> <%= password_input form, :password, placeholder: "Password", class: "form-control" %> <%= error_tag form, :password %> </div> <%= submit "Create User", class: "btn btn-primary" %> <% end %> Template
  • 40. def new_changeset(model, params :empty) do model |> cast(params, ~w(name username), []) |> unique_constraint(:username) |> validate_length(:username, min: 1, max: 20) end def registration_changeset(model, params) do model |> new_changeset(params) |> cast(params, ~w(password), []) |> validate_length(:password, min: 6, max: 100) |> put_pass_hash() end Changesets
  • 41. def create(conn, %{"user" => user_params}) do changeset = User.registration_changeset(%User{}, user_params) case Repo.insert changeset do {:ok, user} -> conn |> Rumbl.Auth.login(user) |> put_flash(:info, "You successfully registered as #{user.name}!") |> redirect(to: user_path(conn, :index)) {:error, changeset}-> render conn, "new.html", changeset: changeset end end Changesets
  • 42. defmodule Rumbl.VideoChannel do use Rumbl.Web, :channel def join("videos:" <> video_id, _params, socket) do {:ok, socket} end def handle_in("new_annotation", params, socket) do broadcast! socket, "new_annotation", %{ user: %{username: "anon"}, body: params["body"], at: params["at"] } {:reply, :ok, socket} end end Channels
  • 44. iex(13)> user = Repo.get_by(User, name: "Homer") iex(14)> user.videos #Ecto.Association.NotLoaded<association :videos is not loaded> iex(15)> Repo.preload(user, :videos) iex(16)> user.videos #Ecto.Association.NotLoaded<association :videos is not loaded> iex(17)> user = Repo.preload(user, :videos) iex(18)> user.videos [%Rumbl.Video{__meta__: #Ecto.Schema.Metadata<:loaded>, category: #Ecto.Association.NotLoaded<association :category is not loaded>, category_id: nil, description: "such great many wow", id: 3, inserted_at: #Ecto.DateTime<2016-02-28T18:42:41Z>, title: "Hubidubiee", updated_at: #Ecto.DateTime<2016-02-28T18:42:41Z>, url: "www.lol.com", user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: 5}] Explicit preloading
  • 45. iex(13)> user = Repo.get_by(User, name: "Homer") iex(14)> user.videos #Ecto.Association.NotLoaded<association :videos is not loaded> iex(15)> Repo.preload(user, :videos) iex(16)> user.videos #Ecto.Association.NotLoaded<association :videos is not loaded> iex(17)> user = Repo.preload(user, :videos) iex(18)> user.videos [%Rumbl.Video{__meta__: #Ecto.Schema.Metadata<:loaded>, category: #Ecto.Association.NotLoaded<association :category is not loaded>, category_id: nil, description: "such great many wow", id: 3, inserted_at: #Ecto.DateTime<2016-02-28T18:42:41Z>, title: "Hubidubiee", updated_at: #Ecto.DateTime<2016-02-28T18:42:41Z>, url: "www.lol.com", user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: 5}] Explicit preloading
  • 46. iex(13)> user = Repo.get_by(User, name: "Homer") iex(14)> user.videos #Ecto.Association.NotLoaded<association :videos is not loaded> iex(15)> Repo.preload(user, :videos) iex(16)> user.videos #Ecto.Association.NotLoaded<association :videos is not loaded> iex(17)> user = Repo.preload(user, :videos) iex(18)> user.videos [%Rumbl.Video{__meta__: #Ecto.Schema.Metadata<:loaded>, category: #Ecto.Association.NotLoaded<association :category is not loaded>, category_id: nil, description: "such great many wow", id: 3, inserted_at: #Ecto.DateTime<2016-02-28T18:42:41Z>, title: "Hubidubiee", updated_at: #Ecto.DateTime<2016-02-28T18:42:41Z>, url: "www.lol.com", user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: 5}] Explicit preloading
  • 48. So we all go and do Elixir and Phoenix now?
  • 51. Thanks & Enjoy Elixir Tobias Pfeiffer @PragTob pragtob.info
  • 52. Photo Attribution ● CC BY-ND 2.0 – https://www.flickr.com/photos/mmmswan/8918529543/ ● CC BY 2.0 – https://flic.kr/p/eKGRRJ ● CC BY-NC 2.0 – https://www.flickr.com/photos/-jule/2728475835/ ● CC BY-NC-ND 2.0 – https://flic.kr/p/eyC7ZT ● CC BY-SA 2.0 – https://commons.wikimedia.org/wiki/File:Heckert_GNU_white.svg