Phoenix Web Development - Mike Voloz - E-Book

Phoenix Web Development E-Book

Mike Voloz

0,0
31,19 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.

Mehr erfahren.
Beschreibung

Learn to build a high-performance functional prototype of a voting web application from scratch using Elixir and Phoenix

Key Features

  • Build a strong foundation in Functional-Programming techniques while learning to build compelling web applications
  • Understand the Elixir Concurrency and parallelization model to build high-performing blazingly fast applications
  • Learn to test, debug and deploy your web applications using Phoenix framework

Book Description

Phoenix is a modern web development framework that is used to build API’s and web applications. It is built on Elixir and runs on Erlang VM which makes it much faster than other options. With Elixir and Phoenix, you build your application the right way, ready to scale and ready for the increasing demands of real-time web applications.

This book covers the basics of the Phoenix web framework, showing you how to build a community voting application, and is divided into three parts. In the first part, you will be introduced to Phoenix and Elixir and understand the core terminologies that are used to describe them. You will also learn to build controller pages, store and retrieve data, add users to your app pages and protect your database. In the second section you will be able to reinforce your knowledge of architecting real time applications in phoenix and not only debug these applications but also diagnose issues in them. In the third and final section you will have the complete understanding of deploying and running the phoenix application and should be comfortable to make your first application release

By the end of this book, you'll have a strong grasp of all of the core fundamentals of the Phoenix framework, and will have built a full production-ready web application from scratch.

What you will learn

  • Learn Phoenix Framework fundamentals and v1.3's new application structure
  • Build real-time applications with channels and presence
  • Utilize GenServers and other OTP fundamentals to keep an application stable
  • Track users as they sign in and out of chat with Phoenix’s built-in presence functionality
  • Write your own database interaction code that is safe, bug-free, and easy to work with
  • Explore testing and debugging methodologies to understand a real software development lifecycle for a Phoenix application
  • Deploy and run your Phoenix application in production

Who this book is for

This book is for people with a basic knowledge of Elixir, who want to start building web applications. Prior experience with web technologies is assumed.

Brandon Richey is a software engineer and Elixir enthusiast who has written a large number of popular Elixir tutorials. He has been doing professional and hobby programming projects spanning topics from healthcare, personal sites, recruiting, and game development for nearly 20 years! When not programming, Brandon enjoys spending time with his family, playing (and making) video games and working on his drawings and paintings!

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 479

Veröffentlichungsjahr: 2018

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Phoenix Web Development

 

 

 

 

 

 

 

 

 

Create rich web applications using functional programming techniques with Phoenix and Elixir

 

 

 

 

 

 

 

 

 

 

 

 

Brandon Richey

 

 

 

 

 

 

 

 

 

 

 

 

BIRMINGHAM - MUMBAI

Phoenix Web Development

Copyright © 2018 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

Commissioning Editor: Kunal ChaudhariAcquisition Editor: Larissa PintoContent Development Editor: Mohammed Yusuf ImaratwaleTechnical Editor: Ralph RosarioCopy Editor: Safis EditingProject Coordinator: Hardik BhindeProofreader: Safis EditingIndexer: Priyanka DhadkeGraphics: Jason MonteiroProduction Coordinator: Shantanu Zagade

First published: April 2018

Production reference: 1250418

Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.

ISBN 978-1-78728-419-7

www.packtpub.com

mapt.io

Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.

Why subscribe?

Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals

Improve your learning with Skill Plans built especially for you

Get a free eBook or video every month

Mapt is fully searchable

Copy and paste, print, and bookmark content

PacktPub.com

Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.

At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.

Contributors

About the author

Brandon Richey is a software engineer and Elixir enthusiast who has written a large number of popular Elixir tutorials. He has been doing professional and hobby programming projects spanning topics from healthcare, personal sites, recruiting, and game development for nearly 20 years! When not programming, Brandon enjoys spending time with his family, playing (and making) video games and working on his drawings and paintings!

I want to acknowledge the hard work put in by some friends and family who helped make this book a reality: Larry Rohrs, for his fantastic work in reviewing and editing a huge number of chapters as well as Mikhail Volozin and Rami Massoud, who also contributed reviews and edits!

About the reviewers

Atul S. Khot is a self-taught programmer and learned from reading C and C++ code. A Linux aficionado and a command-line guy at heart, Atul has dabbled in multiple languages. He is deeply interested in functional languages and massively parallel software systems. Atul speaks at software conferences, and he is a past Dr. Dobb's Jolt award judge. He was the author of Learning functional Data Structures & Algorithms and Scala Functional Programming Patterns, both published by Packt Publishing.

