2016-01-26 10 views
5

Zamiast pobierać dane z bazy danych, chcę użyć jako danych ręcznie zapisanego pliku JSON. Załóżmy, że moje dane są następujące:Jak renderować plik JSON z frameworkiem Phoenix?

[ 
    { "id": 1, "name": "Alice", "email": "[email protected]" }, 
    { "id": 2, "name": "Bob", "email": "[email protected]" }, 
    { "id": 3, "name": "Charles", "email": "[email protected]"} 
] 

i jest on zapisany w pliku o nazwie MOCK_DATA.json. Co należy zrobić, aby renderować ten plik, gdy uzyskuję dostęp do adresu URL localhost:port/api/v1/users? Co powiedzie na adres URL strony localhost:port/api/v1/users/1, aby pokazać { "id": 1, "name": "Alice", "email": "[email protected]" }?

+1

Po prostu chcesz kpić z reakcji, aby szybko zacząć, i zastąpić ją "prawdziwą" implementacją później? To chyba nie musi być produkcja gotowa? –

+0

@PatrickOscity tak, dokładnie. –

Odpowiedz

9

Oto prosty przykład działa ...

Krok 1: Tworzenie aplikacji Phoenix

np exjson dla ExampleJson lub cokolwiek nazwa Twojego jak

mix phoenix.new exjson --no-ecto --no-brunch --no-html 
Krok 2: Konfiguracja routera

Dodaj ten zakres do pliku web/router.ex

scope "/api/v1", Exjson do 
    pipe_through :api 
    resources "/users", UserController 
    end 
Krok 3: Włóż dane makiety gdzieś ac cessible do aplikacji
priv/data/MOCK_DATA.json 
Krok 4: Skonfiguruj UsersController

Pomyśl o kontrolerze użytkowników jako posiadające szereg działań (funkcji) gdzie conn struct doprowadza się z końcowego phoenix wraz z wszelkimi parametrów

defmodule Exjson.UserController do 
    use Exjson.Web, :controller 

    # GET http://localhost:4000/api/v1/users/ 
    def index(conn, _params) do 
    users = File.read!(file) |> Poison.decode!() 
    render conn, users: users 
    end 

    # GET http://localhost:4000/api/v1/users/1 
    def show(conn, params) do 
    users = File.read!(file) |> Poison.decode!() 
    render conn, user: users |> Enum.find(&(&1["id"] === String.to_integer(params["id"]))) 
    end 

    defp file() do 
    Path.join(:code.priv_dir(:exjson), "data/MOCK_DATA.json") 
    end 

end 
Krok 5: Konfigurowanie UsersView

można również pomyśleć o użytkownikom wyświetlanie jako o funkcji, które będzie świadczyć dane otrzymane z kontrolera w odpowiedni sposób. W tym przypadku używasz danych json, więc phoenix ma wbudowane funkcje, które mogą Ci w tym pomóc.

defmodule Exjson.UserView do 
    use Exjson.Web, :view 

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

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

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

end 
+0

Jeśli wysyłasz json w api, to warunki renderowania danych w przeglądarce, często w dzisiejszych czasach, deweloperzy używają tak zwanych frameworków "Single Page Apps" do tworzenia interfejsu użytkownika (komponentu przeglądarki). Np. [Aurelia] (http://aurelia.io/), [Angular2] (https://angular.io/) ale to jest tylko kilka nazw, jest wiele ... –

+0

Co to jest ': code.priv_dir (: exjson) 'parametr w funkcji' Path.join'? Przeszukałem kod źródłowy phoenix, ale moje poszukiwania wyszły pusto. –

+1

Jest to funkcja z biblioteki [erlang library] (http://erlang.org/doc/man/code.html#priv_dir-1) .. po prostu pobiera twój prywatny folder. Pliki w tym folderze są dostępne dla aplikacji. –

1

Jeśli plik jest statyczny (nie zmienia się w czasie trwania usługi), możesz go odczytać, gdy aplikacja będzie kompilować się w kontrolerze. Sprawdź parametry modułu (te zdefiniowane w module, poza funkcjami). W ten sposób będę sparsowany raz.

Jeśli ten plik jest dynamiczny, być może trzeba będzie go przeczytać za każdym razem, gdy API zostanie wywołany i przeanalizować go. Naprawdę niezalecane, ponieważ czytanie pliku z dysku IO spowolni go.

W każdym przypadku wynik pliku, parsowany do mapy, może zostać przekazany do widoku i renderowany, bez różnicy od bazy danych.

Edytuj: kolejną sugestią jest sformatowanie JSON (jeśli to możliwe) i uzyskanie id jako klucza, a resztę danych jako wartości. W ten sposób wyszukiwanie przez id będzie bardzo szybkie, podobnie jak indeks klucza podstawowego w bazie danych.

+0

Jestem początkującym, zarówno w Phoenix, jak i w Elixir, więc nie zrozumiałem twojej odpowiedzi. Czy możesz podać mi przykłady kodu? Ponadto dziękuję za porady dotyczące wydajności, ale w tym momencie nie wiem nawet, jak renderować dane w przeglądarce, dlatego doceniłbym konkretne instrukcje w tym obszarze. –

8

Aby dać ci prawdziwy kod, aby zacząć, to jest najprostsze, co mogę myśleć:

defmodule MyApp.UserController do 
    @mock_data (
    Application.app_dir(:my_app, "priv/mock_data/users.json") 
    |> File.read! 
    |> Poison.decode! 
) 

    def index(conn, _params) do 
    conn 
    |> put_status(:ok) 
    |> json(@mock_data) 
    end 
end 

Potem wystarczy zapisać fałszywych danych w priv/mock_data/users.json wewnątrz projektu. Mogą tam być literówki, ale masz podstawowy pomysł ...

2

Ponieważ po prostu echo JSON z powrotem do punktu końcowego /users, w tym przypadku nie potrzebujesz wywołania Poison.decode/1, który niepotrzebnie dekodowania/kodowania JSON.

Więc dostosowania kodu Patryka:

defmodule MyApp.UserController do 
    @mock_data_string (
    Application.app_dir(:my_app, "priv/mock_data/users.json") 
    |> File.read! 
) 

    def index(conn, _params) do 
    conn 
    |> put_resp_content_type("application/json") 
    |> send_resp(200, @mock_data_string) 
    end 
end 

Jednak dla punktu końcowego /users/1, to najlepiej, aby wyodrębnić wartości za pomocą Poison.decode/1, jako odpowiedź użytkownika @ stephen_m ilustruje.

+0

To miło! Potrzebuję czegoś podobnego (po prostu przesyłając dane JSON z innego serwera przez Phoenix). Dam temu szansę! – fenton