phoenix 開發API系列(三)phoenix api 結合數據庫

概述

介紹了 api 的各類寫法以後,下面介紹構建 api 時與數據庫鏈接的方式。git

下面使用的工程的完整代碼已經公開在: http://git.oschina.net/wangyubin/phoenix-apiweb

ecto 簡介

ecto 實際上是獨立於 phoenix framework 的,它是 elixir 語言實現的用來訪問數據庫的框架,相似於 ORM 可是和傳統的 ORM 又有些不同。 能夠這麼理解,它是利用了 elixir 語言的動態性和函數式的特性,參考了傳統的 ORM 的優點後而開發的新一代數據庫訪問層。sql

ecto 的四個主要組件

  1. Ecto.Repo 數據庫包裝器, 經過它能夠執行數據庫的增刪改查, 經過它配置數據庫鏈接
  2. Ecto.Schema 這是 ORM 的核心,定義了操做對象和底層數據庫表之間的映射
  3. Ecto.Changeset 這是 Ecto 的一個創新的地方,在 Changeset 中,能夠定義校驗數據層合法性的方法,在真正寫入數據庫以前,對數據進行校驗
  4. Ecto.Query 以 elixir 語法編寫的查詢,能夠避免 SQL 注入等常見問題

ecto 使用示例

建立示例工程

  • 新建工程
$ mix new ecto_sample
  • 添加依賴 (mix.exs)
defp deps do
  [
    {:postgrex, ">= 0.0.0"},
    {:ecto, "~> 2.0.0"}
  ]
end
  • 設置應用信息 (mix.exs)
def application do
  [applications: [:logger, :postgrex, :ecto]]
end
  • 獲取依賴包
$ mix deps.get

數據庫鏈接配置

# vi config/config.exs
config :ecto_sample, ecto_repos: [EctoSample.Repo]

config :ecto_sample, EctoSample.Repo,
  adapter: Ecto.Adapters.Postgres,
  database: "ecto_sample",
  username: "iotalab",
  password: "iotalab",
  hostname: "localhost"

配置好數據庫鏈接以後,就能夠在命令行下建立數據庫了數據庫

$ mix ecto.create

建立 model 和 migration 代碼

首先,經過命令行建立一個用來生成表的的 users module。vim

$ mix ecto.gen.migration users

這個命令會在 priv/repo/migrations 下自動生成 migration 腳本,只不過腳本是空的。 下面先建立 users 表的內容,而後填充 migration 腳本的內容api

# vi lib/ecto_models.ex
defmodule EctoSample.User do
  use Ecto.Schema

  schema "users" do
    field :name, :string
    field :password, :string
    field :age, :integer

    timestamps
  end
end
# vi priv/repo/migrations/20160912131700_users.exs  這個文件是由上一條命令產生的
defmodule EctoSample.Repo.Migrations.Users do
  use Ecto.Migration

  def up do
    create table(:users) do
      add :name, :string
      add :password, :string
      add :age, :integer
      timestamps
    end
  end

  def down do
    drop table(:users)
  end
end

建立數據庫表

建立命令很是簡單app

$ mix ecto.migrate

使用示例

建立了一個簡單的表以後,就能夠在命令行下測試是否能夠操做數據庫了。 下面演示了新增一個 user 和 刪除一個 user 的過程。框架

$ iex -S mix
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.3.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> u = %EctoSample.User{name: "wyb", password: "passwd", age: 33}
%EctoSample.User{__meta__: #Ecto.Schema.Metadata<:built, "users">, age: 33,
 id: nil, inserted_at: nil, name: "wyb", password: "passwd", updated_at: nil}


iex(2)> EctoSample.Repo.insert(u)

