スポンサーリンク

2015年7月20日

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

Goal

シンプルなページネーション機能を提供してくれる、
Github - rylev/seitenを動作検証する。

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

Railsにあるページネーションメソッドのようなものが見つからなかった。
でも、ライブラリは見つけた!!
ページネーションを行うため、対象ライブラリの動作検証を実施します。
プロジェクト作成
>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. For what?
  2. Preparation of seiten
  3. Running the Sample
  4. Extra

1. For what?

そもそも何でページネーションを行うのでしょう?
1ページに全ての情報を出してはダメなんでしょうか?
100件位なら掲示板とかでも見たりするのでいいのですが、
1000件、1万件となった情報を1ページで見たいですか?
(1万件とか小規模サイトだとほぼないと思いますが・・・)
私はいやです。
なので、10件くらいずつ表示してくれるようページネーションをします。

2. Preparation of seiten

ライブラリを使う準備をします。
始める前にライブラリの紹介をしておきます。
ライブラリ名: Seiten (Github - rylev/seiten)
(読み方が分からない・・・せいてん?)
Seitenは、Elixirのためのシンプルなページネーションライブラリです。
Phoenix以外でもElixirで作られたWebフレームワークなら利用できます。
そのためプラグ互換性を持っているとのことです。
シンプルと言いながら、なんと便利な!素晴らしい!!
Trotで使ってみるのもいいですね。
それでは使ってみたいと思います!!
ファイル: mix.exs
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"},
   {:seiten, github: "rylev/seiten"}]
end
依存関係の解消。
>mix deps.get

>mix phoenix.server
Unchecked dependencies for environment dev:
* plug (git://github.com/elixir-lang/plug.git)
  different specs were given for the plug app:

  > In deps/seiten/mix.exs:
    {:plug, nil, [git: "git://github.com/elixir-lang/plug.git", ref: "7040c89cb4cf1f1c6afdee379e5982a07d77a6c3", override: true]}

  > In deps/phoenix/mix.exs:
    {:plug, ">= 0.12.2 and < 2.0.0", [optional: false, hex: :plug]}

  Ensure they match or specify one of the above in your PaginationSample.Mixfile deps and set `override: true`
** (Mix) Can't continue due to errors on dependencies
おや、mix.exs の書き方に問題があるようですね。
しかもこれは、seiten の mix.exs ですね。
seiten のファイルを直接修正してしまいますね。
ファイル: deps/seiten/mix.exs:
defp deps do
  [{:cowboy, "~> 1.0"},
   #{:plug, github: "elixir-lang/plug", ref: "7040c89cb4cf1f1c6afdee379e5982a07d77a6c3", override: true}
   {:plug, ">= 0.12.2 and < 2.0.0", [optional: false, hex: :plug]}]
end
mix ファイルを書き換えたので、
再度依存関係を解消する。
>mix deps.get
Running dependency resolution
* Updating plug (Hex package)
Checking package (https://s3.amazonaws.com/s3.hex.pm/tarballs/plug-0.13.0.tar)
Using locally cached package
Unpacked package tarball (c:/Users/Takes_000/.hex/packages/plug-0.13.0.tar)

>mix phoenix.server
準備&起動完了。

3. Running the Sample

サンプルをやってきます。
サンプル通りに記述するとエラー出るんですけどね~(2015/07/20時確認)
なので、ちょいちょいサンプルの内容を変えてます。
ファイル: web/models/user.ex
以下の一行を追加。
use Seiten
ファイル: web/controllers/user_controller.ex
indexアクションを以下のように修正。
def index(conn, _params) do
  users = Repo.all(User)
  paged = PaginationSample.User.paginate(users, conn)
  render(conn, "index.html", users: users, paged: paged)
end
ファイル: web/view/user_view.ex
以下の関数を作成。
def user_pagination(conn, paged) do
  PaginationSample.User.paginated_html(conn, paged)
end
ファイル: web/templates/user/index.html.eex
以下の記述を追加。
<div>
  <%= user_pagination(@conn, @paged) %>
</div>
適当に10件以上のデータを用意して、さて実行!!
うん、ページのリンクが出たね。
ソースコードを見ていく中で気づいた人も多いだろうと思うが、
ページリンクを提供するライブラリだったようですね。
なのでユーザ自体の表示は、
ライブラリが提供してくれる情報をもとに自分で作成しなければならない。
ぬかったわ!!(笑)
ここまでやってくれた人達にはすいません・・・m( )m
ちょっと望んでいた内容と違くなってしまいました。

4. Extra

今までなんのかんの一回もやらなかった操作を実行してみた。
>mix ecto.drop
Generated pagination_sample app
The database for PaginationSample.Repo has been dropped.

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

>mix ecto.migrate

16:34:57.923 [info]  == Running PaginationSample.Repo.Migrations.CreateUser.change/0 forward

16:34:57.923 [info]  create table users

16:34:57.947 [info]  == Migrated in 0.2s
何の異常もないですね。

Speaking to oneself

もう一つライブラリを見つけたが・・・
さてどうするかな自分で実装しちゃおうかな・・・
ページネーションに関しては、一応だが概念、動作、実装方法を理解している。
(そう思いたい・・・)
もしPhoenixにて自分が実装するなら、
EctoからDB操作(limitやoffsetなど)の処理が主体になりますね。
そしてその思想で作られたと思うライブラリを発見・・・
(スターを見るとこちらの方が人気ですね・・・)
Github - drewolson/scrivener
悩ましい・・・結局作ることになるなら自分で実装した方が・・・
rylev/seitenを使うか、drewolson/scrivenerを使うか、自分で実装してしまうか検討します。
なんかライブラリの紹介になってしまったな。

Bibliography

人気の投稿