Coder Social home page Coder Social logo

dwyl / learn-phoenix-framework Goto Github PK

View Code? Open in Web Editor NEW
637.0 32.0 45.0 838 KB

:fire: Phoenix is the web framework without compromise on speed, reliability or maintainability! Don't settle for less. :rocket:

JavaScript 10.05% Elixir 81.15% CSS 0.16% HTML 8.63%

learn-phoenix-framework's Introduction

Learn Phoenix (Web App) Framework

phoenix framework logo

Learn how to use Phoenix Framework to have fun building real-time web/mobile apps
that are fast for "end-users", reliable, scalable, maintainable and (easily) extensible!

Why?

As web/mobile app developers we need to leverage the work that other (really smart) people have done
instead of constantly building things "from scratch" all the time; that is why we use frameworks to build our apps!

See: "Top 10 Reasons Why Phoenix" (further down this page!)

There are many frameworks to choose from (a few "popular" ones are mentioned below in the "Questions" section).
But if we go by what is "popular" we would still be riding horses (and carts) everywhere and no progress would be made.

Note: all the reasons "Why" for Elixir also apply to Phoenix!
check them out: https://github.com/dwyl/learn-elixir#why

What?

A web application framework without compromise!

Developer Joy

The biggest "constraint" in any technology project is people. An "Entrepreneur"/"Founder" or "Product Owner" can have all the good ideas in the world, if they are unable to convert idea into reality, it's meaningless.

(Should I Care About) Benchmarks?

Obviously, you should run your own benchmarks on your own hardware/cloud and make informed decisions based on the requirements of your app/product, but ... when we read the stats for how many concurrent users a Phoenix App can handle (with live WebSocket connections) we were blown away! It means we can build our real-time app(s) with 90% fewer resources.