I would want to thank my parents—late Sushila S. Khot (Aai) and late Shriniwas V. Khot (Anna), for teaching me the value of continuous learning and sharing - and the importance of being human, first and foremost. You lit the lamp in so many lives! Heart of hearts, I know you are watching over me and silently feeling proud.

 

 

 

LarryRohrs worked for a large financial firm as an IT professional for 25 years. Professional coding projects were focused on infrastructure in APL-derivative languages, C, and C++. As a senior manager, Larry managed a large, global, IT team responsible for collecting, verifying, organizing, and expanding key reference data available through large, distributed databases. He is currently retired and enjoys spending more time with family and hobbies.

 

 

 

Packt is searching for authors like you

If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.

Table of Contents

Title Page

Copyright and Credits

Phoenix Web Development

Packt Upsell

Why subscribe?

PacktPub.com

Contributors

About the author

About the reviewers

Packt is searching for authors like you

Preface

Who this book is for

What this book covers

To get the most out of this book

Download the example code files

Conventions used

Get in touch

Reviews

A Brief Introduction to Elixir and Phoenix

Introducing IEx and Elixir

What is IEx?

Variables in Elixir

Immutability in Elixir

Understanding the different types in Elixir

Getting more information with the i helper

Getting more information with the h helper

Using IEx and helpers to understand types

Your objects have no power here

Introduction to Phoenix

Installing Phoenix 1.3

Creating a new Phoenix project

Running the Phoenix Mix Task

Running the Phoenix server for the first time

Phoenix's default application structure

Configuration files

Assets files

Private files

Tests

Other directories

The most important directory: lib

A note about how data flows in Phoenix

Summary

Building Controllers, Views, and Templates

Understanding the flow of Phoenix connections

Creating our Social Voting project

Creating a poll controller

Understanding the controller's structure

Building the poll controller

Understanding templates

Passing data to our templates

Writing controller tests

Understanding the code behind tests

Writing the poll controller test

Summary

Storing and Retrieving Vote Data with Ecto Pages

Understanding the role of schemas

Creating a new migration

Creating the Polls table migration

Creating our Options table migration

Creating our Poll schema

Testing our Poll schema

Creating our Option schema

Understanding the gotchas of associations

Understanding the role of contexts

Creating a Votes context

Grabbing a list of data

Understanding Ecto query writing

Hooking up the context to our controller

Creating a new poll

Creating the new action in the controller

Creating our create function

Writing our unit tests

Summary

Introducing User Accounts and Sessions

Adding user accounts

Designing our user schema

Creating our user schema

Creating our accounts context

Writing our user unit tests

Creating a user signup page

Creating the routes

Creating the controller code (with tests)

Setting up the password functionality

Installing Comeonin

Adding Comeonin to the user schema file

Updating our tests

Updating the UI to include password fields

Creating a user login page

Building our create session function

Writing session controller tests

Summary

Validations, Errors, and Tying Loose Ends

Connecting polls to users

Creating the migration

Modifying the schemas

Fixing broken poll tests

Sending a user ID through the controller

Retrieving data from sessions

Writing our Poll Controller's tests

Restricting access via sessions

Working with validations and errors

Making usernames unique

Writing custom validations

Displaying validation errors in our forms

Summary

Live Voting with Phoenix

Building channels and topics in Phoenix

Understanding sockets

Understanding channels

Working with ES2015 syntax

Imports and exports

let and const

Fat-arrow functions

Variable and argument destructuring

Sending and receiving messages with channels

Conditionally loading our socket

Sending messages on the socket

Allowing users to vote on polls

Making voting real-time

Building our dummy functionality

Changing our dummy code to push to the server

Writing our server channel code for live voting

Refactoring our channels away from the index

Moving the channel functionality to show

Starting our channel tests

Summary

Improving Our Application and Adding Features

Designing and implementing our new features

Implementing file uploads in Phoenix

Working with uploads in Phoenix

Adding file uploads to our new poll UI

Hooking up the uploads to our database

Writing the migration file

Modifying the schema and the context code

Completing the votes context for the image uploads

Implementing voting restrictions

Creating the vote record migration

Creating the vote record schema

Hooking up restrictions

Fixing the broken tests

Summary

Adding Chat to Your Phoenix Application

Adding chat to a Phoenix application

Working with the chat schema

Building the chat schema

