用Phoenix,Postgresql和Ecto创建一个书单应用

文章目录
  1. 1. 修订
  2. 2. 安装Phoenix
  3. 3. 创建书单项目
  4. 4. 添加依赖库
  5. 5. 创建一个仓库(Repo)
  6. 6. 创建模型
  7. 7. 创建数据库移植脚本
  8. 8. 创建查询
  9. 9. 配置路由
  10. 10. 创建控制器
  11. 11. 创建书单视图
  12. 12. 参考资料

本文通过一个书单应用简要介绍使用Phoenix框架创建一个Web应用程序的基本步骤. 从这些基本步骤我们来逐步学习如何使用phoenix框架开发一个Web应用程序的基本过程.

修订

  • 2014-12-17
    • Phoenix 从0.8.0开始 phoenix任务phoenix.start重命名为phoenix.server
    • 修改项目文件mix.exs的依赖版本号,更新依赖库
      • ecto 0.2.0 -> 0.2.8
      • postgrex 0.5.0 -> 0.6.0
      • phoenix 0.5.0 -> master
    • 增加命令注释说明

安装Phoenix

1
git clone https://github.com/phoenixframework/phoenix.git
cd phoenix
mix do deps.get, compile

创建书单项目

phoenix源代码目录中运行如下命令创建一个phoenix项目目录结构

1
mix phoenix.new book_store ../book_store
=== =========== ========== =============
|         |            |              |
命令     任务        项目名称    新创建的项目保存位置

目录../book_store不必事先存在, phoenix会自动创建.

添加依赖库

编辑mix.exs文件, 修改后如下:

1
defmodule BookStore.Mixfile do
  use Mix.Project
  def project do
    [app: :book_store,
     version: "0.0.1",
     elixir: "~> 1.0",
     elixirc_paths: ["lib", "web"],
     compilers: [:phoenix] ++ Mix.compilers,
     deps: deps]
  end
  # Configuration for the OTP application
  #
  # Type `mix help compile.app` for more information
  def application do
    [mod: {BookStore, []},
     applications: [:phoenix, :cowboy, :logger, :postgrex, :ecto]]
  end
  # Specifies your project dependencies
  #
  # Type `mix help deps` for examples and options
  defp deps do
    [ {:phoenix, github: "phoenixframework/phoenix"},
      {:cowboy, "~> 1.0"},
      {:postgrex, "~> 0.6.0"},
      {:ecto, "~> 0.2.8"} ]
  end
end

和修改之前的mix.exs文件相比有两个变更处:

  • application函数中增加了两个依赖的应用程序 :postgres:ecto (16行)
  • deps函数增加两个依赖库{:postgrex, "~> 0.6.0"}{:ecto, "~> 0.2.8"}(24,25行)

运行

1
mix do deps.get, compile

创建一个仓库(Repo)

创建文件web/models/repo.ex,内容如下:

1
defmodule BookStore.Repo do
  use Ecto.Repo, adapter: Ecto.Adapters.Postgres
  def conf do
    parse_url "ecto://postgres:postgres@localhost/book_store"
  end
  def priv do
    app_dir(:book_store, "priv/repo")
  end
end

创建数据库:

1
createdb book_store -U postgres --encoding='utf-8' --locale=en_US.UTF-8 --template=template0

修改lib/book_store.ex为, 如下:

1
defmodule BookStore do
  use Application
  # See http://elixir-lang.org/docs/stable/elixir/Application.html
  # for more information on OTP Applications
  def start(_type, _args) do
    import Supervisor.Spec, warn: false
    children = [
      # Define workers and child supervisors to be supervised
      worker(BookStore.Repo, [])
    ]
    opts = [strategy: :one_for_one, name: BookStore.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

编译

1
mix compile

创建模型

创建文件web/models/books.ex, 内容如下:

1
defmodule BookStore.Books do
  use Ecto.Model
  schema "books" do
    field :title, :string
    field :description, :string
    field :author, :string
    field :publisher, :string
  end
end

创建数据库移植脚本

1
$ mix ecto.gen.migration Bookstore.Repo create_book
Compiled web/models/books.ex
Generated bookstore.app
* creating priv/repo/migrations
* creating priv/repo/migrations/20141112170140_create_book.exs

编辑生成的priv/repo/migrations/20141112170140_create_book.exs脚本, 内容如下:

defmodule BookStore.Repo.Migrations.CreateBook do
  use Ecto.Migration

  def up do
    ["CREATE TABLE books(\
        id serial primary key, \
        title varchar(125), \
        description text, \
        author varchar(255), \
        publisher varchar(255))",\

     "INSERT INTO books(title, description, author, publisher) \
             VALUES ( \
                'Programming Elixir', \
                'Programming Elixir: Functional |> Concurrent |> Pragmatic |> Fun', \
                'Dave Thomas', \
                'The Pragmatic Bookshelf')"
    ]
  end
  def down do
    "DROP TABLE books"
  end
end

运行移植脚本

1
mix ecto.migrate BookStore.Repo

创建查询

创建文件web/models/queries.ex, 内容如下:

1
defmodule BookStore.Queries do
  import Ecto.Query
  def books_query do
    query = from book in BookStore.Books,
            select: book
    BookStore.Repo.all(query)
  end
end

配置路由

打开文件web/router.ex, 修改为如下:

1
defmodule BookStore.Router do
  use Phoenix.Router
  scope "/" do
    # Use the default browser stack.
    pipe_through :browser
    #get "/", BookStore.PageController, :index, as: :pages
    get "/", BookStore.BookController, :index, as: :books
  end
  # Other scopes may use custom stacks.
  # scope "/api" do
  #   pipe_through :api
  # end
end

创建控制器

创建文件web/controllers/book_controller.ex, 内容如下:

1
defmodule BookStore.BookController do
  use Phoenix.Controller
  plug :action
  def index(conn, _params) do
    books = BookStore.Queries.books_query
    render conn, "index", books: books
  end
end

创建书单视图

创建文件web/views/book_view.ex, 内容如下:

1
defmodule BookStore.BookView do
  use BookStore.Views
end

创建目录

1
mkdir web/templates/book

并添加文件web/templates/book/index.html.eex, 内容如下:

1
<h1>我的图书</h1>
<table class='table table-bodered table-striped'>
  <thead>
    <tr>
      <th>#</th>
      <th>标题</th>
      <th>描述</th>
      <th>作者</th>
      <th>出版社</th>
    </tr>
  </thead>
  <tbody>
    <%= for book <- @books do %>
      <tr>
        <td><%= book.id %></td>
        <td><%= book.title %></td>
        <td><%= book.description %></td>
        <td><%= book.author %></td>
        <td><%= book.publisher %></td>
      </tr>
    <% end %>
  </tbody>
</table>

启动应用,并刷新页面

1
mix phoenix.start

我的书单应用

完成!

参考资料

  1. Book Listing App With Elixir, Phoenix, Postgres and Ecto
    http://learnelixir.com/blog/2014/10/05/build-web-app-with-elixir/