Performance Highlights

  • considerably lower latency and request response time than anything else! (thanks to Erlang's lightweight processes and ultra-efficient network/message handling)
  • 4x more requests-per-second than the equivalent Node.js (Express.js) App.
  • 9x more throughput than a Python 2.7 based app. (blocking really sucks!)
  • 10x - 100x more requests handled than Ruby-on-Rails (depending on the type of app!)
  • Similar performance to Go on a single server, but a much simpler multi-server concurrency model, so horizontal scaling across multiple data centers ("availability zones") is much easier! (Erlang manages the resources for multiple servers/processors as a single app "fleet" and delegates requests/processing to them across clusters/zones!)

All of this means that you spend considerably less money on Hardware/Cloud infrastructure so your app/company can gain a competitive advantage on cost.

If you are in the fortunate position to be considering using something way better for your next project, look no further than Phoenix!
Read more: http://www.phoenixframework.org

Who?

Many people/teams/companies are already using Erlang/Elixir and Phoenix and seeing phenomenal results!
Including: Adobe, BBC, Spotify, Pinterest, Discord (Gamer Chat App), Groupon (Fave), Lonely Planet, Brightcove, Slack ...
See: https://github.com/doomspork/elixir-companies

Who Should Learn Phoenix?

  • People who want an easy way of building an app with all the modern conveniences of "generators", built-in Database interface ("ORM") and Firstclass WebSockets for "real-time" while getting legendary reliability.
  • Teams who need the developer productivity or Ruby-on-Rails or Django, but want less "magic" (i.e. want to understand how everything works!).
  • Companies who want to spend 90% less on both developer and infrastructure costs so you can serve more people with fewer resources.

Who Should NOT Learn Phoenix?

  • Anyone who needs to use the "most popular" framework or language (for whatever reason).
  • Companies who already have lots of legacy Java/PHP/etc. and cannot invest the time to learn/use something new.
  • Developers who want "job security" bug-fixing unreliable code.

How?

Assumptions / Pre-Requisites?

Elixir

You cannot build a Phoenix App without knowing Elixir.
If you are new to Elixir, "star" (bookmark) this repo (so you can return to it tomorrow)
and then go to: github.com/dwyl/learn-elixir learn elixir until you feel like you understand the syntax, then come back and learn Phoenix!

Specifically you should focus on learning the Elixir "Basics":

  • types of data
  • atoms
  • pattern matching
  • maps
  • function definitions
  • modules

Node.js

Phoenix uses Node.js to compile assets like JavaScript and CSS files (using Webpack).
Simply ensure you have Node.js installed. https://nodejs.org
You don't need to know Node to use Phoenix.

Installation

If you've already learned some Elixir and installed Node.js, then the first step to getting started with Phoenix is installation!

The Phoenix documentation is amazing, so we recommend following the official phoenix installation instructions!

You'll also need to install PostgreSQL, there is a tutorial of how to do so linked in the Phoenix installation guide linked above, but you can also check out our learn-postgresql repo for instructions, and raise an issue if you have any trouble!

While a basic understanding of JavaScript can be useful at times, you don't need to know how to use Node to use Phoenix.

If you're curious why they chose Brunch.io over "alternatives",
the short answer is: Simplicity & Speed! see: http://brunch.io/docs/why-brunch
Note: Phoenix v1.4 (unreleased at the time of writing) uses WebPack for asset compilation, see: CHANGELOG.md

Next?

Familiarize yourself with the "Up and Running" (official) guide: https://hexdocs.pm/phoenix/up_and_running.html#content up-and-running

Practical Examples?

Once you have phoenix installed and followed the official "up and running" guide,
come back and try these beginner-friendly examples:

Book?

We recommend that people buy (or borrow) @chrismccord's book: "Programming Phoenix"
see: https://pragprog.com/book/phoenix14/programming-phoenix-1-4
phoenix-book-screenshot
The authors are individually impressive and collectively they comprehenisively cover Phoenix like nobody else can! Chris created Phoenix, José created Elixir and Bruce is ultra-experienced technical author with many successful books to his name!
(i.e: the book is the obvious choice for how to learn Phoenix!)


Video Intro by José Valim (Creator of Elixir)

Jose Valim - Phoenix a web framework for the new web
https://youtu.be/MD3P7Qan3pw

ElixirConf 2016 - Keynote by José Valim
https://youtu.be/srtMWzyqdp8


Resources




Our Top 10 Reasons Why Phoenix

"Phoenix provides the productivity of Ruby-on-Rails
with the concurrency and fault-tolerance of Erlang
."

  1. Beyond all the (fantastic) technical benefits, what attracts us to Phoenix is the Great Community of people around the world who are excited about making Phoenix an amazing tool for building web apps!
    Having welcomming people who will

  1. Phoenix uses the Elixir programming language which means your app is compiled and run on the Erlang Virtual Machine "BEAM".
    Erlang is a battle-tested highly fault-tolerant VM used by many telecommunications companies

  2. WebSockets ("channels") are built-in to the framework which means building apps with "real-time" communication and interaction is much easier than virtually any other framework/platform! (no third-party magic module needed! everything you need is already there ready for you to serve millions of people!!)
    see: http://www.phoenixframework.org/docs/channels

  3. Easy asyncrhonisity because all programming in Phoenix (Elixir) is Functional! This means it's really simple to abstract useful functionality like request authentication, logging and processing into "piplines" that are easily human-readable! (no third-party async module required! no "promises", "generators" or "observables" to managed!!)

  4. Security & Resilience Mindset is the default. Encryption (SSL) is easy in Phoenix/Elixir and both mitigation of SQL injection, Cross-site Scripting (XSS) and CSRF protection are built-in (enabled by default) so it's virtually impossible for a "novice" programmer to introduce this type of security bug.

  5. Concise Code cannot be understated! We can write way fewer lines than in the equivalent Node.js/Java/Rails/Go app, this means developers are more productive and there is less code to maintain!

  6. Testability due to functional programming of all controllers!

  7. Easy Deployment: https://hexdocs.pm/phoenix/heroku.html

  8. Zero-downtime Deployment is free! (again because of Erlang). Erlang manages transitioning "live/active" users from the old to new version of your app without them even noticing that it was upgraded/updated!!

  9. Built-in Monitoring/Managment of your app through Erlang supervisors mean that you know exactly how your app is performing, what parts have crashed/restarted and why! This is a feature we pay (a lot) for in other frameworks and here it's free!!

Can you think of another reason why using Phoenix is awesome?!
Please Share your thoughts in this thread: #13




Questions?

Do I need to learn Elixir before trying/using Phoenix?

Yes. See: https://github.com/dwyl/learn-elixir

Do I Need to know Erlang to use Elixir & Phoenix...?

No. You can start learning/using Elixir today and call Erlang functions when required,
but you don't need to know Erlang before you can use Phoenix!

But Phoenix is not "Mainstream" ... Should I/we use it...?

There are many web application frameworks you/we can choose from: https://en.wikipedia.org/wiki/Comparison_of_web_frameworks
So why would anyone select a framework written in a programming language that is not "mainstream"...?

Why are we not using Hapi.js anymore...?

This is missinformation. We are still using Hapi.js for a number of projects where it is appropriate.
This includes several client projects and internal dwyl apps/tools.

We decided to use Phoenix for our new projects for these simple reasons:

  • Elixir is a nicer language than JavaScript. #LessIsMore #LessButBetter #SmallIsBeautiful #SyntaxMatters
  • JS can be functional, whereas Elixir is (always) Functional! The distinction makes all the difference!
    With "functional" programming, the programs are a lot easier to think about while you are writing/maintaining them!
  • Elixir uses the Erlang VM which is way more efficient/powerful than "V8"
  • The Erlang VM scales much easier to multi-core multi-server multi-data-center than Node.js
    (or pretty much anything else for that matter!!)

For our new projects we need multi-data-center fault-tolerance!
we get that "for free" by using Erlang -> Elixir -> Phoenix
!!

In our opinion Hapi.js is still "the best" Node.js framework and we will continue to use and recommend it
to people that need simple apps that scale and are easy to maintain.
see: https://github.com/dwyl/learn-hapi

Also we still use JavaScript for all our AWS Lambda Micro-Services, that is not going to change.
They are simple, efficient and scale really well!
see: https://github.com/dwyl/learn-aws-lambda

What's "Wrong" with using Rails or Django?

The original "productive" web frameworks were "Ruby-on-Rails" and "Django" (python) back in 2005!
(We used both of these for periods in our "journey" and can speak on the advantages of each of them!)

There is "nothing wrong" with using Rails or Django.
We think there are still plenty of use-cases for both frameworks.
We just know that it's (a lot) easier to build "real-time"
with Phoenix because "Channels" (WebSockets) are baked in,
and the Elixir/Erlang concurrency is a whole different ballgame!
Erlang (and thus Phoenix) can handle millions of concurrent users on a single server,
whereas a Rails/Django server can only handle a few thousand (at best!)
if your app is only serving a few thousand people at once, then you're fine!!

We love the fact that Erlang uses "lighweight long-lived" processes,
which means we can connect millions of (IoT) devices ... For IoT Erlang is (unquestionably) the Answer!
For simpler web apps where you only expect a few users per day, Rails/Django are still viable.

But why compromise if you don't have to?
If you can have a Tesla for the "price" of a Ford Focus, why wouldn't you?!?
Why settle for good when you can easily have/use the best?

But GitHub Still Uses Rails ... Surely GitHub is "Scalable"?

Yes, GitHub is still using Rails for their Web App/Site.
But ask any of the core team at GitHub if (given the chance to start over) they would chose Rails
to build GitHub in 2017, and see how many of them say "yes, of course" (with a straight face...)!

Also, GitHub does a lot of things to Scale Rails in the background.
And many of their newer (client-side) features are written in JavaScript! see: https://github.com/github

Bottom line is: anything can be made to scale using "DevOps",
but Phoenix is made to scale by default because Erlang (was) invented (to) scale!

Why NOT Use Go?

"There are two kinds of programming languages - those that nobody uses and those that everybody's bitching about" ~ Bjarne Stroustrup (creator of C++)

Go is very popular. Largely due to the fact that Google "sponsors" it.
It was meant to simplify (replace) C++ and Java inside Google ...
and for the most part, it has succeeded!

We really like Go. It was our "number two" choice when deciding what programming language
(after Elixir) in our "post JS stack"... The decision to use elixir instead of anything else was easy:

  • Elixir is functional (much simpler to read/write/maintain/extend)
  • Elixir functions compose in a really elegant way as "plugs"/"pipelines"
  • Data is immutable which makes application state predictable (no guessing!)
  • Types are dynamic and inferred (no need to manually declare them) but there are rules which simplify things and the compiler checks them giving an appropriate warning.
  • Erlang makes distributed apps much easier and our plan is to build IoT systems that will mean connecting many (millions) devices with persistent connections, Erlang was made for this!
  • Phoenix includes many useful things out-of-the box including several security features most people won't even think of.

Further Reading:


(`help wanted` expanding this answer...)

Why NOT Use Scala + Play Framework instead...?

If you are already used to writing Java or deploying to the JVM, the Play Framework is a superb choice: https://www.playframework.com
Scala is a good programming language and everyone should learn it! https://www.scala-lang.org/what-is-scala.html

We have used Play a few times (before we adopted Node.js) and really liked it!
But Scala is a "kitchen sink" (multi-paradigm) programming language that allows people to use "all of Java" ...
We think Scala's "Java Interoperability" means it's "too easy" to allow complexity into your codebase. Specifically "OOP Mutation" ...

So why aren't we (DWYL) using "Play" for new projects any more? Firstly, we transitioned to Hapi.js (Node.js) a few years ago because it was more "lightweight" and allowed us to write tiny programs that used only a few Megs of RAM (where our Play apps were very resource-hungry..! have you ever tried running a Scala app on a "basic" laptop like a Chromebook...?)

Summary of "reasons" for Phoenix instead of Play:

  • We maintain that Play/Scala still has plenty of valid use-cases.
  • Elixir is way simpler than Scala.
  • The Erlang VM is way better at concurrency than the JVM.
  • We love the fact that all data is immutable in Elixir.
  • We love how few resources it takes to run a Phoenix app (e.g on a Raspberry Pi!!)

We just think that for our project(s) Erlang's Concurrency model works better and Functional code transforming Immutable data is easier to test and maintain.

If you have evidence that "Scala is Simpler" we would love to hear from you!
Tell us: https://github.com/dwyl/learn-phoenix-web-development/issues

Why not use Haskell?

If you like Functional Programming (FP) so much, why not use Haskell?

learn-phoenix-framework's People

Contributors

abdur-rahmaanj avatar changjoo-park avatar cleop avatar faraazahmad avatar iteles avatar jay-meister avatar jbarget avatar katbow avatar modernconstructionservices avatar nelsonic avatar padmajs avatar robstallion avatar samhstn avatar shouston3 avatar simonlab avatar zooeymiller avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

learn-phoenix-framework's Issues

tutorial - first stages

@RobStallion and I were thinking of creating a walkthrough aimed at getting someone started with phoenix, ending with deployed mini application

Some possible stages the walkthrough could follow:

  • installation
  • new route, controller, view & template
  • basic login flow with some hardcoded user in the login action
  • replace hardcoded user with use of database using ecto
  • deploy

Further improvements:

  • testing
  • sockets

@nelsonic what do you think of this as an initial scope?

How to run a "raw" SQL query using Ecto.Adapters.SQL.query

On page 119 of Programming Phoenix there's an example for how to write a "direct" SQL query:

Ecto.Adapters.SQL.query(Rumbl.Repo, "SELECT, power($1, $2)", [2, 10])

This does not SELECT any data from the database it (is meant to) merely calculate 2^10 which should return 1024 ... instead we see:
image

It's not a DB/connection error because other queries work! e.g:
image

So... I'm left scratching my head as to how to run an SQL query using Ecto ...
has anyone else attempted to do this?

Passing action along in form with multiple pages

I have a form with name and email (form1) on one page, which is inserted into the db, then goes to a second form (/signup2) to fill in password and security Q&A. The first page was loading as expected and the name & email was being properly inserted into the database upon clicking "Next".

However, when it was redirected to /signup2 there would be an error:

assign @action not available in eex template.
Please make sure all proper assigns have been set. If this
is a child template, ensure assigns are given explicitly by
the parent template as they are not automatically forwarded.
Available assigns: [:changeset, :conn, :current_user, :view_module, :view_template]

So the trouble seemed to be that in /signup2 there was no action. The create controller that inserted the input from form1 and redirected to /signup2 was as follows when the error was occurring:

  def create(conn, %{"user" => user_params}) do
    changeset = User.changeset(%User{}, user_params)

    case Repo.insert(changeset) do
      {:ok, _post} ->
        conn
        |> redirect(to: user_path(conn, :signup2, changeset: changeset))
      {:error, changeset} ->
        render(conn, "new.html", changeset: changeset)
    end
  end

When the changeset was inspected, the action was set to nil.

We tried setting this by adding assign to the pipe, but assign kept coming back as an undefined function:

{:ok, _post} ->
        conn
        |> assign(action: :some_action)
        |> redirect(to: user_path(conn, :signup2, changeset: changeset))

The solution was to render the signup2.html and pass in the action directly.

{:ok, _user} ->
        render(conn, "signup2.html", changeset: changeset, action: :some_action)

Ecto testing 100% Coverage

When striving to get 100% coverage, the schema line sometimes fails
screen shot 2017-03-06 at 16 30 21

I have found this line in your models test impossible to consistently cover (without ignoring the file from coverage)

See the progression of the problem in our application here: InclusiveClassrooms/skills-wheel#63

test for logged-in users using ExUnit tags

Tried to run the test on p.139 using: mix test test/controllers --only login_as
got:

  1) test lists all user's video on index (Rumbl.VideoControllerTest)
     test/controllers/video_controller_test.exs:36
     ** (RuntimeError) expected response with status 200, got: 302, with body:
     <html><body>You are being <a href="/">redirected</a>.</body></html>
     stacktrace:
       (phoenix) lib/phoenix/test/conn_test.ex:362: Phoenix.ConnTest.response/2
       (phoenix) lib/phoenix/test/conn_test.ex:376: Phoenix.ConnTest.html_response/2
       test/controllers/video_controller_test.exs:41: (test)