Designing our message functionality

Implementing message functions in our context

Writing our unit tests

Fixing navigation in our application

Creating the chat UI

Building the UI Itself

Creating our chat channel

Sending chat messages

Hooking up the new JavaScript code to Phoenix

Refactoring for poll chats

Fixing up our tests

Returning to a passing test suite

Summary

Using Presence and ETS in Phoenix

Utilizing Presence and ETS to make our app more robust

What is Presence?

Updating our chat UI

Elixir implementation

JavaScript implementation

Using ETS

Why use ETS?

Experimenting with ETS in an IEx window

Creating our Presence ETS table and GenServer

Setting up the GenServer

Creating the public interface for the GenServer

Implementing the cast and call logic

Hooking up the GenServer to our application

Storing Presence data in ETS

Retrieving Presence data in ETS

Summary

Working with Elixir's Concurrency Model

Introduction to Elixir's concurrency model

The difference between concurrency and parallelism

In process 1

Run process 1

In process 1

In process 2

Run process 1 and process 2 at the same time

Talking about OTP/understanding the model

Working with an example

Diving deeper into the concurrency model

The model - what is a process?

The model - what if our process crashes?

The model - what is a task?

The model - what is an agent?

The model - what is a supervisor?

The model - what is an application?

Using GenServers

Summary

Implementing OAuth in Our Application

Solidifying the new user experience

Shoring up our tests

Building a good development seeds file

Hooking up our polls index

Adding Ueberauth support

Adding OAuth login support for Twitter with Ueberauth

Setting up our application with Twitter

Configuring the Twitter login process in Phoenix

Modifying the users schema

Implementing the Twitter login in Phoenix

Adding OAuth login support for Google with Ueberauth

Configuring Google to allow OAuth

Configuring Ueberauth in Google

Implementing Google OAuth for Ueberauth and Phoenix

Summary

Building an API and Deploying

Building our API

Building an API in Code

Expanding Our API Request

Authenticating Against our API

Allowing a user to navigate to their profile page

Introducing API keys to the database

Validating API Keys

Dealing with Error Handling in APIs

Implementing an API Resource Show

Adding an Error Handler for 404s for JSON

Deploying Phoenix applications to production

Initial requirements for deployment into production

Alternative Deployment Strategies

Summary

Other Books You May Enjoy

Leave a review - let other readers know what you think

Preface

With Elixir and Phoenix, you build your application the right way the first way: ready to scale and ready for the increasing demands of real-time web applications.

This book will cover the bare basics of the Phoenix web framework through building a community voting application and, in the course, discuss the new structure changes introduced in Phoenix v1.3. We'll cover the initial challenges of getting started with our app, working with the generators to learn more about the structure of a standard Phoenix app. From there, we'll build our application and work with Channels, Schemas, Contexts, and even dive into more advanced topics such as working with Tasks/Async and GenServers. By the end of this book, we'll have a strong grasp of all the core fundamentals of the Phoenix framework, and we'll have built a full production-ready web application from nothing!

Who this book is for

This is for people who have started messing around with Elixir and have enjoyed what they've seen! We'll take those skills and apply them to building a full web application. If you have some knowledge of Elixir and have experience with other web frameworks in other languages and want to see what it's like to build a web application where concurrency and performance are first-class citizens, you're in the right place!

What this book covers

Chapter 1, A Brief Introduction to Elixir and Phoenix, goes over the basics of developing in Elixir and Phoenix and makes the readers understand some of the basic constructs available.

Chapter 2, Building Controllers, Views, and Templates, covers working with the fundamentals of every Phoenix application.

Chapter 3, Storing and Retrieving Vote Data with Ecto Pages, discusses working with data in our database.

Chapter 4, Introducing User Accounts and Sessions, begins to introduce the concept of Users into our system and introduces working with login, logout, and session management.

Chapter 5, Validations, Errors, and Tying Loose Ends, explores working on tightening up our application through validation, error-handling, and general tweaks.

Chapter 6, Live Voting with Phoenix, starts building out a real-time application with Phoenix and JavaScript.

Chapter 7, Improving Our Application and Adding Features, continues to build upon the solid foundation of our application and brings it closer to production-ready.

Chapter 8, Adding Chat to Your Phoenix Application, adds even more real-time feature support.

Chapter 9, Using Presence and ETS in Phoenix, teaches readers to use Phoenix's new Presence support to keep track of what users are logged in or logged out of our system.

