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])
endThis 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)
endThis 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.