2015-06-03 11 views
27

Cố gắng tạo ứng dụng với Elixir + Phoenix, điều đó có thể xử lý cả yêu cầu "trình duyệt" và "api" để xử lý tài nguyên của nó.Phoenix - bộ điều khiển có nhiều kết xuất

Có thể làm điều đó mà không cần phải làm điều gì đó như thế:

scope "/", App do 
    pipe_through :browser 

    resources "/users", UserController 
end 

scope "/api", App.API as: :api do 
    pipe_through :api 

    resources "/users", UserController 
end 

đó có nghĩa là phải tạo ra hai bộ điều khiển, mà có thể có các hành vi tương tự, ngoại trừ việc nó sẽ render HTML với trình duyệt đường dẫn và, nói JSON, cho đường ống dẫn api.

Tôi đã nghĩ có lẽ một cái gì đó như Rails respond_to do |format| ...

Trả lời

21

tôi sẽ không khuyên bạn nên nó (tôi sẽ khuyên bạn nên có hai bộ điều khiển và di chuyển logic của bạn thành một mô-đun khác nhau mà được gọi bằng cả hai bộ điều khiển) nhưng nó có thể được thực hiện . Bạn có thể chia sẻ một bộ điều khiển, nhưng bạn vẫn cần một đường dẫn riêng để đảm bảo loại phản hồi chính xác (html/json) được thiết lập.

Sau đây sẽ sử dụng cùng một bộ điều khiển và chế độ xem, nhưng hiển thị json hoặc html tùy thuộc vào tuyến đường. "/" là html, "/ api" là json.

Router:

defmodule ScopeExample.Router do 
    use ScopeExample.Web, :router 

    pipeline :browser do 
    plug :accepts, ["html"] 
    plug :fetch_session 
    plug :fetch_flash 
    plug :protect_from_forgery 
    end 

    pipeline :api do 
    plug :accepts, ["json"] 
    end 

    scope "/", ScopeExample do 
    pipe_through :browser # Use the default browser stack 

    get "/", PageController, :index 
    end 

    scope "/api", ScopeExample do 
    pipe_through :api # Use the default browser stack 

    get "/", PageController, :index 
    end 
end 

Bộ điều khiển:

defmodule ScopeExample.PageController do 
    use ScopeExample.Web, :controller 

    plug :action 

    def index(conn, params) do 
    render conn, :index 
    end 
end 

Xem:

defmodule ScopeExample.PageView do 
    use ScopeExample.Web, :view 

    def render("index.json", _opts) do 
    %{foo: "bar"} 
    end 
end 

Bạn cũng có thể chia sẻ router và có tất cả mọi thứ được phục vụ bởi các tuyến đường tương tự nếu bạn sử dụng một router như:

defmodule ScopeExample.Router do 
    use ScopeExample.Web, :router 

    pipeline :browser do 
    plug :accepts, ["html", "json"] 
    plug :fetch_session 
    plug :fetch_flash 
    plug :protect_from_forgery 
    end 


    scope "/", ScopeExample do 
    pipe_through :browser # Use the default browser stack 

    get "/", PageController, :index 
    end 
end 

Sau đó, bạn có thể chỉ định định dạng bằng cách sử dụng ?format=json ở cuối url - tôi khuyên bạn nên sử dụng các url khác nhau cho API và trang web của mình.

+1

Bạn không cần phải nội suy định dạng, bạn có thể sử dụng nguyên tử cho mẫu và tiêu đề chấp nhận sẽ được sử dụng để hiển thị định dạng chính xác. –

+0

@ChrisMcCord cảm ơn - Tôi đã thử một vài điều và không thể làm cho tiêu đề kiểu nội dung hoạt động. Tôi sẽ cập nhật câu trả lời của mình. – Gazler

+1

@gazler nếu nhiều bộ điều khiển là giải pháp, chúng ta nên đặt tên cho không gian sao cho chúng khác nhau nhưng tách biệt? bộ điều khiển API nên đi vào bộ điều khiển/API/user_controller.exs? – DogEatDog

29

Như Gazler nói, có lẽ bạn đang phục vụ tốt nhất bởi có đường ống riêng biệt, nhưng một cái gì đó như thế này có thể được vui vẻ thực hiện với mô hình kết hợp vào các hành động điều khiển giống nhau:

def show(conn, %{"format" => "html"} = params) do 
    # ... 
end 

def show(conn, %{"format" => "json"} = params) do 
    # ... 
end 

Hoặc nếu các cơ quan chức năng đều giống nhau , và bạn sẽ chỉ muốn làm một mẫu dựa trên các tiêu đề chấp nhận, bạn có thể làm:

def show(conn, params) do 
    # ... 

    render conn, :show 
end 

Đi qua một nguyên tử như tên mẫu sẽ gây phượng để kiểm tra chấp nhận tiêu đề và đưa ra các .json hoặcMẫu.

+2

Nó không giống như thông qua trong 'params' có' định dạng' trong nó? Có điều gì đã thay đổi kể từ câu trả lời này không? –

+1

Câu trả lời này có vẻ không hợp lệ nữa.Tuy nhiên, bạn có thể khớp mẫu như 'def index (% {private:% {phoenix_format:" json "}} = conn, params) do'. Tôi không biết liệu điều này có an toàn hay không. –

+0

@d_rail .. hoạt động tốt dưới Phoenix 1.3, cảm ơn bạn. –

Các vấn đề liên quan