Chapter 10, Working with Elixir's Concurrency Model, takes readers through how Elixir handles concurrency implementations at a deeper level.

Chapter 11, Implementing OAuth in Our Application, implements a new way for users to sign in with providers such as Twitter and Google.

Chapter 12, Building an API and Deploying, outlines finishing reading our application, adding an API to interact with our application, and finally finishing deploying our application to production.

To get the most out of this book

Readers should already have at least a basic understanding of the Elixir programming language and some beginner-level knowledge of common web development terms and techniques

You will also need an internet-capable programming environment where you can install required software such as Elixir, Phoenix, Node.js, and Postgres

Download the example code files

You can download the example code files for this book from your account at www.packtpub.com. If you purchased this book elsewhere, you can visit www.packtpub.com/support and register to have the files emailed directly to you.

You can download the code files by following these steps:

Log in or register at

www.packtpub.com

.

Select the

SUPPORT

tab.

Click on

Code Downloads & Errata

.

Enter the name of the book in the

Search

box and follow the onscreen instructions.

Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:

WinRAR/7-Zip for Windows

Zipeg/iZip/UnRarX for Mac

7-Zip/PeaZip for Linux

The code bundle for the book is also hosted on GitHub athttps://github.com/PacktPublishing/Phoenix-Web-Development. In case there's an update to the code, it will be updated on the existing GitHub repository.

We also have other code bundles from our rich catalog of books and videos available athttps://github.com/PacktPublishing/. Check them out!

Get in touch

Feedback from our readers is always welcome.

General feedback: Email [email protected] and mention the book title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].

Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.

Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.

If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.

Reviews

Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!

For more information about Packt, please visit packtpub.com.

A Brief Introduction to Elixir and Phoenix

In this book, we'll walk through the process of building a functional prototype of a social web application that will rely on real-time data updates. If you've ever used any sort of live voting application out there (such as Straw Poll or Twitter Polls), then you're probably pretty comfortable with the idea already. If not, I'll summarize our application so that you know what you're going to be building throughout this book.

Our application will allow users to register for new accounts on our site. From there, they will have the option to create new polls for other users (either while logged in or anonymously) to vote on. We want to make sure that the votes for the polls are recorded and broadcast out to anyone watching the polls in real-time, so we'll take advantage of Phoenix's built-in channel support to provide this.

In addition, our application will allow users to create chat rooms that will be displayed alongside the poll. After they've voted, users will be allowed to chat and discuss the results live as the votes come in. Users will also be allowed to post images, which will be processed,  and uploaded to S3.

Users who create polls will be able to decide who is allowed to vote on their polls; for example, either only logged-in users or any user. Users will be able to modify their polls until they go live.

Users who own the polls should be able to participate in real-time discussions with the people voting on and viewing their polls, including anonymous users. Being able to communicate with each other takes advantage of some of the more advanced real-time concepts that are powering Elixir behind-the-scenes and running separately from the main web portion of our Phoenix application. These concepts demonstrate how we can build larger and more performance-intensive applications!

Now, before we really dive into developing this application, we'll need to make sure we understand some of the tools that are going to help us build this application. The assumption is that you're coming into this with an existing understanding of Elixir, but if not, we will briefly cover some core Elixir concepts while also learning about a tool that will be critical for building a great application in Elixir: the IEx shell and the debugger!

To recap, in this chapter we will cover the following topics:

Basic Elixir concepts

The interactive Elixir shell, IEx

Installing Phoenix

Creating a new Phoenix project with Mix tasks

An introduction to the Phoenix project structure

Introducing IEx and Elixir

We'll start off by talking a little bit about the Elixir programming language that Phoenix sits atop. The most important thing to note, especially if you're coming from another programming language such as Ruby, Go, PHP, JavaScript, or Java, is that there is one significant difference between Elixir and the rest: Elixir is a functional language. While this doesn't change everything dramatically, it does introduce a few gotchas that we will need to get out of the way.

If you're already comfortable with Elixir and IEx, feel free to skip this section, as this is intended to be a quick introduction or refresher to the Elixir language and the IEx debugging tool.

Before we dive too far into those gotchas, let's first get acquainted with a tool that is going to make our development process in Elixir much simpler: IEx.

What is IEx?

The good news: Elixir includes a tool called a Read-Evaluate-Print-Loop (REPL), which is essentially an Elixir shell. You can think of this as being similar to an irb in Ruby or the node shell in Node.js. It is a very detailed and helpful tool that we'll be referring to quite a bit in our journey of building this full web app! To open REPL up (assuming you have Elixir installed), run the following command:

