Prepare app for releases by moving configuration to runtime

This commit is contained in:
Mikko Ahlroth 2015-11-30 22:16:00 +02:00
parent 50d8088e7b
commit 6f9915d34f
15 changed files with 98 additions and 67 deletions

3
.gitignore vendored
View file

@ -9,6 +9,9 @@ config.exs
# Configs
config/*.exs
# Release
/rel
# Static artifacts
/node_modules
/bower_components

View file

@ -54,6 +54,8 @@ config :mebe_web,
# Set to true for any view you want to use custom templates for.
# If using custom templates for a view, create a folder web/templates/custom/<viewname>
# and make a copy of all templates for the view inside the folder.
# Note that releases will always use the custom templates that were set in
# the configuration file at release creation time.
custom_templates: %{
"ErrorView" => false,
"FeedView" => false,

View file

@ -7,8 +7,7 @@ defmodule MebeEngine.Worker do
alias MebeEngine.Crawler
alias MebeEngine.DB
@data_path Application.get_env(:mebe_web, :data_path)
alias MebeWeb.Utils
def start_link(opts \\ []) do
GenServer.start_link(__MODULE__, :ok, opts)
@ -36,7 +35,9 @@ defmodule MebeEngine.Worker do
Initialize the database by crawling the configured path and parsing data to the DB.
"""
def load_db() do
Logger.info "Loading post database from '#{@data_path}'…"
data_path = Utils.get_conf :data_path
Logger.info "Loading post database from '#{data_path}'…"
%{
pages: pages,
@ -44,7 +45,7 @@ defmodule MebeEngine.Worker do
tags: tags,
years: years,
months: months,
} = Crawler.crawl @data_path
} = Crawler.crawl data_path
Logger.info "Loaded #{Enum.count pages} pages and #{Enum.count posts} posts."

15
lib/utils.ex Normal file
View file

@ -0,0 +1,15 @@
defmodule MebeWeb.Utils do
@moduledoc """
This module contains functions and other stuff that just don't fit anywhere else properly.
"""
@doc """
Get a configuration setting.
Uses Application.get_env to get the given setting's value. Use this instead of module attributes
so the configuration settings are not compiled in!
"""
def get_conf(key) do
Application.get_env :mebe_web, key
end
end

View file

@ -4,8 +4,6 @@ defmodule MebeWeb.Mixfile do
def project do
[app: :mebe_web,
version: "1.0.0",
deps_path: "deps",
lockfile: "mix.lock",
elixir: "~> 1.1.0",
elixirc_paths: elixirc_paths(Mix.env),
compilers: [:phoenix] ++ Mix.compilers,
@ -19,7 +17,7 @@ defmodule MebeWeb.Mixfile do
# Type `mix help compile.app` for more information
def application do
[mod: {MebeWeb, []},
applications: [:phoenix, :cowboy, :logger]]
applications: [:phoenix, :cowboy, :logger, :phoenix_html, :earmark, :conform]]
end
# Specifies which paths to compile per environment
@ -35,7 +33,9 @@ defmodule MebeWeb.Mixfile do
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:phoenix_html, "~> 2.2"},
{:cowboy, "~> 1.0"},
{:earmark, "~> 0.1.16"}
{:earmark, "~> 0.1.16"},
{:exrm, "~> 1.0.0-rc5"},
{:conform, "~> 1.0.0-rc4"}
]
end
end

View file

@ -1,10 +1,18 @@
%{"cowboy": {:hex, :cowboy, "1.0.4"},
%{"bbmustache": {:hex, :bbmustache, "1.0.3"},
"conform": {:hex, :conform, "1.0.0-rc4"},
"cowboy": {:hex, :cowboy, "1.0.4"},
"cowlib": {:hex, :cowlib, "1.0.2"},
"earmark": {:hex, :earmark, "0.1.19"},
"erlware_commons": {:hex, :erlware_commons, "0.15.0"},
"exrm": {:hex, :exrm, "1.0.0-rc5"},
"fs": {:hex, :fs, "0.9.2"},
"getopt": {:hex, :getopt, "0.8.2"},
"neotoma": {:hex, :neotoma, "1.7.3"},
"phoenix": {:hex, :phoenix, "1.0.3"},
"phoenix_html": {:hex, :phoenix_html, "2.2.0"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.0.1"},
"plug": {:hex, :plug, "1.0.2"},
"poison": {:hex, :poison, "1.5.0"},
"ranch": {:hex, :ranch, "1.2.0"}}
"providers": {:hex, :providers, "1.4.1"},
"ranch": {:hex, :ranch, "1.2.0"},
"relx": {:hex, :relx, "3.5.0"}}

View file

@ -1,20 +1,12 @@
defmodule MebeWeb.ControllerUtils do
use MebeWeb.Web, :controller
alias MebeWeb.Utils
@moduledoc """
This module contains the common functions for all controllers.
"""
@blog_name Application.get_env(:mebe_web, :blog_name)
@blog_author Application.get_env(:mebe_web, :blog_author)
@absolute_url Application.get_env(:mebe_web, :absolute_url)
@posts_per_page Application.get_env(:mebe_web, :posts_per_page)
@disqus_comments Application.get_env(:mebe_web, :disqus_comments)
@page_commenting Application.get_env(:mebe_web, :page_commenting)
@disqus_shortname Application.get_env(:mebe_web, :disqus_shortname)
@feeds_enabled Application.get_env(:mebe_web, :enable_feeds)
@force_read_more Application.get_env(:mebe_web, :force_read_more)
@doc """
Render a list of posts with the given template and params. The posts
and generic configuration settings are assigned to the connection.
@ -31,14 +23,24 @@ defmodule MebeWeb.ControllerUtils do
"""
def insert_config(conn) do
conn
|> assign(:blog_name, @blog_name)
|> assign(:blog_author, @blog_author)
|> assign(:absolute_url, @absolute_url)
|> assign(:posts_per_page, @posts_per_page)
|> assign(:disqus_comments, @disqus_comments)
|> assign(:page_commenting, @page_commenting)
|> assign(:disqus_shortname, @disqus_shortname)
|> assign(:feeds_enabled, @feeds_enabled)
|> assign(:force_read_more, @force_read_more)
|> assign(:blog_name, Utils.get_conf(:blog_name))
|> assign(:blog_author, Utils.get_conf(:blog_author))
|> assign(:absolute_url, Utils.get_conf(:absolute_url))
|> assign(:posts_per_page, Utils.get_conf(:posts_per_page))
|> assign(:disqus_comments, Utils.get_conf(:disqus_comments))
|> assign(:page_commenting, Utils.get_conf(:page_commenting))
|> assign(:disqus_shortname, Utils.get_conf(:disqus_shortname))
|> assign(:feeds_enabled, Utils.get_conf(:feeds_enabled))
|> assign(:force_read_more, Utils.get_conf(:force_read_more))
end
@doc """
Render the 404 page.
"""
def render_404(conn) do
conn
|> insert_config
|> put_status(:not_found)
|> render(MebeWeb.ErrorView, :"404")
end
end

View file

@ -2,8 +2,10 @@ defmodule MebeWeb.FeedController do
use MebeWeb.Web, :controller
alias MebeEngine.DB
import MebeWeb.ControllerUtils, only: [render_posts: 4]
alias MebeWeb.Utils
import MebeWeb.ControllerUtils, only: [render_posts: 4, render_404: 1]
plug :check_feeds_enabled
plug :put_resp_content_type, "application/rss+xml"
plug :put_layout_formats, ["xml"]
plug :put_layout, "feed.xml"
@ -26,4 +28,18 @@ defmodule MebeWeb.FeedController do
|> assign(:tag, tag)
|> render_posts(posts, "postlist.xml", params)
end
# A private plug to check if feeds are enabled at runtime. We need to do this
# at runtime to make it work with releases (where the release is compiled with
# configuration that was active when the release was made). This plug will halt
# the request processing, returning a 404 error if feeds are not enabled.
defp check_feeds_enabled(conn, _opts) do
case Utils.get_conf :enable_feeds do
true -> conn
false ->
conn
|> render_404
|> halt
end
end
end

View file

@ -2,9 +2,8 @@ defmodule MebeWeb.PageController do
use MebeWeb.Web, :controller
alias MebeEngine.DB
import MebeWeb.ControllerUtils, only: [render_posts: 4, insert_config: 1]
@posts_per_page Application.get_env(:mebe_web, :posts_per_page)
alias MebeWeb.Utils
import MebeWeb.ControllerUtils, only: [render_posts: 4, insert_config: 1, render_404: 1]
def index(conn, params) do
conn
@ -153,16 +152,11 @@ defmodule MebeWeb.PageController do
end
defp calculate_ranges(page) do
posts_per_page = Utils.get_conf :posts_per_page
{
(page - 1) * @posts_per_page,
@posts_per_page
(page - 1) * posts_per_page,
posts_per_page
}
end
defp render_404(conn) do
conn
|> insert_config
|> put_status(:not_found)
|> render(MebeWeb.ErrorView, :"404")
end
end

View file

@ -1,8 +1,6 @@
defmodule MebeWeb.Router do
use Phoenix.Router
@enable_feeds Application.get_env(:mebe_web, :enable_feeds)
pipeline :browser do
plug MebeWeb.RequestStartTimePlug
plug :accepts, ["html", "xml"]
@ -16,11 +14,11 @@ defmodule MebeWeb.Router do
get "/p/:page", PageController, :index
get "/", PageController, :index
if @enable_feeds, do: (get "/feed", FeedController, :index)
get "/feed", FeedController, :index
get "/tag/:tag/p/:page", PageController, :tag
get "/tag/:tag", PageController, :tag
if @enable_feeds, do: (get "/tag/:tag/feed", FeedController, :tag)
get "/tag/:tag/feed", FeedController, :tag
get "/archive/:year/p/:page", PageController, :year
get "/archive/:year", PageController, :year

View file

@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="<%= Application.get_env :mebe_web, :blog_author %>">
<meta name="author" content="<%= @blog_author %>">
<title><%= title @conn %></title>
<link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">

View file

@ -1,7 +1,7 @@
defmodule MebeWeb.ErrorView do
use MebeWeb.Web, :view
@absolute_url Application.get_env(:mebe_web, :absolute_url)
alias MebeWeb.Utils
def render("404.html", %{conn: conn}) do
render "not_found.html", %{conn: conn}
@ -20,5 +20,5 @@ defmodule MebeWeb.ErrorView do
@doc """
Get the home page URL of the site.
"""
def home_url(), do: @absolute_url
def home_url(), do: Utils.get_conf :absolute_url
end

View file

@ -1,7 +1,7 @@
defmodule MebeWeb.FeedView do
use MebeWeb.Web, :view
@feeds_full_content Application.get_env(:mebe_web, :feeds_full_content)
alias MebeWeb.Utils
def show_full(), do: @feeds_full_content
def show_full(), do: Utils.get_conf :feeds_full_content
end

View file

@ -1,10 +1,7 @@
defmodule MebeWeb.LayoutView do
use MebeWeb.Web, :view
@default_title Application.get_env(:mebe_web, :blog_name)
@extra_html Application.get_env(:mebe_web, :extra_html)
@feeds_enabled Application.get_env(:mebe_web, :enable_feeds)
alias MebeWeb.Utils
@doc """
Resolve title from the current assigns. Will use the current page's or post's title, if available.
@ -18,23 +15,14 @@ defmodule MebeWeb.LayoutView do
conn.assigns[:page] ->
conn.assigns[:page].title
true -> @default_title
true -> Utils.get_conf :blog_name
end
end
@doc """
Return the extra HTML defined in the config.
"""
def extra_html(), do: @extra_html
if not @feeds_enabled do
@doc """
If feeds are not enabled, mock the feed_path functions so that compilation does not crash because
of missing feed_path.
"""
def feed_path(_, _), do: nil
def feed_path(_, _, _), do: nil
end
def extra_html(), do: Utils.get_conf :extra_html
@doc """
Calculate time taken for request so far.

View file

@ -16,6 +16,8 @@ defmodule MebeWeb.Web do
below.
"""
alias MebeWeb.Utils
def controller do
quote do
use Phoenix.Controller
@ -30,7 +32,9 @@ defmodule MebeWeb.Web do
root = "web/templates"
# Check if we should be using a custom template
custom_templates = Application.get_env :mebe_web, :custom_templates
# TODO: Enable custom views even for releases, currently always set to off
# because they use compile time configuration
custom_templates = Utils.get_conf :custom_templates
compiled_view = MebeWeb.Web.module_to_str __MODULE__
if Map.get custom_templates, compiled_view do