Screenshot:
image

p.167 when adding the defimpl to_param we get ** (FunctionClauseError) no function clause matching in Phoenix.Param.Rumbl.Video.to_param/

before adding the defimpl on page 167 the tests run fine:
image

But once we adde the code:

defimpl Phoenix.Param, for: Rumbl.Video do
  def to_param(%{slug: slug, id: id}) do
    "#{id}-#{slug}"
  end
end

to: rumbl/web/models/video.ex

and re-run the tests we get the error:

test/views/video_view_test.exs:5
     ** (FunctionClauseError) no function clause matching in Phoenix.Param.Rumbl.Video.to_param/

image

Failing test 1:
image

Failing tests 2 & 3:
image

Googling ... 🔍

Logging/Debugging Phoenix Apps |> What are the options? |> Can we use ElasticSearch + Kibana?

Logging is an incredibly important activity for any web application, 🔥
but sadly, one of the things most people only think about when things "go wrong"... 😿

no logs

Our goal is to be able to:

  • Read the logs in a human friendly format without scrolling through mountains of plaintext
  • Search/Filter logs
  • Correlate/Trace all logs for a given request together (this isn't an issue if the app has only a handful of users/requests per minute but is essential when we have multiple request per second and we need to "trace" a given request through the stack to understand where/when it's failing...!)