$> iex

You should see something similar to the following snippet appear on your screen:

$> iex

Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.5.0) - press Ctrl+C to exit (type h() ENTER for help)

iex(1)>

Now we can start messing around with some sample Elixir code! Let's start off with a couple of base scenarios.

Understanding the different types in Elixir

Elixir has a number of different built-in types that we'll be working within the course of building our applications. They are the following:

Strings (sometimes referred to as binaries)

Integers

Floats

Lists

Maps

Keyword lists

Tuples

Modules

Functions (functions themselves break into two separate types: module functions and anonymous functions)

Let's take a look at the various representations of these types and use some of the tools in IEx to understand more about what we're working with.

Getting more information with the h helper

IEx also provides us with another incredibly helpful built-in function: h. Similar to i, h has two arities available for us to use: h/0, which displays the help page for IEx, and h/1, which displays the help for a particular module. So, while the following example won't work:

iex(5)> h 5

Invalid arguments for h helper: 5

This following example will:

iex(6)> h Integer

Integer

Functions for working with integers.

Using i and h effectively will go a long way towards helping us understand more of Elixir as we go along!

Introduction to Phoenix

Phoenix is a web framework that sits on top of the Elixir programming language, much in the same way that Rails sits atop Ruby or Express sits atop Node and JavaScript. There are a few areas where Phoenix shares a lot of the same core ideas and beliefs of other frameworks and areas where Phoenix differs pretty heavily.

Phoenix is very much designed to be a standard Elixir application and thus abides by the same rules and the same principles, but also encompasses all of the same things that make Elixir so great to work with! In my mind, the first and biggest thing that Phoenix gets via Elixir is first-class and dead-simple concurrency support. Writing code that performs and scales well on multiple core machines (that is, basically every single computer out there nowadays) is a breeze, and when you're just starting out building your Phoenix application, you won’t even have to think about it. It isn't until you start diving more heavily into the more advanced topics, such as OTP, GenServers, and Async Tasks, where you really need to start thinking deeply about your concurrency models and how everything fits together.

Phoenix also benefits very heavily from being based on a functional immutable language. Large codebases remain very simple to reason with, and the fear of introducing significant breaking changes because of a mutation deeply-nested in your code is now a thing of the past! If you're coming from a language where you've built a complex application and a simple change ends up breaking everything, this should be a breath of fresh air to you. I referenced this in one of my earlier examples, but when you actually see it in action and understand why it works the way it does, trust me, you won't want to go back to the old ways of building applications!

Before we do anything else, let's talk briefly about how to actually install Phoenix so that you can get started on working with it as soon as possible. The best (and most up-to-date) instructions can be found on the Phoenix framework website (https://phoenixframework.org), but just in case, here you are. Please note that the following instructions assume you already have Elixir installed.

Installing Phoenix 1.3

For best results, you'll want to make sure you have the most recent version of Hex installed on your local machine. Again, the assumption here is that you already have Elixir installed on your computer:

$ mix local.hex

Found existing entry: /Users/brandon.richey/.mix/archives/hex-0.16.1

Are you sure you want to replace it with "https://repo.hex.pm/installs/1.5.0/hex-0.17.1.ez"? [Yn] y

* creating /Users/brandon.richey/.mix/archives/hex-0.17.1

Now we'll move on to installing Phoenix itself. Installing Phoenix is a little bit different from just installing something via a hex package on an existing Elixir project. You'll want to use Phoenix’s project generators to get your project up and running, as there is a lot of additional setups required compared to a small, standard Elixir project. This is why you need to go through a separate process to install Phoenix.

To install the Phoenix framework and get access to the Mix tasks needed to create new Phoenix projects, you'll want to run the following code:

$ mix archive.install https://github.com/phoenixframework/archives/raw/master/phx_new.ez

* creating /Users/brandon.richey/.mix/archives/phx_new

Creating a new Phoenix project

Now that we have something in place to help us understand Elixir and Phoenix and we've installed everything necessary, we can start to discuss how to actually begin implementing our first project in Phoenix. To get started on a project and generate the Phoenix application skeleton we'll need to start developing, we'll run a special command using the installed Mix application that came with Elixir. We also added the Phoenix Hex archive to our local Hex installation, so we should have access to a few new Phoenix-specific Mix tasks, such as mix phx.new!

Running the Phoenix Mix Task

