Render specific number of Ecto members (resource)

Hello Devs!

If we have created a CRUD resource, for example - posts we could render them in our template with

<%= for post <- @posts do %>
  <%= post.title %>
<% end %>

and of course with list in our controller

websites = Home.list_posts(params)

And that renders all posts’ post.titles.
But for example if we have 6 members in that posts schema, how should we render in template only first 3 ones?

I have tried:

<%= @posts |> Enum.with_index |>{post, index<3}) ->  %>

Best Regards,

Best option would be to add a limit to your ecto query so you aren’t pulling out more data than you need.

def list_posts_limited(params, limit) do
  #not sure what params represents so left that part out
  Repo.all(from p in Post, limit: ^limit)

Otherwise try

Home.list_posts(params) |> Enum.take(3)

But changing the query/adding another function with the limit is the far better option.


sanswork gave you the correct answer answer you need, but on your example, the reason why didn’t work is because given a list of n elements, returns a list of m elements - it maps from one element to another.

To get from n element to n-m element you can use something like Enum.reduce, or specifically in your use case, Enum.filter would work in tandem with Enum.with_index.

iex(4)> [:a, :b, :c, :d, :e] |> Enum.with_index() |> Enum.filter(fn {_, index} → index < 3 end)
[a: 0, b: 1, c: 2]

iex(5)> [:a, :b, :c, :d, :e] |> Enum.with_index() |> Enum.reduce([], fn {el, index}, acc when index < 3 → [el | acc]; _, acc → acc end)
[:c, :b, :a]

But again, Enum.take/2 is much more idiomatic and delegating to database is also the correct approach since that means you’re not fetching unnecessary data

1 Like