I was considering pushing the log to ElasticSearch asynchronously (not interrupting the flow of execution) which could then be viewed in Kibana (in the browser).

We used "ELK" @ TC and it worked well for tracing logs through our stack using a "correlation ID" for a given request. see: https://www.elastic.co/videos/kibana-logstash

@jruts / @tonydaly / @katbow / @SimonLab / @Shouston3 / @jackcarlisle / @des-des / @Jbarget
have you come across a good logging tool/solution for Elixir/Phoenix ?

We are going to need logging in all our apps so this discussion is relevant to everyone building apps with "PETE". Also having logging/tracing as a skill will seriously help you "level up". 🥇

I just came across this while trying to debug something for "dwylbot" and noted that
2e are not currently logging the Webhook payloads in /web/controllers/webhooks_controller.ex so this is an immediate pain I have ...
but it's also a requirement for all our client/internal projects ASAP! 💸

Database errors with `mix ecto.create` or `mix phoenix.server`

Postgres server not running

If you run mix ecto.create and see this:

screen shot 2017-03-05 at 18 11 40

or if you run mix phoenix.server and see this:

screen shot 2017-03-05 at 18 11 23

then it means your postgres server isn't running. You can fix this by running postgres -D /usr/local/var/postgres/

Invalid username and password

If you see an error like this:

