I’ve written before about setting up a current_user
in
Phoenix and requiring
that user in your controller action. Today
I’ll be talking about scoped finds.
What is a scoped find?
In the Rails world, a scoped find looks like this:
def edit
@post = current_user.posts.find(params[:id])
end
This is a useful security technique that either finds a post that belongs to the
currently signed in user or raises an ActiveRecord::RecordNotFound
error
(which Rails turns into a 404). Doing finds like this prevents unauthorized
access without a bunch of boilerplate authorization code.
How can I do a scoped find in Ecto?
Since Elixir isn’t object oriented, you can’t do current_user.posts.find
,
but you can do something similar. The Phoenix generation tasks use
Repo.get!
which works
similarly to Active Record’s find
. For those times when you need to more than
an id lookup, Ecto also has
Repo.get_by!
which is
works like get!
but with additional parameters.
It could be used liked this for the same functionality as the Rails/Ruby code above:
def edit(conn, %{"id" => id}) do
post = Repo.get_by!(Post, id: id, user_id: current_user(conn).id)
render(conn, "edit.html", post: post)
end
This will either find a record or raise an Ecto.NoResultsError
(which Phoenix
will turn into a 404).
I hope this helps you perform scoped finds when working on your Phoenix apps.