Phoenix has gone through a few iterations of general architecture and project structures, but as of version 1.3, they've stuck on a design that is incredibly elegant and easy to use. Instead of the sometimes clumsy system they previously had, where you had your models, your controllers, your views, and your templates and nothing in between, you can now design things around controllers, views, templates, contexts, and schemas. Before we start diving into what those differences are and why they’re so important, let's talk about the general project structure of a Phoenix application.

The first major thing is that Phoenix applications are considered first-class Elixir projects, so as such follow the same major rules. Generally, Elixir projects should have a test directory and a lib directory. Your test directory is where any new tests you write and any tests you run will live out of lib, on the other hand, is where the actual code for any actual work should go. Let's explore how these directories will get filled out by creating a small sample throwaway Phoenix application.

To create a new Phoenix application, we'll start off by running the mix task phx.new:

$ mix phx.new sampler

* creating sampler/config/config.exs

* creating sampler/config/dev.exs

* creating sampler/config/prod.exs

* creating sampler/config/prod.secret.exs

* creating sampler/config/test.exs

* creating sampler/lib/sampler/application.ex

* creating sampler/lib/sampler.ex

* creating sampler/lib/sampler_web/channels/user_socket.ex

* creating sampler/lib/sampler_web/views/error_helpers.ex

* creating sampler/lib/sampler_web/views/error_view.ex

* creating sampler/lib/sampler_web/endpoint.ex

* creating sampler/lib/sampler_web/router.ex

* creating sampler/lib/sampler_web.ex

* creating sampler/mix.exs

* creating sampler/README.md

* creating sampler/test/support/channel_case.ex

* creating sampler/test/support/conn_case.ex

* creating sampler/test/test_helper.exs

* creating sampler/test/sampler_web/views/error_view_test.exs

* creating sampler/lib/sampler_web/gettext.ex

* creating sampler/priv/gettext/en/LC_MESSAGES/errors.po

* creating sampler/priv/gettext/errors.pot

* creating sampler/lib/sampler/repo.ex

* creating sampler/priv/repo/seeds.exs

* creating sampler/test/support/data_case.ex

* creating sampler/lib/sampler_web/controllers/page_controller.ex

* creating sampler/lib/sampler_web/templates/layout/app.html.eex

* creating sampler/lib/sampler_web/templates/page/index.html.eex

* creating sampler/lib/sampler_web/views/layout_view.ex

* creating sampler/lib/sampler_web/views/page_view.ex

* creating sampler/test/sampler_web/controllers/page_controller_test.exs

* creating sampler/test/sampler_web/views/layout_view_test.exs

* creating sampler/test/sampler_web/views/page_view_test.exs

* creating sampler/.gitignore

* creating sampler/assets/brunch-config.js

* creating sampler/assets/css/app.css

* creating sampler/assets/css/phoenix.css

* creating sampler/assets/js/app.js

* creating sampler/assets/js/socket.js

* creating sampler/assets/package.json

* creating sampler/assets/static/robots.txt

* creating sampler/assets/static/images/phoenix.png

* creating sampler/assets/static/favicon.ico

Fetch and install dependencies? [Yn]

We'll now be asked if we want to fetch and install dependencies. If we say yes, a few things will happen:

First off, all of the standard Elixir dependencies that exist for all Phoenix applications will be downloaded from

hex

and compiled.

Next, all of the Node/JavaScript dependencies that Phoenix applications depend on (assuming you did not use the

--no-brunch

flag when you created your new Phoenix application) will be downloaded from

npm

and compiled.

Assets will be built and set up appropriately via Brunch.

If we say yes, we should see something akin to the following output:

* running mix deps.get

* running mix deps.compile

* running cd assets npm instal node node_modules/brunch/bin/brunch build

We are all set! Go into your application by running:

$ cd sampler

Then configure your database in config/dev.exs and run:

$ mix ecto.create

Start your Phoenix app with:

$ mix phx.server

You can also run your app inside IEx (Interactive Elixir) as:

$ iex -S mix phx.server

When everything is done, we can enter our new project directory, create our database, and start up our Phoenix server!

$ cd sampler && mix ecto.create

Compiling 13 files (.ex)

Generated sampler app

The database for Sampler.Repo has been created

To create a database, you will need to have a username and password set up for your database server of choice that has the correct permissions or roles assigned that allow you to create databases. If you are working with a role or user that does not have that permission, you can also create the database manually and instead run mix ecto.reset.

Running the Phoenix server for the first time