screen shot 2017-03-05 at 17 45 52

it is likely that the username and password towards the bottom of your config/dev.exs dont match your local machine's postgres username and password.

If you know your postgress username and password then you'll need to change the values for those fields in config/dev.exs. If you don't know your username and password for postgres you will need to reset them. Look here for details

Add documentation on `mix ecto.create` error

I had issues when running mix ecto.create that were caused by 2 separate issue:

  1. postgres server not running
  2. username and password incorrect for postgres config

will write up an issue and reference it in the simple-server.md

PS. will need write privileges to the repo

Hello world example

The hello world example in the programming phoenix book generates lots of boiler plate and gives you much more than you would get in a traditional hello world app. ie db integration, xss protection and much more. Can we find something more minimal? Can we use the phoenix framework without using auto generated boiler plate, so we can give a user an example of a hello word app with a minimal code base..

I am not sure if in this case, we would want to drop down and just use plug. This might be an option, since phoenix is built on plug..

...warning: `Ecto.Changeset.cast/4` is deprecated, please use `cast/3` + `validate_required/3` instead

running mix test on page 134
but get the following warning message:

...warning: `Ecto.Changeset.cast/4` is deprecated, please use `cast/3` + `validate_required/3` instead
    (rumbl) web/models/video.ex:22: Rumbl.Video.changeset/2
    test/models/video_test.exs:15: Rumbl.VideoTest."test changeset with invalid attributes"/1
    (ex_unit) lib/ex_unit/runner.ex:296: ExUnit.Runner.exec_test/1
    (stdlib) timer.erl:166: :timer.tc/1

.warning: `Ecto.Changeset.cast/4` is deprecated, please use `cast/3` + `validate_required/3` instead
    (rumbl) web/models/video.ex:22: Rumbl.Video.changeset/2
    test/models/video_test.exs:10: Rumbl.VideoTest."test changeset with valid attributes"/1
    (ex_unit) lib/ex_unit/runner.ex:296: ExUnit.Runner.exec_test/1
    (stdlib) timer.erl:166: :timer.tc/1

image

Looked at: https://hexdocs.pm/ecto/Ecto.Changeset.html

tried changing the code in web/models/video.ex:20-25 from:

  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, @required_fields, @optional_fields)
    |> assoc_constraint(:category)
  end

To:

  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, @optional_fields)
    |> validate_required(params, @required_fields)
    |> assoc_constraint(:category)
  end

or:

  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [@required_fields, @optional_fields]) # cast all fields as a single list
    |> validate_required(params, @required_fields)
    |> assoc_constraint(:category)
  end

but tests failed:
image

