From 684f1eb8f4b7d2bd11d1562e62e9755174a217bb Mon Sep 17 00:00:00 2001 From: alisinabh Date: Sat, 24 Jun 2017 07:11:05 +0430 Subject: [PATCH] Fixes supporiting in url params --- README.md | 4 +- lib/newapi/newapi.ex | 80 ++++++++++++++++++++++++++++++++++++++++ lib/prex.ex | 11 +++++- lib/prex/name_helpers.ex | 2 +- lib/prex/templates.ex | 73 ++++++++++++++++++++++++++++++++++-- mix.lock | 6 +-- newtest.apib | 59 +++++++++++++++++++++++++++++ 7 files changed, 223 insertions(+), 12 deletions(-) create mode 100644 lib/newapi/newapi.ex create mode 100644 newtest.apib diff --git a/README.md b/README.md index 9e390d6..75b975c 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ defmodule MyApi.User do """ def list_all_users(since \\ nil, limit \\ nil) do req_url = Path.join @base_url, "/users(?since,limit)" - HTTPoison.request(:get, req_url, body: Poison.encode!(%{ "since" => since, "limit" => limit}), headers: ["Content-Type": "application/json"]) + HTTPotion.request(:get, req_url, body: Poison.encode!(%{ "since" => since, "limit" => limit}), headers: ["Content-Type": "application/json"]) end def list_all_users!(since \\ nil, limit \\ nil) do @@ -78,7 +78,7 @@ defmodule MyApi.User do """ def create_a_user do req_url = Path.join @base_url, "/users(?since,limit)" - HTTPoison.request(:put, req_url) + HTTPotion.request(:put, req_url) end def create_a_user! do diff --git a/lib/newapi/newapi.ex b/lib/newapi/newapi.ex new file mode 100644 index 0000000..815e0d7 --- /dev/null +++ b/lib/newapi/newapi.ex @@ -0,0 +1,80 @@ +# Created by Prex +defmodule Newapi do + @moduledoc """ + + """ + + @base_url "" + + ### + # API Calls + ### + + # Tasks + + @doc """ + + + ## Parameters + - status: + - priority: + - number: + """ + def list_all_tasks(status, priority, number) do + req_url = Path.join @base_url, "/tasks/tasks?priority=#{priority |> URI.encode_www_form}" <> + (if number != nil, do: "number=#{number |> URI.encode_www_form}", else: "") <> "&" <> + (if status != nil, do: "status=#{status |> URI.encode_www_form}", else: "") + + HTTPotion.request(:get, req_url, body: Poison.encode!(%{"status" => status, "priority" => priority, "number" => number}), headers: ["Content-Type": "application/json"]) + end + + def list_all_tasks!(status, priority, number) do + {:ok, result} = list_all_tasks(status, priority, number) + result + end + + @doc """ + This is a state transition to another resource. + + ## Parameters + - status: + - priority: + - number: + - id: + """ + def retrieve_task(status, priority, number, id) do + req_url = Path.join @base_url, "/tasks/tasks?priority=#{priority |> URI.encode_www_form}" <> + (if number != nil, do: "number=#{number |> URI.encode_www_form}", else: "") <> "&" <> + (if status != nil, do: "status=#{status |> URI.encode_www_form}", else: "") + + HTTPotion.request(:get, req_url, body: Poison.encode!(%{"status" => status, "priority" => priority, "number" => number, "id" => id}), headers: ["Content-Type": "application/json"]) + end + + def retrieve_task!(status, priority, number, id) do + {:ok, result} = retrieve_task(status, priority, number, id) + result + end + + @doc """ + + + ## Parameters + - status: + - priority: + - number: + - id: + """ + def delete_task(status, priority, number, id) do + req_url = Path.join @base_url, "/tasks/tasks?priority=#{priority |> URI.encode_www_form}" <> + (if number != nil, do: "number=#{number |> URI.encode_www_form}", else: "") <> "&" <> + (if status != nil, do: "status=#{status |> URI.encode_www_form}", else: "") + + HTTPotion.request(:delete, req_url, body: Poison.encode!(%{"status" => status, "priority" => priority, "number" => number, "id" => id}), headers: ["Content-Type": "application/json"]) + end + + def delete_task!(status, priority, number, id) do + {:ok, result} = delete_task(status, priority, number, id) + result + end + +end diff --git a/lib/prex.ex b/lib/prex.ex index b64083f..03e7d51 100644 --- a/lib/prex.ex +++ b/lib/prex.ex @@ -13,8 +13,15 @@ defmodule Prex do %{"name" => group_name, "description" => group_description, "resources" => resources} = group actions_code = do_generate_module(resources, "") + file_name = cond do + group_name == nil or group_name == "" -> + api_name + true -> + group_name + end + {:ok, - "lib/#{normalize_var_name(api_name)}/#{normalize_var_name(group_name)}.ex", # TODO fix folders + "lib/#{normalize_var_name(api_name)}/#{normalize_var_name(file_name)}.ex", Prex.Templates.get_module(api_name, group_name, base_url, group_description, actions_code)} end @@ -34,5 +41,5 @@ defmodule Prex do end defp get_actions(_uri, _global_params, [], acc), do: acc - + end diff --git a/lib/prex/name_helpers.ex b/lib/prex/name_helpers.ex index e3a06a0..d516bc6 100644 --- a/lib/prex/name_helpers.ex +++ b/lib/prex/name_helpers.ex @@ -29,7 +29,7 @@ defmodule Prex.NameHelpers do end @doc """ - Converts an http method name to equivalant atom for HTTPoison to use + Converts an http method name to equivalant atom for HTTPotion to use ## Examples iex> Prex.NameHelpers.normalize_http_method "GET" diff --git a/lib/prex/templates.ex b/lib/prex/templates.ex index 095beb3..f396b77 100644 --- a/lib/prex/templates.ex +++ b/lib/prex/templates.ex @@ -5,6 +5,8 @@ defmodule Prex.Templates do import Prex.NameHelpers + @url_regex ~r/{([A-Za-z0-9\\?,]+)}/ + @doc """ Creates an elixir module code for an API group @@ -17,7 +19,13 @@ defmodule Prex.Templates do """ @spec get_module(String.t, String.t, String.t, String.t, Enum.t) :: String.t def get_module(api_name, group_name, base_url, docs, actions) do - module_name = normalize_module_name(api_name) <> "." <> normalize_module_name(group_name) + module_name = cond do + group_name == nil or group_name == "" -> + IO.puts "warning: there is an unnamed resource group. using base module name..." + normalize_module_name(api_name) + true -> + normalize_module_name(api_name) <> "." <> normalize_module_name(group_name) + end """ # Created by Prex defmodule #{module_name} do @@ -45,7 +53,7 @@ defmodule Prex.Templates do \"\"\" def #{action_name} do req_url = Path.join @base_url, \"#{url}\" - HTTPoison.request(#{req_method}, req_url) + HTTPotion.request(#{req_method}, req_url) end def #{action_name}! do @@ -71,6 +79,16 @@ defmodule Prex.Templates do action_name = normalize_func_name(name) req_method = normalize_http_method method {:ok, action_params, recall_params, body, param_docs} = get_action_params(params, "", "", "", "") + {:ok, striped_url, opt_params} = process_url url + extra_url = + case opt_params do + nil -> + "" + "" -> + "" + opts -> + " <>\n #{Enum.join(opts, " <> \"&\" <> \n ")}" + end """ @doc \"\"\" #{docs} @@ -79,8 +97,9 @@ defmodule Prex.Templates do #{param_docs} \"\"\" def #{action_name}(#{action_params}) do - req_url = Path.join @base_url, \"#{url}\" - HTTPoison.request(#{req_method}, req_url, body: Poison.encode!(%{#{body}}), headers: ["Content-Type": "application/json"]) + req_url = Path.join @base_url, \"#{striped_url}\"#{extra_url} + + HTTPotion.request(#{req_method}, req_url, body: Poison.encode!(%{#{body}}), headers: ["Content-Type": "application/json"]) end def #{action_name}!(#{action_params}) do @@ -102,6 +121,8 @@ defmodule Prex.Templates do case {required, default} do {true, nil} -> new_param_acc + {true, ""} -> + new_param_acc {true, default_val} -> new_param_acc <> " \\\\ \"#{default_val}\"" {false, nil} -> @@ -112,6 +133,8 @@ defmodule Prex.Templates do new_param_acc <> " \\\\ \"#{default_val}\"" end + IO.puts inspect {required, default} + new_param_acc = new_param_acc <> "," new_recall_acc = recall_acc <> var_name <> "," @@ -131,4 +154,46 @@ defmodule Prex.Templates do {:ok, param, recall, body, doc} end + defp process_url(url) do + case Regex.run @url_regex, url do + [_, url_params] -> + params = String.split url_params, "," + flat_url = Regex.replace(@url_regex, url, "") + {:ok, req_params, opt_params} = + do_process_url(params, [], []) + + IO.puts inspect opt_params + + case req_params do + [] -> + {:ok, flat_url, opt_params} + [_a | _b] -> + IO.puts inspect req_params + query = Enum.join(req_params, "&") + {:ok, "#{flat_url}?#{query}", opt_params} + end + _ -> + {:ok, url, []} + end + + end + + + defp do_process_url([], params, optional_params), do: {:ok, params, optional_params} + defp do_process_url([param | tail], params, optional_params) do + if String.starts_with?(param, "?") do + name = String.slice(param, 1, String.length(param)-1) + do_process_url(tail, + params, + ["(if #{name} != nil, do: \"#{urlify_param(name)}\", else: \"\")" | optional_params]) + else + do_process_url(tail, + # url <> "#{param}=\#{#{param}}&", + [urlify_param(param) | params], + optional_params) + end + end + + defp urlify_param(param), do: "#{param}=\#{#{param} |> URI.encode_www_form}" + end diff --git a/mix.lock b/mix.lock index 1c8064c..afb0a53 100644 --- a/mix.lock +++ b/mix.lock @@ -1,3 +1,3 @@ -%{"earmark": {:hex, :earmark, "1.2.2", "f718159d6b65068e8daeef709ccddae5f7fdc770707d82e7d126f584cd925b74", [:mix], []}, - "ex_doc": {:hex, :ex_doc, "0.16.1", "b4b8a23602b4ce0e9a5a960a81260d1f7b29635b9652c67e95b0c2f7ccee5e81", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, optional: false]}]}, - "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []}} +%{"earmark": {:hex, :earmark, "1.2.2", "f718159d6b65068e8daeef709ccddae5f7fdc770707d82e7d126f584cd925b74", [:mix], [], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.16.1", "b4b8a23602b4ce0e9a5a960a81260d1f7b29635b9652c67e95b0c2f7ccee5e81", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, + "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}} diff --git a/newtest.apib b/newtest.apib new file mode 100644 index 0000000..cbfceb2 --- /dev/null +++ b/newtest.apib @@ -0,0 +1,59 @@ + +FORMAT: 1A + +# Advanced Action API +A resource action is – in fact – a state transition. This API example +demonstrates an action - state transition - to another resource. + +## API Blueprint ++ [Previous: Resource Model](11.%20Resource%20Model.md) ++ [This: Raw API Blueprint](https://raw.github.com/apiaryio/api-blueprint/master/examples/12.%20Advanced%20Action.md) ++ [Next: Named Endpoints](13.%20Named%20Endpoints.md) + +# Tasks [/tasks/tasks{?status,priority,?number}] + ++ Parameters + + status (string) + + priority (number) + + number (number) + +## List All Tasks [GET] + ++ Response 200 (application/json) + + [ + { + "id": 123, + "name": "Exercise in gym", + "done": false, + "type": "task" + }, + { + "id": 124, + "name": "Shop for groceries", + "done": true, + "type": "task" + } + ] + +## Retrieve Task [GET /task/{id}] +This is a state transition to another resource. + ++ Parameters + + id (string) + ++ Response 200 (application/json) + + { + "id": 123, + "name": "Go to gym", + "done": false, + "type": "task" + } + +## Delete Task [DELETE /task/{id}] + ++ Parameters + + id (string) + ++ Response 204