无法在 phoenix 中创建自定义链接:协议 Enumerable 未实现
Posted
技术标签:
【中文标题】无法在 phoenix 中创建自定义链接:协议 Enumerable 未实现【英文标题】:Can't create a custom link in phoenix: protocol Enumerable not implemented 【发布时间】:2018-02-11 04:06:47 【问题描述】:我是 Elixir/Phoenix 的新手,我想创建一个不使用模型 ID 但最终出现错误的链接:
protocol Enumerable not implemented for %XX.YY.Article__meta__: #Ecto.Schema.Metadata<:built, "articles">, content: nil, id: nil, inserted_at: nil, short_title: "lalalilala", slug: 457, title: nil, updated_at: nil.
这是我尝试创建链接的方式:
def link_to_article(conn, article_map) do
article = struct(%XX.YY.Article, article_map)
link article_map.short_title,
to: page_path(conn, :index, article),
class: "btn btn-default"
end
我有这个 to_param 的实现:
defimpl Phoenix.Param, for: XX.YY.Article do
alias XX.YY.Slug
def to_param(%slug: slug, title: title) do
"#Slug.pad_slug(slug)-#Slug.slugify_title(title)"
end
end
如果我将article_map
提供给链接,则链接有效,但很难看(地图成为查询字符串)。 article
强制使用 to_param
并创建漂亮的 URL 缺少什么?
编辑,这里是路由器声明:
get "/", PageController, :index
get "/:article", PageController, :index
因为我希望 URL 类似于 qweqwe.com/padded_slug-article_title
在控制器中,我将索引定义为:
def index(conn, %"article" => article_identifier) do
[slug|_] = article_identifier |> String.split("-")
article = XX.YY.get_current_article(slug)
case article do
nil -> Phoenix.Controller.redirect(conn, to: "/")
article ->
render conn, "index.html",
articles: XX.YY.get_articles_for_menu!(),
current_article: article
end
end
def index(conn, _params) do
render conn, "index.html",
articles: XX.YY.get_articles_for_menu!(),
current_article: XX.YY.get_default_article!()
end
这段代码丑吗?
到目前为止的所有路线:
page_path GET / QQ.PageController :index
user_path GET /users QQ.UserController :index
user_path GET /users/:id/edit QQ.UserController :edit
user_path GET /users/new QQ.UserController :new
user_path GET /users/:id QQ.UserController :show
user_path POST /users QQ.UserController :create
user_path PATCH /users/:id QQ.UserController :update
PUT /users/:id QQ.UserController :update
user_path DELETE /users/:id QQ.UserController :delete
article_path GET /articles QQ.ArticleController :index
article_path GET /articles/:id/edit QQ.ArticleController :edit
article_path GET /articles/new QQ.ArticleController :new
article_path GET /articles/:id QQ.ArticleController :show
article_path POST /articles QQ.ArticleController :create
article_path PATCH /articles/:id QQ.ArticleController :update
PUT /articles/:id QQ.ArticleController :update
article_path DELETE /articles/:id QQ.ArticleController :delete
page_path GET /:article QQ.PageController :index
调用栈:
(elixir) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir) lib/enum.ex:116: Enumerable.reduce/3
(elixir) lib/enum.ex:1823: Enum.reduce/3
(XX) lib/QQ/router.ex:1: QQ.Router.Helpers.segments/3
(XX) lib/QQ/router.ex:1: QQ.Router.Helpers.page_path/3
(XX) lib/QQ/views/layout_view.ex:8: QQ.LayoutView.link_to_article/2
【问题讨论】:
通常index
路径不需要对象 id 或任何对象相关数据,因此最后一个参数只是一个映射或 URL 参数的关键字列表,但这是我的疯狂猜测,用 @ 测试它987654333@ 或 edit
路径。
你能发布你的router.ex
吗?
@Dogbert 请看我的编辑!
@JustMichael 这是因为我不希望 URL 中包含 show
。我将生成的资源保留用于管理目的,并使用自定义路由进行查看。
@Sautieh 你的router.ex
中是否有另一条路线指向PageController.index
?你能发布mix phoenix.routes
的输出吗?
【参考方案1】:
您有两条路由指向同一个控制器/功能 (PageController.index
)。路由器辅助函数仅针对控制器/函数的第一个实例生成,这就是如果您尝试将文章作为第三个参数传递时会出现错误的原因。
如果您没有使用 get "/", PageController, :index
路由,删除它会修复错误。
如果你正在使用它,你必须像这样为第二条路由添加一个自定义名称:
get "/:article", PageController, :index, as: :article_index
现在您可以使用article_index_path
来生成路径:
article_index_path(conn, :index, article)
【讨论】:
哦,好吧,我想我可以在这些路线上进行模式匹配,并且在我开始摆弄 to_param 和所有东西之前它曾经工作过。我稍后会这样做,如果它有效,将接受您的回答!谢谢 不幸的是,这并没有解决问题(我删除了:article
路由并保留了/
)。当我转到/articles
(不是/users
)时,我也遇到了完全相同的错误,所以我认为问题来自以Articles
作为参数创建链接,因此来自to_param
函数..??我将在问题中添加调用堆栈
您是否完全删除了该路线或使用as:
更改其名称,正如我在答案中所写的那样?根据堆栈跟踪,您仍在使用page_path
生成文章路线。您必须使用答案中提到的新名称。
我完全删除了/:article
,所以唯一的路径page_path
是page_path GET / QQ.PageController :index
。正如我所说,当我进入文章页面Request: GET /articles
时,我遇到了完全相同的错误,因为视图中的@articles
充满了Articles
,并且在构建链接时它会中断。
您必须添加另一条路线并使用它来生成我在答案中写的链接。您不能将文章传递给 GET /
路由。以上是关于无法在 phoenix 中创建自定义链接:协议 Enumerable 未实现的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Wordpress 管理面板中创建自定义 HTML 表单?