figured I need to call cast on all the fields as a single list.
read http://learningwithjb.com/posts/concat-lists-with-elixir
So changed to:

  @required_fields ~w(url title description)
  @optional_fields ~w(category_id)
  @all_fields ~w(url title description category_id) # obviously not "DRY"

  @doc """
  Builds a changeset based on the `struct` and `params`.
  """
  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, @all_fields)
    |> validate_required(@required_fields)
    |> assoc_constraint(:category)
  end

and ran: mix test and got:
test fail

I would like to continue spending time on this but I suspect that it will become clear to me later in the book or through more practice/understanding so I'm just going to leave this issue open in case someone else knows how to "fix" it ...

Trying to execute a single ExUnit test

Tried using the code in the book on p.131. (copied verbatim):

defmodule MyTest do
  use ExUnit.Case, async: true

  setup do
    # run some tedious setup code
    :ok
  end

  test "pass" do
    assert true
  end

  test "fail" do
    assert false
  end
end

tried to run the individual file in the terminal.

But got the following error:

(RuntimeError) cannot use ExUnit.Case without starting the ExUnit application, please call ExUnit.start() or explicitly start the :ex_unit app

Screenshot:
image

Looked at https://hexdocs.pm/ex_unit/ExUnit.Case.html but no luck.
Also looked at https://elixirschool.com/lessons/basics/testing and didn't get much enlightenment...

I'm trying to execute a single test file ...
looked at: http://stackoverflow.com/questions/26150146/how-can-i-make-mix-run-only-specific-tests-from-my-suite-of-tests
Tried mix test basic-test.exs and mix test --only basic-test.exs
image

This question might be more appropriate in https://github.com/dwyl/learn-elixir ...
but I figured that given its from the "Programming Phoenix" book, other people might find it here....

p.164 player does not load video! Uncaught TypeError: _player2.default.init is not a function

When trying to view a valid video url/id on page 164 of the Programming Phoenix book,
the video is not displaying.

When I open DevTools > Console I see the following error:

Uncaught TypeError: _player2.default.init is not a function

Screenshot:
image

Everything else appears to be working but the video is not being loaded.
I've tried searching the book's "errata" page: https://pragprog.com/titles/phoenix/errata
and spent some time googling for the error text and more generic keywords.

I suspect that the error is because we haven't said how the web page should get
get the YT script ... but I could be wrong.

If anyone else has come across this issue, please share how you resolved it! thanks! 👍

On a side note this type of is not a function error doesn't happen in Elm!
dwyl/technology-stack#27 (comment)

web/controllers/video_controller.ex:23: undefined function video_path/2

on page 93 of Programming Phoenix we run mix ecto.migrate ...
we're seeing:

== Compilation error on file web/controllers/video_controller.ex ==
** (CompileError) web/controllers/video_controller.ex:23: undefined function video_path/2
    (stdlib) lists.erl:1338: :lists.foreach/2
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (elixir) lib/kernel/parallel_compiler.ex:117: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1

image

p.165 when attempting to run "mix ecto.migrate" getting error: (Postgrex.Error) ERROR 42P07 (duplicate_table): relation "videos" already exists

image

nelson@local:rumbl Admin$ mix ecto.migrate

09:04:00.993 [info]  == Running Rumbl.Repo.Migrations.CreateVideo.change/0 forward

