Skip to content

Instantly share code, notes, and snippets.

@chrismccord
Last active January 17, 2016 12:11
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrismccord/cf51346c6636b5052885 to your computer and use it in GitHub Desktop.
Save chrismccord/cf51346c6636b5052885 to your computer and use it in GitHub Desktop.
Phoenix 0.9 to 0.10.0 upgrade instructions

form_tag, link, CSRF changes

Plug 0.10.0 moves CSRF tokens from cookies back to sessions. To avoid future bumps on the road, a get_csrf_token/0 function has been added to controllers and imported into views. Update all your csrf token reference code to use the new function. Additionally, form_tag and link helpers have been added that will inject the csrf token for you automatically. You should transition to these new functions where possible, ie:

  <%= form_tag("/hello", method: :post) %>
    ... your form stuff. csrf is inject for you
  </form>

Additionally, a link helper has been added that can send POST/PUT/DELETE requests with csrf inclusion, ie:

<%= link "Remove", to: user_path(@conn, :delete, @user), method: :delete) %>

view.ex, using

web/view.ex has been removed, as well as the using macro that allowed you to inject shared aliases/imports across other views. It has been replace by a web/web.ex file that serves as a centralized place to group model, view, and controller shared code injection blocks.

  1. Save the following block of code as web/web.ex (replace MyApp with your application module), and copy your web/view.ex contents as indicated in the block below. After the new file is saved, delete your web/view.ex file.
defmodule MyApp.Web do
  @moduledoc """
  A module that keeps using definitions for controllers,
  views and so on.

  This can be used in your application as:

      use MyApp.Web, :controller
      use MyApp.Web, :view

  Keep the definitions in this module short and clean,
  mostly focused on imports, uses and aliases.
  """

  def view do
    quote do
      use Phoenix.View, root: "web/templates"

      # Import URL helpers from the router
      import MyApp.Router.Helpers

      # Import all HTML functions (forms, tags, etc)
      use Phoenix.HTML
      
      # *****
      # Copy your old `web/view.ex` using block contents here
      # *****
    end
  end

  def controller do
    quote do
      use Phoenix.Controller

      # Import URL helpers from the router
      import MyApp.Router.Helpers
    end
  end
  
  def model do
    quote do
    end
  end

  @doc """
  When used, dispatch to the appropriate controller/view/etc.
  """
  defmacro __using__(which) when is_atom(which) do
    apply(__MODULE__, which, [])
  end
end
  1. Update all your views to use the new Web module, ie:
# 0.9.x
defmodule MyApp.PageView do
  use MyApp.View
end

# 0.10.0
defmodule MyApp.PageView do
  use MyApp.Web, :view
end
  1. Update all your controller use declrations, ie:
# 0.9.x
defmodule MyApp.UserController do
  use Phoenix.Controller
end

# 0.10.0
defmodule MyApp.UserController do
  use MyApp.Web, :controller
end

Endpoint PubSub Config

  • The :options key has been removed from the :pubsub keyword list. Just define the options alongside the pubsub configuration.
  • The :name option when configuring a pubsub adapter is now required instead of inflected
# 0.9.x
config :my_app, MyApp.Endpoint,
  pubsub: [adapter: Phoenix.PubSub.PG2]
           
# 0.10.0
config :my_app, MyApp.Endpoint,
  pubsub: [name: MyApp.PubSub,
           adapter: Phoenix.PubSub.PG2]

Redis PubSub Adapter

The :eredis based adapter has been replaced with :redo for propper remote connections. Update your configuration and mix deps like so:

# config.exs
# 0.9.x
config :my_app, MyApp.Endpoint,
  pubsub: [adapter: Phoenix.PubSub.Redis]
           
# 0.10.0
config :my_app, MyApp.Endpoint,
  pubsub: [name: MyApp.PubSub,
           adapter: Phoenix.PubSub.Redis,
           host: "127.0.0.1",
           ...]

