When calling cast_assoc, I'd like a 'find or create' style behavior. Is there an easy way to do this in Ecto?
As a contrived example, a user belongs_to a favorite color, which is unique by color.name. If I create a new user with a favorite color that already exists, I get an error (name has already been taken). Instead I'd like to set user.color_id to the pre-existing color record. Is there a built in feature in Ecto to do this, or will I have to roll my own solution?
User changeset:
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:name])
|> cast_assoc(:color)
end
Failing test:
test "create user with pre-existing color" do
Repo.insert!(%Color{name: "red"})
%User{}
|> User.changeset(%{name: "Jim", color: %{name: "red"}})
|> Repo.insert!
end