sunneach / webcandy (http://onerlang.blogspot.com/)
The Hughes Waroquier's StickyNotes app works under control of the WebMachine 1.0+ (implemented on MochiWeb server). A bit deeper attempt to illustrate and use the key mechanisms and methods of this approach.
Clone this repository (size: 1.3 MB): HTTPS / SSH
$ hg clone http://bitbucket.org/sunneach/webcandy/
| commit 19: | a39e2675f62f |
| parent 18: | 6c40d169bb9d |
| branch: | default |
| tags: | tip |
Added tag 0.2 for changeset 6c40d169bb9d
| r19:a39e2675f62f | 116 loc | 3.1 KB | embed / history / annotate / raw / |
|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | %% @author sunneach http://bitbuckets.com/sunneach
%% @copyright 2009 sunneach
%% @doc Example webmachine_resource.
-module(webmstn_notes_resource).
-export([
init/1,
content_types_provided/2,
allowed_methods/2,
content_types_accepted/2,
process_post/2,
resource_exists/2,
finish_request/2,
delete_resource/2
]).
-export([to_json/2,from_json/2]).
-record(ncontext,{id,data,input}).
-include_lib("webmachine/include/webmachine.hrl").
init([]) -> {ok, #ncontext{}};
init([Cfg]) ->
{trace_dir,Dir} = Cfg,
AbsDir =filename:absname(Dir),
{{trace,AbsDir},#ncontext{}}.
content_types_provided(RD,Ctx) ->
{[{"application/json",to_json}],RD,Ctx}.
to_json(RD, Ctx) ->
{Ctx#ncontext.data, RD, Ctx}.
allowed_methods(RD, Ctx) ->
{case wrq:path_info(note, RD) of
undefined -> ['POST'];
_ -> ['GET', 'HEAD', 'PUT','DELETE']
end,
RD, Ctx}.
content_types_accepted(RD, Ctx) -> % called when 'PUT' comes
{[{"application/x-www-form-urlencoded", from_json}], RD, Ctx}.
% {[{"application/json", from_json}], RD, Ctx}.
%% PUT
%% update record
from_json(RD, Ctx) ->
{_Ans,RD1,Ctx1} = action(update,RD,Ctx),
{true,RD1,Ctx1}.
%% POST
%% Create record
process_post(RD,Ctx) ->
{_Ans,RD1,Ctx1} = action(create,RD,Ctx),
{true,RD1,Ctx1}.
%% DELETE record
delete_resource(RD, Ctx) ->
RD1 = wrq:set_resp_header("Content-Type", "application/json",RD),
Str = Ctx#ncontext.input, % passed from resource_exists
case Ctx#ncontext.id of
all ->
{true, RD1, Ctx};
_ ->
Ans1 = notes:delete(Str),
Ans = mochijson2:encode(Ans1),
{true, RD1, Ctx#ncontext{data=Ans}}
end.
%% DELETE, PUT support
finish_request(RD, Ctx) ->
{Ctx#ncontext.data, RD, Ctx}.
%% POST and PUT
action(Act,RD,Ctx) ->
Data = mochiweb_util:parse_qs(wrq:req_body(RD)),
Struct = mochijson2:decode(proplists:get_value("json", Data)),
%% will crush if action IS NOT Act
Act = list_to_atom(binary_to_list(struct:get_value(<<"action">>, Struct))),
RD1 = wrq:set_resp_header("Content-Type", "application/json",RD),
Ans = mochijson2:encode(notes:Act(Struct)),
RD2 = wrq:append_to_resp_body(Ans,RD1),
{Ans, RD2, Ctx}.
%% GET,HEAD
%% read_all,
resource_exists(RD, Ctx) ->
case wrq:method(RD) of
'POST' ->
{true,RD,[]};
_ ->
case wrq:path_info(note, RD) of
"all" ->
notes(all,RD,Ctx#ncontext{id=all});
Id ->
notes(Id,RD,Ctx#ncontext{id=Id})
end
end.
%% notes access: read_all action
notes(all,RD,Ctx) ->
RD1 = wrq:set_resp_header("Content-Type", "application/json",RD),
Ans = mochijson2:encode(notes:read_all([])),
{true, RD1, Ctx#ncontext{id=all,data=Ans}};
%% notes access: read Id
notes(Id,RD,Ctx) ->
RD1 = wrq:set_resp_header("Content-Type", "application/json",RD),
Str = {struct, [{<<"id">>, list_to_integer(Id)}]},
Ans1 = notes:read(Str),
Ans = mochijson2:encode(Ans1),
{case struct:get_value(<<"id">>,Ans1) of
undefined -> false;
_Doc -> true
end,
RD1,Ctx#ncontext{id=Id,data=Ans,input=Str}}. % Ctx defined at Init
|
