def create_article(attrs \\ %{}) do
%Article{}
|> Article.changeset(attrs)
|> Ecto.Changeset.cast_assoc(:category, with: &Category.changeset/2)
|> Repo.insert()
end
I think you want to that when you want users to create an article and a category at the same time or update an existing category at the same time. And you need to preload an empty struct or an existing record for the association following you to create a new or update an existing one.
<div class="field">
<%= label f, :category, class: "label" %>
<div class="control">
<%= select f, :category_id, @categories %>
</div>
<p class="help is-danger"><%= error_tag f, :category %></p>
</div>
But given this part of your form I can assume that the category to associate to the new article already exists and just has to be selected. In this case you just have to update your article schema with an additional changeste like below:
def create_changeset(article, attrs) do
article
|> cast(attrs, [:title, :content, :published, :category_id])
|> validate_required([:title, :content, :published, :category_id])
|> foreign_key_constraint(:category_id, message: "Category not found!")
|> unique_constraint(:title)
end
So I just add one more field in the cast and validate_required functions: category_id which will be submited by the form. The foreign_key_constraint validator will throw an error if by some mean the user attempt to submit an invalid category id. So you use this changeset only to create new article unless you want to allow user to change also the category when updating an article. If you don’t want them to be able to uppdate the category of existing articles you just use your initial changeset for article update.






















