Подтвердить что ты не робот

Смешивание областей и ассоциаций в Phoenix/Ecto

В Rails, если у меня есть следующая настройка:

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post

  def self.approved
    where(approved: true)
  end
end

Тогда я могу сделать что-то вроде этого:

post = Post.find(100)
comments = post.comments.approved

чтобы быстро получить все одобренные комментарии для данного Post.

Как я могу сделать что-то подобное в Ecto?

defmodule MyApp.Post do
  use Ecto.Model

  schema "posts" do
    #columns omitted
    has_many :comments, MyApp.Comment
  end
end

defmodule MyApp.Comment do
  use Ecto.Model

  schema "comments" do
    #columns omitted
    belongs_to :post, MyApp.Post
  end
end

У меня есть Post с comments pre-loaded:

post = MyApp.Post
       |> MyApp.Repo.get(100)
       |> MyApp.Repo.preload(:comments)

Я даже не уверен, с чего начать с области approved в MyApp.Comment.

4b9b3361

Ответ 1

Предварительные загрузки могут принимать запросы. Таким образом, вы можете фильтровать связанные комментарии, подобные этому.

post = 
  MyApp.Post
  |> Ecto.Query.preload(comments: ^MyApp.Comment.approved(MyApp.Comment))
  |> MyApp.Repo.get(100)

И в вашей модели Comment

def approved(query) do
  from c in query,
  where: c.approved == true
end

Ответ 2

Я не думаю, что это возможно с текущей версией Ecto. Предварительная загрузка не позволяет фильтровать. Альтернатива заключается в том, чтобы получить комментарии с запросом:

(from comment in MyApp.Comment, 
  where: comment.post_id == ^post_id 
    and comment.approved == true,
select: comment) |> Repo.all