Hey there. I come from a Ruby on Rails background and was trying to figure out how to do things in Phoenix similar to how they’re done in Rails.
I have a setup where a User can have Categories, but a specific User can only have one Category with a given name. For instance, Steve can have one “Default” category, but not two, and Tom can have a “Default” category that is not the same as Steve’s.
In Rails, this can be done kinda like this:
def cat_name_unique_for_user?(user_id, cat_name)
return false unless Category.find_by(user_id: user_id, name: cat_name).nil?
true
end
The closest equivalent I could come up with without trying to unravel the mysteries of how to actually access the return of Ecto.query()
was this validator
defp validate_name_unique_for_user(changeset, user_id, name) do
query = from(cat in "categories", where: cat.user_id == ^user_id, where: cat.name == ^name)
unless Repo.exists?(query) do
add_error(changeset, :name, "Name is not unique for current user!")
end
changeset
end
This gets called in changesets by:
category
...
|> validate_name_unique_for_user(:user_id, :name)
The error I get back when trying this approach is
** (DBConnection.EncodeError) Postgrex expected an integer in -9223372036854775808..9223372036854775807, got :user_id. Please make sure the value you are passing matches the definition in your table or in your query or convert the value accordingly.
Given I’m interpolating the user_id, I would expect that to only ever be an integer, not an atom. Can someone please explain to me where I’ve gone wrong here? These speedbumps with Ecto are proving obnoxious. Thanks!