Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preloading associations and paginating

I have a show action in my PersonController which is this:

person = Repo.get_by(Person, nick: params["nick"])
page = Message
|> where([m], m.person_id == ^person.id)
|> where([m], m.hidden == false)
|> order_by([m], desc: m.created_at)
|> Repo.preload(:channel)
|> Repo.paginate(page: params["page"], page_size: 250)

The paginate method comes from the Scrivener package.

With the Repo.preload line there, I get this error:

key :__meta__ not found in: #Ecto.Query<from m in Logs.Message, where: m.person_id == ^34424, where: m.hidden == false, order_by: [desc: m.created_at]>

If I remove the Repo.preload, this code works fine. I need to preload the channel because in the message template I generate a link to a specific channel:

<a href='/<%= @message.channel.name %>?date=<%= date %>#<%= @message.id %>'>
  [<%= @message.created_at |> Calendar.Strftime.strftime!("%H:%M:%S") %>]
</a>

The channels that a person can send messages to over a single day can vary, and so I would like to preload the channels. How can I do this?

like image 939
Ryan Bigg Avatar asked Nov 19 '15 22:11

Ryan Bigg


1 Answers

Repo.preload expects to receive a model or a list of models. It looks like you're passing it a query. There are two solutions:

  1. Move Repo.preload after the Repo.paginate call - at this point we're working with models (I presume Repo.paginate executes the query, I'm not directly familiar with it)
  2. Change the call from Repo.preload to Ecto.Query.preload - the later transforms the query and inserts the information about the preloads directly into the generated query
like image 88
michalmuskala Avatar answered Oct 04 '22 17:10

michalmuskala