There are two ways to start up the Phoenix server, and now that the application is set up and the database is there to support our application, we can move on to actually running it! The two different ways to run your application are either via Mix phx.server or in the IEx console. In the context of your application requiring debugging support via IEx, you need -S Mix phx.server. As a general rule, I only run my application in a local development environment through IEx. This allows you to get interactive debugging via IEx.pry, as well as the ability to perform things like Ecto queries or test calling public functions in modules.

Remember when we talked about the interactive help functions that are built-in to Elixir and can be accessed via IEx? Well, you can do the same thing with Phoenix functions, too! For example, let's say we want to know a little more information about how we send out JSON content directly from a controller, as shown in the following example:

iex(4)> h Phoenix.Controller.json

def json(conn, data)

Sends JSON response.

It uses the configured :format_encoders under the :phoenix application for

:json to pick up the encoder module.

## Examples

iex> json conn, %{id: 123}

Okay, so we now have our application and we have things up and running. If we visit our browser window, we should see the Phoenix startup page, as follows:

Phoenix's default application structure

As mentioned previously, Phoenix is itself a full-featured Elixir application, and as a result, tends to follow a lot of the same conventions and rules that other Elixir applications follow. We’ve briefly touched on the topic previously, but now it's time to get into it and take a look at how Phoenix projects are structured so that we can understand how to build on top of Phoenix. The starting directory structure looks a little something like the following:

├── README.md├── assets│ ├── brunch-config.js│ ├── css│ ├── js│ ├── package.json│ ├── static│ └── vendor├── config│ ├── config.exs│ ├── dev.exs│ ├── prod.exs│ ├── prod.secret.exs│ └── test.exs├── lib│ ├── testapp│ ├── testapp.ex│ ├── testapp_web│ └── testapp_web.ex├── mix.exs├── priv│ ├── gettext│ └── repo└── test ├── support ├── test_helper.exs └── testapp_web

Configuration files

First, we have a config directory in the root of our Phoenix application. This is where all of the application and web service configuration files will live. We typically have the config.exs, dev.exs, test.exs, prod.secret.exs, and prod.exs files by default with our Phoenix application. The first file, config.exs, is a file that stores generic configuration details that should be the same across all run-time environments for your application, whether they're testing, development, or production environments. The next few (dev.exs, test.exs, and prod.exs) are your environment-specific configuration files. Finally, we have our prod.secret.exs, which is auto-generated by Phoenix but not checked into source control by default. This file should never be checked into the source control for your application, as this is where sensitive information should live, such as API keys, secret keys, and database passwords. If this is ever checked into source control then it would be in the history of your application, which would be a pretty significant security concern for anyone having to maintain your Phoenix application!

Assets files

Next, we have our assets directory. This is where all of the front-end assets (images, CSS, JavaScript, and so on) live, as well as Brunch and NPM. (Your node_modules directory, for example, is found here.) The idea here is that by divorcing your front-end code and files from the rest of the work that Phoenix needs to do, Phoenix's developers can instead focus on making Phoenix great and leave the front-end and asset compilation problems to better solutions such as Brunch or Webpack, as well make asset compilation tool choices separately from those that created the framework. Even though Phoenix comes with Brunch by default, it's still straightforward to replace it with Webpack if that’s more suited to your speed.

Private files

There is also a priv directory, which is a little trickier to explain. Priv contains a lot of the helper and application setup code that is required. This contains your Repo's seeds file and migrations that need to be run (which we'll cover later), translations to your application via gettext, and finally, your static asset files (which have been built/compiled/transpiled/etc from your assets directory).

Tests

Your test directory contains all of the ExUnit tests for your application, which itself is broken up into two starting directories: (application name)_web and support (plus a test_helper Elixir script that contains some initialization code). (app)_web is used to contain the web application tests that cover controllers, contexts, views, templates, and so on, so you can think of this as the container for all of your Phoenix application tests. Support is instead used to bolster the functionality of your tests and make it easier to write new tests and share common logic or helpers. For the most part, we won't be modifying the code inside here very often. Most of the changes that we're going to make will instead be in the test/(app)_web directory and sub-directories.

Other directories

We also have a few miscellaneous directories that you won't really be interacting with at all. _build and deps, for example, contain various build artifacts and Elixir application dependencies (these won't actually get created until you build your application).

The most important directory: lib

