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
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
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-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
/ but the generated code below did not give us the path namespace for
api_post_path. We will need to add
api to the scope in routes.
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
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