In Rails you can easily get an array of full error messages from a model.
full_messages (ActiveModel::Errors) - APIdock
class Person
validates_presence_of :name, :address, :email
validates_length_of :name, in: 5..30
end
person = Person.create(address: '123 First St.')
person.errors.full_messages
# => ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Email can't be blank"]
Here’s how I did it for my Phoenix project with Ecto.
def save_torrent(torrent) do
changeset = Torrent.changeset(%Torrent{}, torrent)
case Repo.insert(changeset) do
{:ok, _torrent} ->
Logger.info "Torrent saved to database: #{torrent.name}"
{:error, changeset} ->
errors = Enum.reduce(changeset.errors, [], fn (field_error, errors) ->
{field, {error_message, _}} = field_error
errors = ["#{field} #{error_message}" | errors]
end)
Logger.error "Torrent skipped: #{torrent.name} - Errors: #{Enum.join(errors, ", ")}"
end
end
We iterate through a changeset’s errors map and reduce each one into a errors accumulator.
Here’s the relevant code:
errors = Enum.reduce(changeset.errors, [], fn (field_error, errors) ->
{field, {error_message, _}} = field_error
errors = ["#{field} #{error_message}" | errors]
end)
Update: Jose suggested a cleaner option! Check it out.
errors = for {key, {message, _}} <- changeset.errors do
"#{key} #{message}"
end
errors ends up being a list of strings, which we can just Enum.join() to turn it into a nice comma separated string.
[error] Torrent skipped: Big Bunny - Errors: magnet has already been taken
Hopefully we can build this method directly into Ecto so in the future we can just call:
changeset.full_errors
Please leave your feedback on the feature proposal:
New feature proposal: changeset errors full message.
Implementing ActiveRecords’ errors full_messages for Elixir/Phoenix and Ecto was originally published in sergiotapia on Medium, where people are continuing the conversation by highlighting and responding to this story.