Generating HTML and JSON Scaffold with Phoenix 1.3 (1.3.2) Generators

In Rails, when we generate a new model, we often get the dual benefit of getting HTML and JSON scaffolded for us at the same time within same controllers. Default Rails generates JBuilder views and handles the views in the controllers. This is a nice feature that helps us get up and running quickly for most Rails projects. In most cases, all of the API controllers and routes are namespaced into a /api/ path for clarification.

The Phoenix Framework doesn't do this generation for you and it would be more difficult to use the same controllers. Phoenix actually does it in our opinion, better, because we can scaffold the HTML and JSON in the namespace with generators. In these cases, we want to scaffold both HTML and JSON using a common context and schema for the project /lib/ but have different functionality in the /lib/web/.

We can do this by starting off with our basic generator for HTML that will generate the views, templates, controller, schema, and context. This will create the Ecto Migration, set up the schema and /lib/ calls. This will give us everything we want in /posts

mix phx.gen.html Blog Post posts title:string content:string

Next, to get the API namespace, we run a very similar generator for JSON, but include the --web flag for the namespace and the --no-context and --no-schema flags to source the existing context and schema. 

mix phx.gen.json Blog Post posts title:string content:string --web Api --no-context --no-schema

Although we have the scaffolded code, we aren't done yet. We namespaced the route with /api/ but the generated code below did not give us the path namespace for api_post_path. We will need to add as: :api to the scope in routes.
 

Generated Code:

scope "/api", PhxGenHtmlJsonWeb.Api do
  pipe_through :api
  ...
  resources "/posts", PostController
end

Modified for the correct route paths:

scope "/api", PhxGenHtmlJsonWeb.Api, as: :api do
  pipe_through :api
  ...
  resources "/posts", PostController
end

You can find the sample project here: https://github.com/kickinespresso/phx_gen_html_json


Generator Results:

The database for PhxGenHtmlJson.Repo has been created
cjs-MBP15:phx_gen_html_json cj$ mix phx.gen.html Blog Post posts title:string content:string
* creating lib/phx_gen_html_json_web/controllers/post_controller.ex
* creating lib/phx_gen_html_json_web/templates/post/edit.html.eex
* creating lib/phx_gen_html_json_web/templates/post/form.html.eex
* creating lib/phx_gen_html_json_web/templates/post/index.html.eex
* creating lib/phx_gen_html_json_web/templates/post/new.html.eex
* creating lib/phx_gen_html_json_web/templates/post/show.html.eex
* creating lib/phx_gen_html_json_web/views/post_view.ex
* creating test/phx_gen_html_json_web/controllers/post_controller_test.exs
* creating lib/phx_gen_html_json/blog/post.ex
* creating priv/repo/migrations/20180309180927_create_posts.exs
* creating lib/phx_gen_html_json/blog/blog.ex
* injecting lib/phx_gen_html_json/blog/blog.ex
* creating test/phx_gen_html_json/blog/blog_test.exs
* injecting test/phx_gen_html_json/blog/blog_test.exs

Add the resource to your browser scope in lib/phx_gen_html_json_web/router.ex:

resources "/posts", PostController

Remember to update your repository by running migrations:

$ mix ecto.migrate

cjs-MBP15:phx_gen_html_json cj$ mix phx.gen.json Blog Post posts title:string content:string --web Api --no-context --no-schema
* creating lib/phx_gen_html_json_web/controllers/api/post_controller.ex
* creating lib/phx_gen_html_json_web/views/api/post_view.ex
* creating test/phx_gen_html_json_web/controllers/api/post_controller_test.exs
* creating lib/phx_gen_html_json_web/views/changeset_view.ex
* creating lib/phx_gen_html_json_web/controllers/fallback_controller.ex

Add the resource to your Api :api scope in lib/phx_gen_html_json_web/router.ex:

scope "/api", PhxGenHtmlJsonWeb.Api do
  pipe_through :api
  ...
  resources "/posts", PostController
end

North New Jersey Office

Kinnelon, NJ

Philadelphia Office

Media, PA

office Hours

Mon - Fri : 8am to 6pm

Social Media