22:09:51.433 [debug] QUERY OK db=4.4ms
INSERT INTO "users" ("age","name","password","inserted_at","updated_at") VALUES ($1,$2,$3,$4,$5) RETURNING "id" [33, "wyb", "passwd", {{2016, 9, 12}, {14, 9, 51, 0}}, {{2016, 9, 12}, {14, 9, 51, 0}}]
{:ok,
 %EctoSample.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, age: 33,
  id: 3, inserted_at: #Ecto.DateTime<2016-09-12 14:09:51>, name: "wyb",
  password: "passwd", updated_at: #Ecto.DateTime<2016-09-12 14:09:51>}}


iex(3)> u = %EctoSample.User{id: 3}
%EctoSample.User{__meta__: #Ecto.Schema.Metadata<:built, "users">, age: nil,
 id: 3, inserted_at: nil, name: nil, password: nil, updated_at: nil}


iex(4)> EctoSample.Repo.delete(u)

22:11:28.960 [debug] QUERY OK db=3.4ms
DELETE FROM "users" WHERE "id" = $1 [3]
{:ok,
 %EctoSample.User{__meta__: #Ecto.Schema.Metadata<:deleted, "users">, age: nil,
  id: 3, inserted_at: nil, name: nil, password: nil, updated_at: nil}}

補充說明

除了修改上面的文件以外,還有下面2個地方須要修改,不然 EctoSample 模塊不會加載:async

# vi lib/ecto_sample.ex
defmodule EctoSample do
  use Application

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      worker(EctoSample.Repo, []),
    ]
    opts = [strategy: :one_for_one, name: EctoTest.Supervisor]
    Supervisor.start_link(children, opts)
  end
end
def application do
  [applications: [:logger, :postgrex, :ecto],
   mod: {EctoSample, []}]   # <===  IMPORTANT !!!
end

api with postgresql

postgresql 安裝與配置

如下安裝配置是基於 CentOS7 的函數

# 安裝 package
$ sudo yum install postgresql-server

# init db
$ sudo su - postgres
$ initdb -D /var/lib/pgsql/data

# start db
$ sudo systemctl start postgresql

# create user and database
$ sudo su - postgres
$ psql -U postgres -W       # password is also "postgres"
postgres=# CREATE USER iotalab WITH PASSWORD 'iotalab';
postgres=# CREATE DATABASE test OWNER iotalab ENCODING 'UTF8';

設置能夠局域網內訪問

$ sudo su - postgres 
$ cd /var/lib/pgsql/data

vim pg_hba.conf

host    all             all             0.0.0.0/0            md5

vim postgresql.conf

listen_addresses = '*'

遠程鏈接不上時試試禁用 iptables

$ sudo systemctl stop iptables

建立 數據庫和表

  1. 給這個工程加上 數據庫的支持 其實建立的工程的時候,默認就是支持數據庫的。可是前面的示例不須要數據庫,因此建立這個工程的時候用了 –no-ecto 的參數。 從新建立工程,並將已寫的代碼複製進去便可,此次建立工程時不加 –no-ecto 參數。

    $ mix phoenix.new phoenix_api
  2. 配置數據庫鏈接並建立數據庫 修改文件 config/dev.exs

    # Configure your database
    config :phoenix_api, PhoenixApi.Repo,
      adapter: Ecto.Adapters.Postgres,
      username: "iotalab",
      password: "iotalab",
      database: "dev_db",
      hostname: "localhost",
      pool_size: 10

    建立數據庫

    $ mix ecto.create
  3. 建立一張用來測試的表

    $ mix phoenix.gen.model User users name:string email:string age:integer
    * creating web/models/user.ex
    * creating test/models/user_test.exs
    * creating priv/repo/migrations/20160913230129_create_user.exs

    查看生成的文件,已經根據命令行的中參數,生成了對應的對象,能夠發現其中自動添加了 timestamps 方法,這個方法是自動添加一些 updated_at, inserted_at 等通用時間字段。 而後經過命令行建立表:

    $  mix ecto.migrate
    
    07:10:52.527 [info]  == Running PhoenixApi.Repo.Migrations.CreateUser.change/0 forward
    
    07:10:52.527 [info]  create table users
    
    07:10:52.537 [info]  == Migrated in 0.0s

增刪改查 示例

在測試代碼中構造了 增刪改查 的測試 case,而後用 mix test 命令來進行測試。 具體代碼能夠參考:http://git.oschina.net/wangyubin/phoenix-api/blob/master/test/models/user_test.exs

總結

利用 ecto 模塊,操做數據庫很是簡單,可是,寫岀優秀 api 的關鍵仍是在於 api 的設計上,學習這個框架的意義是在於把一些通用繁瑣的工做交給框架來處理,可讓咱們把主要的精力放在業務代碼的構建上。

至此,phoenix framework api 系列的3篇也結束了。

來源:http://blog.iotalabs.io/

相關文章
相關標籤/搜索