# MVC with Elixir [@gregmcintyre](https://twitter.com/gregmcintyre) 2017 ==== ## What is MVC? A proven way of organising lots of code ==== ## This Presentation 1. Try to implement YouTube 2. Write some messy code 3. Organise code better with MVC ==== ## The Situation
==== ## How? ```elixir def youtube_search(query) do # lots of code? end ``` ==== ## First Draft ```elixir def youtube_search(query) do # 1. search results from a database # 2. send back HTML with videos end ``` ==== ## 1. Search Database ```elixir list_of_videos = query_sql_database(" SELECT title, href, img_src, ... FROM videos WHERE $query IN search_terms") ``` ==== ## 2. Send Back HTML ```elixir send_back "" send_back "
" Enum.each list_of_videos, fn(v) -> send_back "
#{v}
" end send_back "
" send_back "" ``` ==== ## Summary ```elixir def youtube_search(request) do list_of_videos = database("SELECT * FROM videos ... ") send_back " ... videos ... " end ``` ==== ## It Works, Time for a Break
==== ## Next Day ```elixir def my_channel(request) do list_of_videos = database(" SELECT title, href, img_src, ... FROM videos WHERE uploader = $logged_in_user") send_back " ... videos ... " end ``` ==== ## ...Next Day ```elixir def youtube_search(request) do list_of_videos = database("... videos WHERE $query IN search_terms") send_back " ... videos ... " end def my_channel(request) do list_of_videos = database("... videos WHERE $logged_in_user_id = uploader_id") send_back " ... videos ... " end def subscriptions(request) do list_of_videos = database("... videos WHERE $logged_in_user_id IN subscribers") send_back " ... videos ... " end ``` ==== ## Pattern ```elixir def youtube_search(request) do # talk with database # send back HTML end def my_channel(request) do # talk with database # send back HTML end def subscriptions(request) do # talk with database # send back HTML end ``` ==== ## Group Similar Code Into Modules ```elixir defmodule Controller do def youtube_search(request) do result = Model.get_search_videos(request.query) View.send_search_page(result) end def my_channel(request) do result = Model.get_channel_videos(request.user) View.send_channel_page(result) end def subscriptions(request) do result = Model.get_subscription_videos(request.user) View.send_subscriptions_page(result) end end ``` ==== ## Group All the Database Code ```elixir defmodule Model do def get_search_videos(query) do return query_giant_database(...) end def get_channel_videos(user) do return query_giant_database(...) end def get_subscription_videos(user) do return query_giant_database(...) end end ``` ==== ## Group All the HTML Code ```elixir defmodule View do def send_search_page(list_of_videos) do send_back header() send_back "
Search Results
" send_back "... #{list_of_videos} ..." send_back footer() end def send_channel_page(list_of_videos) do send_back header() send_back "
My Uploads
" send_back "... #{list_of_videos} ..." send_back footer() end def send_subscriptions_page(list_of_videos) do send_back header() send_back "
Subscriptions
" send_back "... #{list_of_videos} ..." send_back footer() end end ``` ==== ## Feels Neater, Time for a Reward
==== ## Phoenix Controller ```elixir defmodule YouTube.Web.VideoController do # ... def index(conn, request) do videos = YouTube.search_videos(request.query) render(conn, "index.html", videos: videos) end # ... end ``` ==== ## Phoenix Service ```elixir defmodule YouTube do def search_videos(query) do Repo.all( from video in Video, where: query in video.search_terms ) end end ``` ==== ## Phoenix Template ```erb
Listing Videos
<%= for video <- @videos do %>
<%= video.name %>
<%= link "Show", to: video_path(@conn, :show, video) %> <%= link "Edit", to: video_path(@conn, :edit, video) %> <%= link "Delete", to: video_path(@conn, :delete, video), method: :delete %>
<% end %>
<%= link "New video", to: video_path(@conn, :new) %>
``` ==== ## Service? Template?
MVC Category
Phoenix Concepts
Controller
Router, Plugs, Controllers, Channels
Model
Apps, Services, Ecto Models
View
Views, Templates, HTML, CSS, JavaScript
==== ## History This pattern was adapted from desktop applications ==== ## Where Do I Put Code That Deals With...
==== ## Jargon: Controller * Functions to handle events (like web requests) * Let you "control" the computer ==== ## Jargon: Model * Functions to fetch/search/read/write information * Your computer "modelling" of a situation ==== ## Jargon: View * Functions to update what you see (e.g. send back HTML) * Your "view" of the computer modelling ==== ## Next Time You're Doing This
==== ## Imagine This
==== ## Thanks
==== [gregorymcintyre.com/slides/mvc-elixir/](http://gregorymcintyre.com/slides/mvc-elixir/#/)
(face icon by
Freepik
from
www.flaticon.com
)