Now we'll move on to the real meat of our Phoenix application: lib. Lib is where our application lives. By default, our Phoenix application is broken into two separate ideas. Using the application name of Sampler as an example, we will see two directories: lib/sampler and lib/sampler_web. The idea behind this is that every web application in Phoenix has at least two separate applications that work together to get the job done. The first is divorced from the idea of anything web-related, so there are no controllers or templates, JSON, or anything similar. One of the most common patterns that you’ll see here is all of your database-specific Ecto logic through contexts and schemas.

A context is a collection or boundary of domain-specific logic. For example, if you have users and organizations in your project, you may have a unifying context to those separate schemas called something like Accounts.

A Schema, on the other hand, is the one-to-one mapping of a database table to an application concept. Schemas need to be separated from the functionality of your code and used strictly to describe the shape of the data; this keeps your code pure from side-effects and helps make your code significantly easier to test in the long run.

Finally, we have lib/sampler_web. This is where all of the Phoenix-specific work gets done, so everything related to controller logic, templates, or views goes here in the appropriate sub-directory. Channel logic also falls underneath this particular design pattern. This is also where the endpoint.ex file lives, which defines how Plug constructs the Phoenix response to browser/API consumer/etc. It also determines how requests are parsed and how information is passed along to the Phoenix router.

Speaking of the router, our Phoenix router.ex file also lives here (again, because this is Phoenix-specific logic rather than the overarching common application functionality). This is where we will set up all of the rules to describe how to communicate between the browser and Phoenix's controllers.

A note about how data flows in Phoenix

If you're coming from the world of another web framework you might already be familiar with languages such as routers, controllers, templates, and views, but if you're not, let's talk a little bit about what those are, what they mean, and how the data flows in a Phoenix request all the way back out to the browser response. If you're already familiar with these topics, feel free to skip ahead to the next chapter.

When a request is received to a Phoenix application, the first thing that happens is that it gets handled by the endpoint. The endpoint's job is to take a look at the requests and to determine if there are any special functions or handlers that need to deal with the request. The request will flow through a series of plugs. A plug is a set of functionalities that takes in the connection data structure and performs a series of transformations and queries against the incoming request (for example, determining if the originator of the request is an approved server or making sure that the content types make sense). A plug must always take in a connection data structure (typically referred to as conn) and return out a conn, either modified or not. It can also additionally take in a set of options to determine how to modify the conn.

From there, the conn gets moved into the router via the endpoint. The router figures out where the information is coming from and where it is trying to get to. This is done via a combination of the URL hit, the content type, and so on. From here, if a valid route is found, the router will pass the conn on to the controller. A controller's job in a Phoenix application is to provide a means of determining what further transformations need to occur on the conn (which will eventually become our response from the server), as well as doing additional application logic such as running database queries, putting together templates, setting HTTP status codes, and much more. We can think of this as the glue for the different parts of our application that will help us construct our server's response.

The controllers then tell the view how to put together the data in the response and pass along the information it needs to determine the overall shape and feel of the response. It might be a JSON data structure if we're working with an API, or it may be a particular HTML template that we're sending back to the user with further information that is then sent along to the template. We can think of it as if the router answers where the controller answers what, and the view answers how. If we're not working with something simple, such as a JSON API, then there is an additional step that we have to work through called the template. The template helps Phoenix understand how, given a connection object, to build a response and what response to build, and a set of data to pass along to the consumer to build the logic that provides the nice look and feel we'd expect of a modern web app sending back HTML with layouts, partial pieces of content, and an overall structure.

Summary

We should now have a fine working knowledge of a standard Phoenix application. We should now understand how the application's structure, what the different pieces of the Phoenix application are, and how they're all used in conjunction to send something back to the browser when we, for example, send a request to http://localhost:4000/.

In the following chapters, we'll dive more into each of the functional areas of a Phoenix application and understand them at an even deeper level than this. Given that we have a strong foundation, we now need to move on to the real way to learn Phoenix: by building a new Phoenix application from start to finish!

Building Controllers, Views, and Templates

This chapter is focused on the building blocks of any Phoenix application. By understanding what controllers, views, and templates are (and how they interact), it becomes much easier to build out our web application. We'll tackle this through the perspective of building the first major component of our Live Voting application, and by writing tests to cover the new functionality introduced.

The reader will become proficient in a lot of the basic tenets of using controllers, views, and templates. In addition, the reader will learn how the three pieces fit together via functional composition. Finally, they'll begin diving into writing their first tests covering controllers and views to start enforcing a strong and real-world systems development life cycle (SDLC). This will be from the perspective of building an actual application, so we'll start laying the framework for our voting app.