Elixir `where`中的值`user\u id``不能转换为查询中的type:id:

Elixir `where`中的值`user\u id``不能转换为查询中的type:id:,elixir,phoenix-framework,rbac,Elixir,Phoenix Framework,Rbac,我正在尝试一个基于角色的访问控制Pheonix API。用户将在其中登录并创建会话。登录后,他可以创建一个帖子,创建的帖子将分配给该用户id。我遇到了这个问题,用户id像字符串一样出现,而不是其中的值 我尝试了String.to_integeruser_id,但它给出了一个错误,因为user_id像字符串一样出现,而不是存储id的变量 我的路由器 scope "/", PxblogWeb do pipe_through :browser get "/", PageContro

我正在尝试一个基于角色的访问控制Pheonix API。用户将在其中登录并创建会话。登录后,他可以创建一个帖子,创建的帖子将分配给该用户id。我遇到了这个问题,用户id像字符串一样出现,而不是其中的值

我尝试了String.to_integeruser_id,但它给出了一个错误,因为user_id像字符串一样出现,而不是存储id的变量

我的路由器


scope "/", PxblogWeb do
    pipe_through :browser

    get "/", PageController, :index

    resources "/users", UserController do
      resources "/posts", PostController
    end

    resources "/sessions", SessionController, only: [:new, :create, :delete]
  end

  scope "/" do
    resources "/sessions", SessionController, only: [:new, :create, :delete]
  end

  # Other scopes may use custom stacks.
  scope "/api", PxblogWeb do
    pipe_through :api

    get "/users/read", UserController, :index
  end
new.html.eex

<h1>New Post</h1>
<%= render "form.html", Map.put(assigns, :action, Routes.user_post_path(@conn, :create, :user_id)) %>
<span><%= link "Back", to: Routes.user_post_path(@conn, :index, :user_id) %></span>
session_controller.ex

plug :assign_user
  plug :authorize_user when action in [:new, :create, :update, :edit, :delete]


  defp assign_user(conn, _opts) do
    case conn.params do
      %{"user_id" => user_id} ->
        case Repo.get(Pxblog.Post.User, user_id) do
          nil  -> invalid_user(conn)
          user -> assign(conn, :user, user)
        end
      _ -> invalid_user(conn)
    end
  end

  defp invalid_user(conn) do
    conn
    |> put_flash(:error, "Invalid user!")
    |> redirect(to: Routes.page_path(conn, :index))
    |> halt
  end

  defp authorize_user(conn, _) do
    user = get_session(conn, :current_user)
    if user && (Integer.to_string(user.id) == conn.params["user_id"] || Pxblog.RoleChecker.is_admin?(user)) do
      conn
    else
      conn
      |> put_flash(:error, "You are not authorized to modify that post!")
      |> redirect(to: Routes.page_path(conn, :index))
      |> halt()
    end
  end

  def index(conn, _params) do
    posts = Repo.all(assoc(conn.assigns[:user], :posts))
    render(conn, "index.html", posts: posts)
  end

  def new(conn, _params) do
    changeset =
      conn.assigns[:user]
      |> build_assoc(:posts)
      |> Pxblog.Learn.Post.changeset(%{})
    render(conn, "new.html", changeset: changeset)
  end

  def create(conn, %{"post" => post_params}) do
    changeset =
      conn.assigns[:user]
      |> build_assoc(:posts)
      |> Pxblog.Learn.Post.changeset(post_params)
    case Repo.insert(changeset) do
      {:ok, _post} ->
        conn
        |> put_flash(:info, "Post created successfully.")
        |> redirect(to: Routes.user_post_path(conn, :index, conn.assigns[:user]))
      {:error, changeset} ->
        render(conn, "new.html", changeset: changeset)
    end
  end
defmodule PxblogWeb.SessionController do
    use PxblogWeb, :controller

    alias Pxblog.Post.User
    alias Pxblog.Post
    alias Pxblog.Repo

    import Comeonin.Bcrypt, only: [checkpw: 2, dummy_checkpw: 0]

    plug :scrub_params, "user" when action in [:create]

    def new(conn, _params) do
      render conn, "new.html", changeset: Pxblog.Post.User.changeset(%Pxblog.Post.User{}, %{})
    end

    def create(conn, %{"user" => %{"username" => username, "password" => password}})
    when not is_nil(username) and not is_nil(password) do
      user = Repo.get_by(Pxblog.Post.User, username: username)
      sign_in(user, password, conn)
    end

    def create(conn, _) do
      failed_login(conn)
    end

    defp failed_login(conn) do
      dummy_checkpw()
      conn
      |> put_session(:current_user, nil)
      |> put_flash(:error, "Invalid username/password combination!")
      |> redirect(to: Routes.page_path(conn, :index))
      |> halt()
    end

    defp sign_in(user, _password, conn) when is_nil(user) do
      failed_login(conn)
    end

    defp sign_in(user, password, conn) do
      if checkpw(password, user.password_digest) do
        conn
        |> put_session(:current_user, %{id: user.id, username: user.username, role_id: user.role_id})
        |> put_flash(:info, "Sign in successful!")
        |> redirect(to: Routes.page_path(conn, :index))
      else
        failed_login(conn)
      end
    end

    def delete(conn, _params) do
      conn
      |> delete_session(:current_user)
      |> put_flash(:info, "Signed out successfully!")
      |> redirect(to: Routes.page_path(conn, :index))
    end

end

标题中的错误表明某个地方有一个字符串,如下所示:

"some string user_id"
而不是:

"some string #{user_id}" 
其中,错误消息中指示db查询,因此:

"...where id=user_id" 
而不是

"...where id=#{user_id}"
=====

在您的新行动中,您有:

 def new(conn, _params) do
    changeset =
      conn.assigns[:user]
      |> build_assoc(:posts)
      |> Pxblog.Learn.Post.changeset(%{})
    render(conn, "new.html", changeset: changeset)
  end
render调用使变量@changeset在模板中可用,并且通过elixir magic使@conn可用。这是您的模板:

<h1>New Post</h1>
<%= render "form.html", 
    Map.put(assigns, :action, 
            Routes.user_post_path(@conn, :create, :user_id)
           ) 
 %>
<span><%= link "Back", 
 to: Routes.user_post_path(@conn, :index, :user_id) %>
</span>
并且错误消息表示子字符串user_id无法转换为:id类型。我认为Phoenix必须执行数据库查询来构建用户路径

如果您这样做:

$ iex -S mix
然后:

$ iex -S mix
iex(1)> h <YourApp>Web.Router.Helpers.user_post_path

def user_post_path(conn_or_endpoint, action, user_id)              
def user_post_path(conn_or_endpoint, action, user_id, params)          
def user_post_path(conn_or_endpoint, action, user_id, id, params)  
def user_post_path(conn_or_endpoint, action, :user_id)              
def user_post_path(conn_or_endpoint, action, :user_id, params)          
def user_post_path(conn_or_endpoint, action, :user_id, id, params)