无法在 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_pathpage_path GET / QQ.PageController :index。正如我所说,当我进入文章页面Request: GET /articles 时,我遇到了完全相同的错误,因为视图中的@articles 充满了Articles,并且在构建链接时它会中断。 您必须添加另一条路线并使用它来生成我在答案中写的链接。您不能将文章传递给 GET / 路由。

以上是关于无法在 phoenix 中创建自定义链接:协议 Enumerable 未实现的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Xcode 中创建自定义 UIView?

如何在 Wordpress 管理面板中创建自定义 HTML 表单?

在 dotnet 3.5 中创建自定义控件的命令 [关闭]

在 PayPal Payflow Link 信用卡表单中创建自定义字段

如何在 Vue.js 中创建自定义链接组件?

无法在 Spring Data Repository 中创建自定义查询方法 [重复]