无法在phoenix中创建自定义链接:protocol Enumerable未实现

时间:2017-09-02 06:53:42

标签: elixir phoenix-framework

我是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并创建一个漂亮的网址,我缺少什么?

编辑,这是路由器声明:

get "/", PageController, :index
get "/:article", PageController, :index

我希望网址与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

1 个答案:

答案 0 :(得分:1)

您有两条路由指向同一个控制器/功能(PageController.index)。路由器帮助程序函数仅为控制器/函数的第一个实例生成,这就是为什么在尝试将Article作为第三个参数传递时会出现错误的原因。

如果您未使用get "/", PageController, :index路线,则删除该路线将解决错误。

如果您正在使用它,您必须在第二条路线上添加自定义名称,如下所示:

get "/:article", PageController, :index, as: :article_index

现在您可以使用article_index_path生成路径:

article_index_path(conn, :index, article)