スポンサーリンク

2015年10月17日

[Elixir+Phoenix]Ectoでpreloadする対象にorder_byしたい

Goal

Ectoでpreloadする対象にorder_byを行う。

Dev-Environment

OS: Windows8.1
Erlang: Eshell V7.1, OTP-Version 18.1
Elixir: v1.1.1
Phoenix Framework: v1.0.3
PostgreSQL: postgres (PostgreSQL) 9.4.4

Content

ふと思いました。
Ectoのpreloadで取得しているデータを昇順または降順に並び替えたい時どうすればいいんだろう…っと。
Ectoのドキュメントに書いてありますが、忘れないようにTipsとしてアップします。
(但し、超簡略版…)
二つのモデルがあるとする。
(投稿とコメント)

Example:

defmodule LazyAlchemist.Post do
  use LazyAlchemist.Web, :model

  alias LazyAlchemist.Comment

  schema "posts" do
    field :title, :string
    field :content, :string
    field :permalink, :string

    has_many :comments, Comment

    timestamps
  end

  @required_fields ~w(title content permalink)
  @optional_fields ~w()

  ...
end

Example:

defmodule LazyAlchemist.Comment do
  use LazyAlchemist.Web, :model

  alias LazyAlchemist.Post

  schema "comments" do
    field :name, :string
    field :comment, :string

    belongs_to :post, Post, foreign_key: :post_id

    timestamps
  end

  @required_fields ~w(post_id name comment)
  @optional_fields ~w()

  ...
end
二つのモデル間では、has_manyとbelongs_toの設定をしている。
そして、投稿を表示する時にpreloadして、コメントのデータは取得します。
但し、この時にコメントのデータは、コメントが入力された日付でdesc(降順)にソートされたデータとして取得をしたい。

Example:

Repo.get_by(Post, permalink: permalink)
|> Repo.preload(:comments) <- ソートしたい

Q: preloadで取得するデータをorder_byを使ってソートするにはどうしたら良いでしょうか?

A: preloadの中にさらにクエリを記述することができるので、fromをpreloadの中に記述する。

分かり辛いのでサンプルを提示します。

Example:

Repo.get_by(Post, permalink: permalink)
|> Repo.preload(comments: (from c in Comment, order_by: [desc: c.inserted_at]))
つまり、こういう記述ができるとのこと。
大体ドキュメントに書いてある。
書き方はこれだけじゃないので、詳しいところはpreloadのドキュメントを参照すること。
以上。

Bibliography

人気の投稿