09:04:00.993 [info]  create table videos
** (Postgrex.Error) ERROR 42P07 (duplicate_table): relation "videos" already exists
    (ecto) lib/ecto/adapters/sql.ex:195: Ecto.Adapters.SQL.query!/5
    (ecto) lib/ecto/adapters/postgres.ex:86: anonymous fn/4 in Ecto.Adapters.Postgres.execute_ddl/3
    (elixir) lib/enum.ex:1623: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto) lib/ecto/adapters/postgres.ex:86: Ecto.Adapters.Postgres.execute_ddl/3
    (ecto) lib/ecto/migration/runner.ex:98: anonymous fn/2 in Ecto.Migration.Runner.flush/0
    (elixir) lib/enum.ex:1623: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto) lib/ecto/migration/runner.ex:96: Ecto.Migration.Runner.flush/0
    (stdlib) timer.erl:181: :timer.tc/2
    (ecto) lib/ecto/migration/runner.ex:27: Ecto.Migration.Runner.run/6
    (ecto) lib/ecto/migrator.ex:121: Ecto.Migrator.attempt/6
    (ecto) lib/ecto/migrator.ex:71: anonymous fn/4 in Ecto.Migrator.do_up/4
    (ecto) lib/ecto/adapters/sql.ex:615: anonymous fn/3 in Ecto.Adapters.SQL.do_transaction/3
    (db_connection) lib/db_connection.ex:1274: DBConnection.transaction_run/4
    (db_connection) lib/db_connection.ex:1198: DBConnection.run_begin/3
    (db_connection) lib/db_connection.ex:789: DBConnection.transaction/3
    (ecto) lib/ecto/migrator.ex:244: anonymous fn/4 in Ecto.Migrator.migrate/4
    (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
    (ecto) lib/mix/tasks/ecto.migrate.ex:84: anonymous fn/4 in Mix.Tasks.Ecto.Migrate.run/2
    (elixir) lib/enum.ex:651: Enum."-each/2-lists^foreach/1-0-"/2
    (elixir) lib/enum.ex:651: Enum.each/2

Assumptions

What are the assumptions we should make for the people using this guide?

  • Basic elixir knowledge (modules, function definitions, pattern matching, maps, atoms)
  • No exposure to pheonix

Anything else?

Changeset validation (page 67)

Just messing around with the changeset validation outlined in the Programming Phoenix, page 67:

  def changeset(model, params \\ :invalid) do
    model
    |> cast(params, ~w(name username))
    |> validate_required([:username], message: "username cannot be left empty")
    |> validate_required([:name], message: "name cannot be left empty")
    |> validate_length(:username, min: 1, max: 20)
  end

The above works perfectly. However if we comment out this line:
# |> validate_required([:username], message: "username cannot be left empty")

then we get an error from the database that username is null even though we've set minimum characters to 1.
screen shot 2017-03-03 at 19 54 38

Any ideas? @nelsonic @Shouston3 @jackcarlisle @katbow

Cannot push to learn-phoenix repo

@nelsonic I don't have permissions to push to this repo:

remote: Permission to dwyl/learn-phoenix-framework.git denied to JMurphyWeb.
fatal: unable to access 'https://github.com/dwyl/learn-phoenix-framework.git/': The requested URL returned error: 403

warning: using conn/0 to build a connection is deprecated. Use build_conn/0 instead

warning: using conn/0 to build a connection is deprecated. Use build_conn/0 instead.
    test/controllers/video_controller_test.exs:31: Rumbl.VideoControllerTest.__ex_unit_setup_1/1
    test/controllers/video_controller_test.exs:1: Rumbl.VideoControllerTest.__ex_unit__/2
    (ex_unit) lib/ex_unit/runner.ex:289: ExUnit.Runner.exec_test_setup/2
    (ex_unit) lib/ex_unit/runner.ex:247: anonymous fn/2 in ExUnit.Runner.spawn_test/3

Got Wikipedia Editing Skills and 5 Mins of Time? Please add Phoenix to the list of Web Frameworks on Wikipedia

At the time of writing, the Phoenix (Web) Framework is not in the list on Wikipedia:
https://en.wikipedia.org/wiki/Comparison_of_web_frameworks
Snapshot: Comparison-of-web-frameworks-Wikipedia.pdf

The reason this is an issue, is that non-technical decision makers will go looking for it and not find it in the comparison and conclude that it's not "a thing"... whereas there is no shortage of Java, PHP, JavaScript or Python frameworks, which people will inevitably default to. 😞

If someone has time to update the Wikipedia article to reflect that both Elixir https://en.wikipedia.org/wiki/Elixir_(programming_language) and Phoenix (which doesn't appear to have a page yet!) are "a thing"!

Add CONTRIBUTING.md File to Repo

As a person who is new to the DWYL Org/Community 🆕
I need to know how to contribute to the project effectively 💭
so that I can start my journey towards Doing What I Love with my Life! ❤️ ✅ 😂

Markdown:

_**Please read** our_
[**contribution guide**](https://github.com/dwyl/contributing)
(_thank you_!)

Note: these are line-separated but in the actual rendered page it's all one line.
see: https://github.com/dwyl/contributing/blob/master/CONTRIBUTING.md

Multi-privilege Users

When developing a project you might want to authenticate multiple user types with multiple access privileges, for example, an admin user. Has anyone had experience with this in Phoenix? I found a couple of resources but they are quite complex. Has anyone found a simpler solution?

Medium Article

cannot invoke remote function Phoenix.ConnTest.redirected_to/1 inside match

trying to follow the code on p.140 of Programming Phoenix book
and there's a test that checks that the page has been redirected to a given url.
but when we attempt to run the tests we see:
image

Full output:

** (CompileError) test/controllers/video_controller_test.exs:55: cannot invoke remote function Phoenix.ConnTest.redirected_to/1 inside match
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    test/controllers/video_controller_test.exs:53: (module)

21:51:47.736 [error] GenServer #PID<0.177.0> terminating
** (CompileError) test/controllers/video_controller_test.exs:55: cannot invoke remote function Phoenix.ConnTest.redirected_to/1 inside match
    (elixir) src/elixir_translator.erl:279: :elixir_translator.translate/2
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (elixir) src/elixir_clauses.erl:26: :elixir_clauses.match/3
    (elixir) src/elixir_clauses.erl:35: :elixir_clauses.clause/6
    (elixir) src/elixir_clauses.erl:83: anonymous fn/3 in :elixir_clauses.do_clauses/3
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (elixir) src/elixir_clauses.erl:88: :elixir_clauses.do_clauses/3
    (elixir) src/elixir_clauses.erl:73: :elixir_clauses.clauses/3
    (elixir) src/elixir_translator.erl:95: :elixir_translator.translate/2
    (elixir) src/elixir_translator.erl:16: :elixir_translator.translate/2
    (elixir) src/elixir_translator.erl:374: :elixir_translator.translate_block/3
    (elixir) src/elixir_translator.erl:38: :elixir_translator.translate/2
    (elixir) src/elixir_clauses.erl:36: :elixir_clauses.clause/6
    (elixir) src/elixir_def.erl:170: :elixir_def.translate_clause/7
    (elixir) src/elixir_def.erl:159: :elixir_def.translate_definition/8
    (elixir) src/elixir_def.erl:94: :elixir_def.store_definition/10
    test/controllers/video_controller_test.exs:53: (module)
    (elixir) src/elixir_compiler.erl:125: :elixir_compiler.dispatch_loaded/6
    (elixir) src/elixir_module.erl:192: :elixir_module.eval_form/6
    (elixir) src/elixir.erl:223: :elixir.erl_eval/3

password_hash not being saved to users table when new person registers

while attempting to follow the Programming Phoenix book example app "Rumbl" I think I have written out (not copy-pasted!) the code in the examples without errors ...
the /users/new page reders fine:
image

When I submit the form, it appears to work because the name and username data is being inserted into the database:
image

And the GET /users (index) is being displayed:
image

However as you can see from that second screenshot (of the data in the PostgreSQL "Users" table) the password_hash is not being saved to the database ...

Has anyone else seen this issue while working through the book?
code snapshot at time when seeing this issue: https://github.com/dwyl/learn-phoenix-framework/tree/75e57c16da50787ae4d96662ea01822b3e907ea4

Changesets and methods in forms

There were a few questions that came up when I was working with forms. One is outlined in detail in #25 for when you need to pass actions to the form in the controllers, or in the form itself.

Another was why the changeset needed to be defined in the controller and passed in at the beginning of the form. One reason I found for this (there may be others so please add!), is for when the form is being validated, adding in the changeset allows the error_tags to be rendered based on if fields are required & not filled in, or not the correct length, etc. form_for is a function which can take the changeset and convert it to a form (f).

<%= form_for @changeset, user_path(@conn, :create), fn f -> %>
  <label>
    Name: <%= text_input f, :name %>
  </label>

  <label>
    Age: <%= select f, :age, 18..100 %>
  </label>

  <%= submit "Submit" %>
<% end %>

The form can then be passed to other functions (eg select or text_input in the example above), which can generate the input fields by taking information from the changeset.
See here for more information.

The form method is usually derived from the action, however I found in some cases this wasn't working. The form was defaulting to "post" when it should have been "put" when updating users. A line can be added below the first to override the default form method so it is the correct one:

<%= form_for @changeset, @action, fn f -> %>
  <input name="_method" type="hidden" value="put" />

p.168 attempting to create a video in iex get ** (KeyError) key :slug not found in: %Rumbl.Video{__meta__: #Ecto.Schema.Metadata<:built, "videos">

On page 168 of Programming Phoenix the instruction is to create a video.
but when I attempt to run the command listed in the book

iex(1)> video = %Rumbl.Video{id: 1, slug: "hello"}

I get the an error ... 😞

Stack trace:

** (KeyError) key :slug not found in: %Rumbl.Video{__meta__: #Ecto.Schema.Metadata<:built, "videos">, category: #Ecto.Association.NotLoaded<association :category is not loaded>, category_id: nil, description: nil, id: 1, inserted_at: nil, title: nil, updated_at: nil, url: nil, user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: nil}
    (stdlib) :maps.update(:slug, "hello", %Rumbl.Video{__meta__: #Ecto.Schema.Metadata<:built, "videos">, category: #Ecto.Association.NotLoaded<association :category is not loaded>, category_id: nil, description: nil, id: 1, inserted_at: nil, title: nil, updated_at: nil, url: nil, user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: nil})
     (rumbl) web/models/video.ex:4: anonymous fn/2 in Rumbl.Video.__struct__/1
    (elixir) lib/enum.ex:1623: Enum."-reduce/3-lists^foldl/2-0-"/3
     (rumbl) expanding struct: Rumbl.Video.__struct__/1
             iex:1: (file)

Screenshot:
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.