# mix.exs
# 0.9.x

      defp deps do
        [{:eredis, github: ...
         {:poolboy, "~> 1.4.2"},
        ...]
      end

# 0.10.0

      defp deps do
        [{:redo, github: "heroku/redo"},
         {:poolboy, "~> 1.4.2"},
        ...]
      end

Setting up the new Brunch asset system (optional)

Phoenix 0.10.0 includes brunch for static asset compilation. Brunch is a nodejs project, so node is required. See node's website for installation instructions. Use the following steps to get your existing application setup:

  1. Copy package.json to the root of your project https://raw.githubusercontent.com/phoenixframework/phoenix/39aa3e69870ebdd90d82774c933a8b117a8daaba/priv/static/brunch/package.json
  2. Copy brunch-config.js to the root of your project https://raw.githubusercontent.com/phoenixframework/phoenix/39aa3e69870ebdd90d82774c933a8b117a8daaba/priv/static/brunch/brunch-config.js
  3. Ensure node is installed
  4. project_root$ npm install
  5. project_root$ mkdir -p web/static/js
  6. project_root$ mkdir -p web/static/css
  7. project_root$ mkdir -p web/static/vendor
  8. project_root$ touch web/static/js/app.js
  9. project_root$ touch web/static/css/app.scss
  10. copy phoenix.js to web/static/vendor/phoenix.js https://raw.githubusercontent.com/phoenixframework/phoenix/39aa3e69870ebdd90d82774c933a8b117a8daaba/priv/static/phoenix.js
  11. Move/copy your application javascript and app css/sass to the former files
  12. Update your web/templates/layouts/application.html.eex (and others if exist) to use the new brunch built css/js, ie: <script src="<%= static_path(@conn, "/js/app.js") %>"></script> <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">
  13. Add this to load your main js module in your layout(s) just before </body>: <script>require("web/static/js/app")</script>
  14. Add the following Endpoint :watchers and :live_reload configuration to config/dev.exs:
config :my_app, MyAPp.Endpoint,
  ...
  watchers: [{Path.expand("node_modules/brunch/bin/brunch"), ["watch"]}]

# Watch static and templates for browser reloading.
# *Note*: Be careful with wildcards. Larger projects
# will use higher CPU in dev as the number of files
# grow. Adjust as necessary.
config :my_app, MyApp.Endpoint,
  live_reload: [Path.expand("priv/static/js/app.js"),
                Path.expand("priv/static/css/app.css"),
                Path.expand("web/templates/**/*.eex")]

Now start your server with mix phoenix.server and observe brunch compiling your assets in web/static/css and web/static/js and live-reloading the browser on changes.

phoenix_ecto

If you are using Ecto, add phoenix_ecto to your mix deps to enjoy Ecto form/link builder support:

  defp deps do
    [...,
     {:phoenix, "~> 0.10.0"},
     {:phoenix_ecto, "~> 0.1"},
     {:postgrex, ">= 0.0.0"}]
  end

Happy coding!

@essenciary
Copy link

Great stuff, thanks, the upgrade worked like a charm!

However, now I'm running in a bit of an issue with an umbrella app which includes one Phoenix app.

  • I have the following file structure: http://monosnap.com/image/wFEVIaPPTixS7r7bnFPqUIwM85AuHO
    where the web_ui app is the Phoenix app and is using the pocketex app.
  • I'm running mix phoenix.server from the umbrella app to make pocketex available to web_ui
  • it starts up ok, but I get the following error:
    [error] Could not start watcher "/Users/adrian/Dropbox/Projects/essenciary/essenciary/node_modules/brunch/bin/brunch", executable does not exist

Please advise, thanks!

@essenciary
Copy link

Also, I'm getting some deprecation warnings although the views have been upgraded as instructed.

Example warning:
warning: using do...end in views is deprecated, please use the new YourApp.Web definitions web/views/layout_view.ex:2: WebUi.LayoutView (module)

layout_view.ex:

defmodule WebUi.LayoutView do
  use WebUi.Web, :view
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment