スポンサーリンク

2015年7月21日

[Elixir+Phoenix]Phoenixでもページネーションがしたい!!(その2)

Goal

Github - drewolson/scrivenerを動作検証する。

Dev-Environment

OS: Windows8.1
Erlang: Eshell V6.4, OTP-Version 17.5
Elixir: v1.0.4
Phoenix Framework: v0.13.1
PostgreSQL: postgres (PostgreSQL) 9.4.4

Wait a minute

前回のプロジェクトをそのまま流用してもよいが、
seiten を利用した痕跡は消した方が良いです。
プロジェクト作成(前回と同じ名前)
>cd プロジェクト作成ディレクトリ
>mix phoenix.new pagination_sample
>cd pagination_sample
>mix phoenix.server
>ctrl+c
モデル作成
>mix phoenix.gen.html User users email:string name:string
* creating priv/repo/migrations/20150720042204_create_user.exs
* creating web/models/user.ex
* creating test/models/user_test.exs
* creating web/controllers/user_controller.ex
* creating web/templates/user/edit.html.eex
* creating web/templates/user/form.html.eex
* creating web/templates/user/index.html.eex
* creating web/templates/user/new.html.eex
* creating web/templates/user/show.html.eex
* creating web/views/user_view.ex
* creating test/controllers/user_controller_test.exs

Add the resource to the proper scope in web/router.ex:

    resources "/users", UserController

and then update your repository by running migrations:

    $ mix ecto.migrate

>mix ecto.create
The database for PaginationSample.Repo has been created.

>mix ecto.migrate

13:29:01.698 [info]  == Running PaginationSample.Repo.Migrations.CreateUser.change/0 forward

13:29:01.698 [info]  create table users

13:29:01.743 [info]  == Migrated in 0.3s
Description:
“resources “/users”, UserController” は、web/router.ex に追加して下さい
以降、この記事内ではプロジェクトと言ったら、
pagination_sampleを指し示す。

Index

  1. Preparation of scrivener
  2. Operation verification

1. Preparation of scrivener

ライブラリを利用する準備をします。
ライブラリ名: Scrivener (Github - drewolson/scrivener)
ライブラリの説明を簡単に読んでまとめてみると・・・
  • Ecto クエリをページ分割できる
  • paginate 関数を提供する
  • ページの総数、現在ページ、現在ページのエントリとして有用な情報を提供する
  • ページ分割の件数のデフォルトは10件
  • Phoenix と上手く動作する
といったところです。
ファイル: mix.exs
scrivener を追加。
defp deps do
  [{:phoenix, "~> 0.13.1"},
   {:phoenix_ecto, "~> 0.4"},
   {:postgrex, ">= 0.0.0"},
   {:phoenix_html, "~> 1.0"},
   {:phoenix_live_reload, "~> 0.4", only: :dev},
   {:cowboy, "~> 1.0"},
   {:scrivener, "~> 0.11.0"}]
end
依存関係の解消
>mix deps.get
ライブラリの利用準備完了。

2. Operation verification

動作検証します。
ファイル: lib/pagination_sample/repo.ex
ライブラリを利用するために Repo で use する。
defmodule PaginationSample.Repo do
  use Ecto.Repo, otp_app: :pagination_sample
  use Scrivener, page_size: 10
end
ファイル: web/models/user.ex
クエリを利用するため Ecto.Query を import。
ページネーションさせる関数を追加。
defmodule PaginationSample.User do
  use PaginationSample.Web, :model

  import Ecto.Query

  schema "users" do
    field :email, :string
    field :name, :string

    timestamps
  end

  @required_fields ~w(email name)
  @optional_fields ~w()

  @doc """
  Creates a changeset based on the `model` and `params`.

  If `params` are nil, an invalid changeset is returned
  with no validation performed.
  """
  def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
  end

  def paginate(params) do
    PaginationSample.User
    |> order_by([u], desc: u.name)
    |> PaginationSample.Repo.paginate(page: 1, page_size: 10)
  end
end
ファイル: web/controllers/user_controller.ex
indexアクションを以下のように修正。
def index(conn, params) do
  page = User.paginate(params)

  render(conn, "index.html",
         users: page.entries,
         page_number: page.page_number,
         page_size: page.page_size,
         total_pages: page.total_pages,
         total_entries: page.total_entries)
end
ファイル: web/templates/user/index.html.eex
ページ情報を表示するよう修正。
<div>
  <p>page_number: <%= @page_number %></p>
  <p>page_size: <%= @page_size %></p>
  <p>total_pages: <%= @total_pages %></p>
  <p>total_entries: <%= @total_entries %></p>
</div>
実行して確認してみる。
10件だけの表示は問題なし。
ページ情報も出ている。
2ページ目の情報が欲しい場合、UserModel の paginate を以下のように修正する。
ファイル: web/models/user.ex
def paginate(params) do
  PaginationSample.User
  |> order_by([u], desc: u.name)
  |> PaginationSample.Repo.paginate(page: 2, page_size: 10)
end
page: の値が変われば別のページが見れる。
この値を変更できるようにすれば、ページネーションができますね。

Speaking to oneself

何この便利なライブラリ・・・It’s cool!!!!
よっしこれを使おう!
つい昨日まで悩んできたのに現金なことですが(笑)
表示部分とページ遷移部分を付け足してやれば、
ページネーション機能の実装も楽勝ですな!!(笑)
ライブラリの作者がページネーションを実装している記事が見つかりました。
リンク先を見れば内部で、どうやって動作しているかが理解できると思います。
Pagination with Phoenix & Ecto

Bibliography

人気の投稿