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.title
s.
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 |> Enum.map(fn({post, index<3}) -> %>
Best Regards,
ykostov
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)
end
Otherwise try
Home.list_posts(params) |> Enum.take(3)
But changing the query/adding another function with the limit is the far better option.
2 Likes
sanswork gave you the correct answer answer you need, but on your example, the reason why Enum.map didn’t work is because given a list of n
elements, Enum.map 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