slug 包含一个 nil 值
slug contains a nil value
我关注了 elixircasts 页面上的 this episode。我在创建新记录时遇到问题。当我尝试添加一本新书时,我遇到了这样的错误
cannot convert Bookstore.Inventory.Book to param, key :slug contains a nil value
我不知道我的代码哪里有问题。我已经编写了相同的代码来为我的作者的页面创建 slug,并且它有效。如果指出我犯了错误,我将不胜感激。
我正在使用 {:slugify, "~> 1.3"}
.
inventory/book.ex
@derive {Phoenix.Param, key: :slug}
schema "books" do
field(:description, :string)
field(:image_url, BookstoreWeb.Uploaders.ImageUploader.Type)
field(:isbn, :string)
field(:original_price, :float)
field(:title, :string)
field(:slug, :string)
field(:year_published, :integer)
belongs_to(:category, Bookstore.Genres.Category)
belongs_to(:author, Bookstore.Writers.Author)
timestamps()
end
@doc false
def changeset(book, attrs) do
book
|> cast(attrs, [
:author_id,
:category_id,
:isbn,
:title,
:description,
:year_published,
:original_price,
:slug
])
|> validate_required([:isbn, :title, :description, :year_published, :original_price])
|> build_slug()
|> cast_attachments(attrs, [:image_url])
end
def build_slug(changeset) do
id = get_field(changeset, :id)
title = get_field(changeset, :title)
if id && title do
name = Enum.join([id, title], "")
slug = Slug.slugify(name)
put_change(changeset, :slug, slug)
else
changeset
end
end
inventory.ex
def get_book!(slug),
do:
Repo.get_by!(Book, slug: slug)
|> Repo.preload(:category)
|> Repo.preload(:author)
def create_book(attrs \ %{}) do
%Book{}
|> Book.changeset(attrs)
|> Repo.insert()
end
默认情况下,Ecto 让数据库自动生成主键(参见 docs),这意味着 id
只有在书籍保存到数据库后才会生成(在调用Repo
), 之前无法检索。
您在 build_slug
中的 get_field(changeset, :id)
调用将 return nil
,您的 else
分支将被评估并且该书将与 nil
slug 一起保存。
在您分享的 link 中,slug
仅从 title
构建,这是典型的方法。
如果您随后想使用 /books/123-my-title
等 URL 访问它,可以使用 String.split(id_and_slug, "-", parts: 2)
.
等方式解析您的参数
我关注了 elixircasts 页面上的 this episode。我在创建新记录时遇到问题。当我尝试添加一本新书时,我遇到了这样的错误
cannot convert Bookstore.Inventory.Book to param, key :slug contains a nil value
我不知道我的代码哪里有问题。我已经编写了相同的代码来为我的作者的页面创建 slug,并且它有效。如果指出我犯了错误,我将不胜感激。
我正在使用 {:slugify, "~> 1.3"}
.
inventory/book.ex
@derive {Phoenix.Param, key: :slug}
schema "books" do
field(:description, :string)
field(:image_url, BookstoreWeb.Uploaders.ImageUploader.Type)
field(:isbn, :string)
field(:original_price, :float)
field(:title, :string)
field(:slug, :string)
field(:year_published, :integer)
belongs_to(:category, Bookstore.Genres.Category)
belongs_to(:author, Bookstore.Writers.Author)
timestamps()
end
@doc false
def changeset(book, attrs) do
book
|> cast(attrs, [
:author_id,
:category_id,
:isbn,
:title,
:description,
:year_published,
:original_price,
:slug
])
|> validate_required([:isbn, :title, :description, :year_published, :original_price])
|> build_slug()
|> cast_attachments(attrs, [:image_url])
end
def build_slug(changeset) do
id = get_field(changeset, :id)
title = get_field(changeset, :title)
if id && title do
name = Enum.join([id, title], "")
slug = Slug.slugify(name)
put_change(changeset, :slug, slug)
else
changeset
end
end
inventory.ex
def get_book!(slug),
do:
Repo.get_by!(Book, slug: slug)
|> Repo.preload(:category)
|> Repo.preload(:author)
def create_book(attrs \ %{}) do
%Book{}
|> Book.changeset(attrs)
|> Repo.insert()
end
默认情况下,Ecto 让数据库自动生成主键(参见 docs),这意味着 id
只有在书籍保存到数据库后才会生成(在调用Repo
), 之前无法检索。
您在 build_slug
中的 get_field(changeset, :id)
调用将 return nil
,您的 else
分支将被评估并且该书将与 nil
slug 一起保存。
在您分享的 link 中,slug
仅从 title
构建,这是典型的方法。
如果您随后想使用 /books/123-my-title
等 URL 访问它,可以使用 String.split(id_and_slug, "-", parts: 2)
.