Giter Club home page Giter Club logo

Comments (9)

doomspork avatar doomspork commented on September 3, 2024 1

Howdy @fireproofsocks! I'm happy to add a little section like this:

defp deps do
  [{:jsonapi, "~> 0.1.0"}]
end

I'm not sure this is the right place for a write up on how to add packages and resolve them.

from jsonapi.

jherdman avatar jherdman commented on September 3, 2024 1

@fireproofsocks @oskarrough this issue is a bit stale, but I wanted to check in to see if you've got what you needed before I closed it.

from jsonapi.

oskarrough avatar oskarrough commented on September 3, 2024

Expanding on this, I am not sure how to use this library with Phoenix 1.3.

For instance, how do you merge the view from the readme with the default generated one?

defmodule HelloWeb.UserView do
  use HelloWeb, :view

  alias HelloWeb.UserView, as: UserView

  def render("index.json", %{users: users}) do
    %{data: render_many(users, UserView, "user.json")}
  end

  def render("show.json", %{user: user}) do
    %{data: render_one(user, UserView, "user.json")}
  end

  def render("user.json", %{user: user}) do
    %{id: user.id,
      email: user.email,
      password: user.password}
  end
end

from jsonapi.

doomspork avatar doomspork commented on September 3, 2024

@oskarrough the instructions say to add use JSONAPI.View to the top of your view module and the other methods to the body, have you tried that yet?

from jsonapi.

oskarrough avatar oskarrough commented on September 3, 2024

@doomspork thank you. I did try but can't see any change in the JSON output. I'm new to this and feel like I am missing something obivous. Shouldn't the bottom user.json in the view be changed to something?

# two methods from user controller
def index(conn, _params) do
  users = Accounts.list_users()
  render(conn, "index.json", users: users)
end

def show(conn, %{"id" => id}) do
  user = Accounts.get_user!(id)
  render(conn, "show.json", user: user)
end
defmodule HelloWeb.UserView do
  use HelloWeb, :view
  use JSONAPI.View, type: "users"

  alias HelloWeb.UserView, as: UserView

  def fields() do
    [:email]
  end

  def render("index.json", %{users: users}) do
    %{data: render_many(users, UserView, "user.json")}
  end

  def render("show.json", %{user: user}) do
    %{data: render_one(user, UserView, "user.json")}
  end

  def render("user.json", %{user: user}) do
    %{id: user.id,
      email: user.email
    }
  end
end

from jsonapi.

doomspork avatar doomspork commented on September 3, 2024

@oskarrough no worries! The https://github.com/jeregrine/jsonapi#how-to-use-with-phoenix section touches on what needs to occur but perhaps we could expand on it some.

JSON API generates a lot of those functions for you, take a peek here: https://github.com/jeregrine/jsonapi/blob/master/lib/jsonapi/view.ex#L143

If you don't intend to do anything additional to the view before returning it, you can just do this:

defmodule HelloWeb.UserView do
  use HelloWeb, :view
  use JSONAPI.View, type: "users"

  def fields() do
    [:email]
  end
end

The rest should work as expected.

from jsonapi.

oskarrough avatar oskarrough commented on September 3, 2024

@doomspork aah, I see. Thank you, it works. It was helpful to see the actual code from the JSONAPI.View.. should have checked that :)

It would be great with an example for queries, sorting and filtering as well. I see that GET /api/users?sort=name will set conn.assigns.jsonapi_query.sort to [asc: :name] and tried the following:

# user controller
plug JSONAPI.QueryParser,
  filter: ~w(age),
  sort: ~w(created_at email),
  view: HelloWeb.UserView

def index(conn, _params) do
  sort = conn.assigns.jsonapi_query.sort
  render(conn, "index.json", data: Accounts.list_users_sorted(sort))
end

# context
def list_users_sorted(sort) do
  Repo.all(User |> order_by(^sort))
end

which works! Is it the right way to do it?

from jsonapi.

doomspork avatar doomspork commented on September 3, 2024

@oskarrough that's wonderful news!

That is one way to implement the order by and includes. It's difficult to document given that everyone's application will be setup differently and there's no single "right way".

In a previous project I relied on plugs to handle this, please note this code is incomplete because I don't have time to clean this up enough to share in it's entirety:

defmodule JSONAPI.Includes do
  def call(%{method: "POST"} = conn, _), do: conn
  def call(%{assigns: %{jsonapi_query: query}, private: %{resource: resource}} = conn, opts) do
    repo = Keyword.fetch!(opts, :repo)
    resource = repo.preload(resource, normalize_includes(query.includes))

    Plug.Conn.put_private(conn, :resource, resource)
  end
  def call(conn, _), do: conn

  defp normalize_include(include) when is_atom(include), do: include
  defp normalize_include({}), do: []
  defp normalize_include(include) when is_tuple(include) do
    parent = elem(include, 0)
    children = Tuple.delete_at(include, 0)
    Keyword.put([], parent, normalize_include(children))
  end

  defp normalize_includes(includes), do: Enum.map(includes, &normalize_include/1)
end

defmodule JSONAPI.Query do
  def call(%{assigns: %{jsonapi_query: jsonapi_query}} = conn, opts) do
      resource = Keyword.get(opts, :resource)
      repo = Keyword.fetch!(opts, :repo)
      filters = query_filters(jsonapi_query)

      resource
      |> select([r], r)
      |> order_by([r], ^jsonapi_query.sort)
      |> build_query(filters)
      |> repo.all
      |> handle_results(conn)
    end

    def call(conn, _opts) do
      conn
    end

    defp build_query(query, filters) when is_list(filters), do: Enum.reduce(filters, query, &build_query/2)
    defp build_query({k, v}, query) when is_list(v), do: where(query, [r], field(r, ^k) in ^v)
    defp build_query({k, v}, query), do: where(query, [r], field(r, ^k) == ^v)

    defp query_filters(%{filter: filters}), do: Enum.map(filters, &query_filter/1)

    defp query_filter({k, v}) when is_binary(v) do
      value =
        case String.split(v, ",") do
          [one] -> one
          list  -> list
        end

      {k, value}
    end
    defp query_filter(filter), do: filter  
end

from jsonapi.

fireproofsocks avatar fireproofsocks commented on September 3, 2024

Thanks @jherdman I think we're good! Thanks for checking!

from jsonapi.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.