Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merge branch 'master' of git://github.com/evanmiller/ChicagoBoss into…

… multiple_listeners
  • Loading branch information...
commit 104efe6d525df9d1789f916c1959a254ec573558 2 parents c47b94d + 39a0092
Grzegorz Stanislawski authored December 15, 2011
12  doc-src/api-controller.html
@@ -180,6 +180,18 @@
180 180
 <p>Return <code>Data</code> to the client as a JSON object while setting additional HTTP <code>Headers</code>.</p>
181 181
 
182 182
 <div class="code spec">
  183
+    {jsonp, Callback<span class="typevar">::string()</span>, Data<span class="typevar">::proplist()</span>}
  184
+</div>
  185
+
  186
+<p>Returns <code>Data</code> as a JSONP method call to the client. Performs appropriate serialization if the values in Data contain a BossRecord or a list of BossRecords.</p>
  187
+
  188
+<div class="code spec">
  189
+    {jsonp, Callback<span class="typevar">::string()</span>, Data<span class="typevar">::proplist()</span>, Headers<span class="typevar">::proplist()</span>}
  190
+</div>
  191
+
  192
+<p>Return <code>Data</code> to the client as a JSONP method call (as above) while setting additional HTTP <code>Headers</code>.</p>
  193
+
  194
+<div class="code spec">
183 195
     not_found
184 196
 </div>
185 197
 
8  doc-src/api-mail-controller.html
@@ -28,7 +28,7 @@
28 28
 <div class="code">
29 29
     {ok, FromAddress, ToAddress, HeaderFields} | <br />
30 30
     {ok, FromAddress, ToAddress, HeaderFields, Variables} | <br />
31  
-    {ok, FromAddress, ToAddress, HeaderFields, Variables, Attachments} | <br />
  31
+    {ok, FromAddress, ToAddress, HeaderFields, Variables, Options} | <br />
32 32
     nevermind
33 33
 </div>
34 34
 <p>If the return value is <code>nevermind</code>, no email will be sent. Otherwise,</p>
@@ -40,7 +40,11 @@
40 40
     However, the header fields for Message-ID: and Date: will be populated automatically if not provided.
41 41
     </p></li>
42 42
     <li><p><code>Variables</code> (if present) will be passed to the associated Django template(s), which will form the body of the message.</p></li>
43  
-    <li><p><code>Attachments</code> (if present) is a list of tuples representing email attachments. Each attachment should consist of: <code>{FileName, MimeType, Contents}</code>. In this case <code>FileName</code> simply refers to how the file will be named in the email (and is not necessarily a file on the local file system). The file's <code>Contents</code> should be an io_list.</p></li>
  43
+    <li><p><code>Options</code> (if present) is a proplist of additional options, possibly containing:
  44
+    <ul>
  45
+        <li><p><code>attachments</code> - a list of tuples representing email attachments. Each attachment should consist of: <code>{FileName, MimeType, Contents}</code>. In this case <code>FileName</code> simply refers to how the file will be named in the email (and is not necessarily a file on the local file system). The file's <code>Contents</code> should be an io_list.</p></li>
  46
+        <li><p><code>template</code> - a string with the name of another template to use for rendering (assuming you don't want the default template, which is just the same as the function name).</p></li>
  47
+    </ul>
44 48
 </ul>
45 49
 <p><strong>Formatting.</strong> If templates ending only in ".txt" are present, the message will be sent in plain-text; if templates ending only in ".html" are present, the message will be sent as HTML; but if both ".txt" and ".html" templates are present, the message will be sent as a a MIME multi-part message with alternative plain-text and HTML representations.</p>
46 50
 <p><strong>I18n.</strong> To use Chicago Boss's i18n machinery in emails, specify the desired language in the "Content-Language" header field returned from the mail controller.</p>
2  src/boss.app.src
... ...
@@ -1,7 +1,7 @@
1 1
 {application, boss,
2 2
     [
3 3
     {description, "Chicago Boss web framework"},
4  
-    {vsn, "0.6.8"},
  4
+    {vsn, "0.6.9"},
5 5
     {registered, [
6 6
         boss_cache, boss_cache_sup,
7 7
         boss_db, boss_db_sup, 
14  src/boss/boss_mail.erl
@@ -15,8 +15,8 @@ send_template(Application, Action, Args) ->
15 15
             send_message(Application, FromAddress, ToAddress, Action, HeaderFields, [], []);
16 16
         {ok, FromAddress, ToAddress, HeaderFields, Variables} -> 
17 17
             send_message(Application, FromAddress, ToAddress, Action, HeaderFields, Variables, []);
18  
-        {ok, FromAddress, ToAddress, HeaderFields, Variables, Attachments} -> 
19  
-            send_message(Application, FromAddress, ToAddress, Action, HeaderFields, Variables, Attachments);
  18
+        {ok, FromAddress, ToAddress, HeaderFields, Variables, Options} -> 
  19
+            send_message(Application, FromAddress, ToAddress, Action, HeaderFields, Variables, Options);
20 20
         nevermind ->
21 21
             ok
22 22
     end.
@@ -31,13 +31,15 @@ send(FromAddress, ToAddress, Subject, Body) ->
31 31
             {"From", FromAddress}], "text/plain"), 
32 32
     gen_server:call(boss_mail, {deliver, FromAddress, ToAddress, fun() -> [MessageHeader, "\r\n", Body] end}).
33 33
 
34  
-send_message(App, FromAddress, ToAddress, Action, HeaderFields, Variables, Attachments) ->
35  
-    BodyFun = fun() -> build_message(App, Action, HeaderFields, Variables, Attachments) end,
  34
+send_message(App, FromAddress, ToAddress, Action, HeaderFields, Variables, Options) ->
  35
+    BodyFun = fun() -> build_message(App, Action, HeaderFields, Variables, Options) end,
36 36
     gen_server:call(boss_mail, {deliver, FromAddress, ToAddress, BodyFun}).
37 37
 
38  
-build_message(App, Action, HeaderFields, Variables, Attachments) ->
  38
+build_message(App, Action, HeaderFields, Variables, Options) ->
39 39
     ContentLanguage = proplists:get_value("Content-Language", HeaderFields),
40  
-    {MimeType, MessageBody} = build_message_body_attachments(App, Action, Variables, Attachments, ContentLanguage),
  40
+    EffectiveAction = proplists:get_value(template, Options, Action),
  41
+    Attachments = proplists:get_value(attachments, Options, []),
  42
+    {MimeType, MessageBody} = build_message_body_attachments(App, EffectiveAction, Variables, Attachments, ContentLanguage),
41 43
     MessageHeader = build_message_header(HeaderFields, MimeType),
42 44
     [MessageHeader, "\r\n", MessageBody].
43 45
 
2  src/boss/boss_record_compiler.erl
@@ -38,7 +38,7 @@ trick_out_forms([H|T], LeadingForms) ->
38 38
     trick_out_forms(T, [H|LeadingForms]).
39 39
 
40 40
 trick_out_forms(LeadingForms, Forms, ModuleName, Parameters) ->
41  
-    Attributes = proplists:get_value(attributes, erl_syntax_lib:analyze_forms(LeadingForms ++ Forms)),
  41
+    Attributes = proplists:get_value(attributes, erl_syntax_lib:analyze_forms(LeadingForms ++ Forms), []),
42 42
     [{eof, _Line}|ReversedOtherForms] = lists:reverse(Forms),
43 43
     UserForms = lists:reverse(ReversedOtherForms),
44 44
     Counters = lists:foldl(
14  src/boss/boss_web_controller.erl
@@ -393,9 +393,9 @@ process_result(_, {not_found, Payload}) ->
393 393
 process_result(AppInfo, {redirect, Where}) ->
394 394
 	process_result(AppInfo, {redirect, Where, []});
395 395
 process_result(AppInfo, {redirect, "http://"++Where, Headers}) ->
396  
-    process_result(AppInfo, {redirect, "/"++string:join(tl(string:tokens(Where, "/")), "/"), Headers});
  396
+    process_result(AppInfo, {redirect_external, "http://"++Where, Headers});
397 397
 process_result(AppInfo, {redirect, "https://"++Where, Headers}) ->
398  
-    process_result(AppInfo, {redirect, "/"++string:join(tl(string:tokens(Where, "/")), "/"), Headers});
  398
+    process_result(AppInfo, {redirect_external, "https://"++Where, Headers});
399 399
 process_result(_AppInfo, {redirect, {Application, Controller, Action, Params}, Headers}) ->
400 400
     RouterPid = boss_web:router_pid(list_to_atom(lists:concat([Application]))),
401 401
     URL = boss_router:unroute(RouterPid, Controller, Action, Params),
@@ -403,6 +403,8 @@ process_result(_AppInfo, {redirect, {Application, Controller, Action, Params}, H
403 403
     {302, [{"Location", BaseURL ++ URL}, {"Cache-Control", "no-cache"}|Headers], ""};
404 404
 process_result(AppInfo, {redirect, Where, Headers}) ->
405 405
     {302, [{"Location", AppInfo#boss_app_info.base_url ++ Where}, {"Cache-Control", "no-cache"}|Headers], ""};
  406
+process_result(_, {redirect_external, Where, Headers}) ->
  407
+    {302, [{"Location", Where}, {"Cache-Control", "no-cache"}|Headers], ""};
406 408
 process_result(_, {ok, Payload, Headers}) ->
407 409
     {200, [{"Content-Type", proplists:get_value("Content-Type", Headers, "text/html")}
408 410
             |proplists:delete("Content-Type", Headers)], Payload}.
@@ -597,6 +599,14 @@ process_action_result(Info, {json, Data, Headers}, AppInfo, AuthInfo) ->
597 599
             [{"Content-Type", proplists:get_value("Content-Type", Headers, "application/json")}
598 600
                 |proplists:delete("Content-Type", Headers)]}, AppInfo, AuthInfo);
599 601
 
  602
+process_action_result(Info, {jsonp, Callback, Data}, AppInfo, AuthInfo) ->
  603
+    process_action_result(Info, {jsonp, Callback, Data, []}, AppInfo, AuthInfo);
  604
+process_action_result(Info, {jsonp, Callback, Data, Headers}, AppInfo, AuthInfo) ->
  605
+    JsonData  = boss_json:encode(Data, AppInfo#boss_app_info.model_modules),
  606
+    process_action_result(Info, {output, Callback ++ "(" ++ JsonData ++ ");",
  607
+            [{"Content-Type", proplists:get_value("Content-Type", Headers, "application/javascript")}
  608
+                |proplists:delete("Content-Type", Headers)]}, AppInfo, AuthInfo);
  609
+
600 610
 process_action_result(Info, {output, Payload}, AppInfo, AuthInfo) ->
601 611
     process_action_result(Info, {output, Payload, []}, AppInfo, AuthInfo);
602 612
 process_action_result(_, {output, Payload, Headers}, _, _) ->
66  src/smart_exceptions/smart_exceptions.erl
@@ -80,7 +80,7 @@
80 80
 %%
81 81
 %% If you want to see what the transform produces, provide the flag '-E'.
82 82
 
83  
-parse_transform(Forms, Opts) ->
  83
+parse_transform(Forms, _Opts) ->
84 84
     %% Opts = compiler options
85 85
     M = get_module_name(Forms),
86 86
     forms(M, Forms).
@@ -99,13 +99,13 @@ forms(M, Forms0) ->
99 99
     Forms = simple_resolve_imports(Forms0),
100 100
     [ form(M, Form) || Form <- Forms ].
101 101
 
102  
-form(M, {function, Line, F, A, _Clss} = Form) ->
  102
+form(M, {function, _Line, F, A, _Clss} = Form) ->
103 103
     mapform0(
104  
-      fun({function, Lf, F1, A1, []}=Form0) ->
  104
+      fun({function, _Lf, _F1, _A1, []}=Form0) ->
105 105
 	      Form0;
106 106
 	 ({function, Lf, F1, A1, Clss}) ->
107 107
 	      smart_function(M, F1, A1, Lf, Clss);
108  
-	 ({match, Lm, P, E}=Expr) ->
  108
+	 ({match, Lm, P, E}=_Expr) ->
109 109
 	      smart_match(M, F, A, Lm, P, E);
110 110
 	 ({'case',Lc,E,Clss}) ->
111 111
 	      smart_case(M, F, A, Lc, E, Clss);
@@ -115,23 +115,23 @@ form(M, {function, Line, F, A, _Clss} = Form) ->
115 115
 	      smart_fun(M, F, A, Lf, Clss);
116 116
 	 ({'fun',Lf,{clauses,Clss}, Info}) ->
117 117
 	      smart_fun(M, F, A, Lf, Clss, Info);
118  
-	 ({op,Lo,Op,E1,E2}=E) ->
  118
+	 ({op,Lo,Op,E1,E2}=_E) ->
119 119
 	      smart_binop(M, F, A, Lo, Op, E1, E2);
120  
-	 ({op,Lo,Op,E1}=E) ->
  120
+	 ({op,Lo,Op,E1}=_E) ->
121 121
 	      smart_unop(M, F, A, Lo, Op, E1);
122  
-	 ({call,Lc,{remote,Lr,{atom,Lm,erlang},{atom,Lf,exit}},[Rsn]}=E) ->
  122
+	 ({call,Lc,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,exit}},[Rsn]}=_E) ->
123 123
 	      smart_exit(M, F, A, Lc, Rsn);
124  
-	 ({call,Lc,{remote,Lr,{atom,Lm,erlang},{atom,Lf,fault}},[Rsn]}=E) ->
  124
+	 ({call,Lc,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,fault}},[Rsn]}=_E) ->
125 125
 	      smart_fault(M, F, A, Lc, Rsn);
126  
-	 ({call,Lc,{remote,Lr,{atom,Lm,erlang},{atom,Lf,error}},[Rsn]}=E) ->
  126
+	 ({call,Lc,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,error}},[Rsn]}=_E) ->
127 127
 	      smart_error(M, F, A, Lc, Rsn);
128  
-	 ({call,Lc,{remote,Lr,{atom,Lm,erlang},{atom,Lf,throw}},[Rsn]}=E) ->
  128
+	 ({call,_Lc,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,throw}},[_Rsn]}=E) ->
129 129
 	      E;
130  
-	 ({call,Lc,{atom,Lf,exit},[Rsn]}=E) ->
  130
+	 ({call,Lc,{atom,_Lf,exit},[Rsn]}=_E) ->
131 131
 	      smart_exit(M, F, A, Lc, Rsn);
132  
-	 ({call,Lc,{atom,Lf,throw},[Rsn]}=E) ->
  132
+	 ({call,_Lc,{atom,_Lf,throw},[_Rsn]}=E) ->
133 133
 	      E;
134  
-	 ({call,Lc,{remote,Lr,{atom,Lm,Mod},{atom,Lf,Fn}},As}=E) ->
  134
+	 ({call,Lc,{remote,_Lr,{atom,_Lm,Mod},{atom,_Lf,Fn}},As}=E) ->
135 135
 	      case erlang:is_builtin(Mod, Fn, length(As)) of
136 136
 		  true ->
137 137
 		      smart_bif(M, F, A, Lc, 
@@ -139,14 +139,14 @@ form(M, {function, Line, F, A, _Clss} = Form) ->
139 139
 		  false ->
140 140
 		      E
141 141
 	      end;
142  
-	 ({bin, Lb, BinElts}=E) ->
  142
+	 ({bin, Lb, _BinElts}=E) ->
143 143
 	      smart_bin(M, F, A, Lb, E);
144 144
 	 (E) ->
145 145
 	      E
146 146
       end,
147 147
       Form
148 148
      );
149  
-form(M, Form) ->
  149
+form(_M, Form) ->
150 150
     Form.
151 151
 
152 152
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -162,9 +162,9 @@ simple_resolve_imports(Forms) ->
162 162
     Imps_and_funcs = func_defs(Forms),
163 163
     resolve_calls(Forms, Imps_and_funcs).
164 164
 
165  
-func_defs([{attribute, La, import, {M, FAs}}|Forms]) ->
  165
+func_defs([{attribute, _La, import, {M, FAs}}|Forms]) ->
166 166
     [ {{F,A}, {import, M}} || {F,A} <- FAs ] ++ func_defs(Forms);
167  
-func_defs([{function,Lf, F, A, Clss}|Forms]) ->
  167
+func_defs([{function,_Lf, F, A, _Clss}|Forms]) ->
168 168
     [ {{F,A}, local} | func_defs(Forms) ];
169 169
 func_defs([_|Forms]) ->
170 170
     func_defs(Forms);
@@ -179,15 +179,15 @@ resolve_calls(Forms, FuncDefs) ->
179 179
 %% erlang:f(...). This is deliberate, since Erlang itself behaves that way.
180 180
 %% (Doing so also makes a mockery of scoping.)
181 181
 
182  
-resolve_form({function, _Lf, Fn, Ar, _Clss} = Form, FuncDefs) ->
  182
+resolve_form({function, Lf, _Fn, _Ar, _Clss} = Form, FuncDefs) ->
183 183
     mapform0(
184  
-      fun({call, Lc, {atom, Lf, F}, As}=Expr) ->
  184
+      fun({call, Lc, {atom, _Lf, F}, As}=Expr) ->
185 185
 	      FA = {F, A = length(As)},
186 186
 	      case erlang:is_builtin(erlang,F,A) of
187 187
 		  true ->
188 188
 		      %% if ALSO defined locally, should warn
189 189
 		      %% ?msg("Looking up ~p -> bif\n", [FA]),
190  
-		      Lm = Lc,
  190
+		      _Lm = Lc,
191 191
 		      mk_remote_call(erlang, F, As);
192 192
 		  false ->
193 193
 		      case lists:keysearch(FA, 1, FuncDefs) of
@@ -207,7 +207,7 @@ resolve_form({function, _Lf, Fn, Ar, _Clss} = Form, FuncDefs) ->
207 207
       end,
208 208
       Form
209 209
      );
210  
-resolve_form(Form, FuncDefs) ->
  210
+resolve_form(Form, _FuncDefs) ->
211 211
     Form.
212 212
 
213 213
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -472,7 +472,7 @@ exn_tuple(Concs, Abs) ->
472 472
 %%   * something similar was optionally done in version 1.0 for BIFs
473 473
 %%   * left for "future work"
474 474
 
475  
-smart_bin(M, F, A, Line, {bin, _Lb, BinElts}=Expr) ->
  475
+smart_bin(M, F, A, Line, {bin, _Lb, _BinElts}=Expr) ->
476 476
     Rsn = new_var(),
477 477
     Exn_rsn = bin_error(Expr, Rsn),
478 478
     Exn_term = exn_term({M, F, A}, {line, Line}, Exn_rsn),
@@ -482,7 +482,7 @@ smart_bin(M, F, A, Line, {bin, _Lb, BinElts}=Expr) ->
482 482
 	   []).
483 483
 
484 484
 
485  
-bin_error({bin, Lb, BinElts}=Expr, AbsRsn) ->
  485
+bin_error({bin, _Lb, BinElts}=_Expr, AbsRsn) ->
486 486
     %% io:format("%% decorating ~w\n", [Expr]),
487 487
     {tuple, -1,
488 488
      lists:flatten(
@@ -495,11 +495,11 @@ bin_error({bin, Lb, BinElts}=Expr, AbsRsn) ->
495 495
 %% so we basically emit them at will and hope they are reasonably
496 496
 %% legible. [Improve as needed.]
497 497
 
498  
-bin_indicator({var, Lx, X}=Var, Line, Width, Type) when X =/= '_' ->
  498
+bin_indicator({var, _Lx, X}=Var, _Line, Width, Type) when X =/= '_' ->
499 499
     exn_tuple([X, bin_type_summary(Width, Type)], Var);
500 500
 bin_indicator({integer, _Lc, _C}, _Line, _Type, _Width) ->
501 501
     [];
502  
-bin_indicator(P, Line, Type, Width) ->
  502
+bin_indicator(_P, _Line, _Type, _Width) ->
503 503
     % io:format("%% bin_indicator: skipped unknown pattern" " ~w on line ~w\n", [P, Line]),
504 504
     [].
505 505
 
@@ -514,7 +514,7 @@ bin_indicator(P, Line, Type, Width) ->
514 514
 
515 515
 bin_type_summary(default, [binary]) ->
516 516
     binary;
517  
-bin_type_summary({integer, Line, Width}, [binary]) ->
  517
+bin_type_summary({integer, _Line, Width}, [binary]) ->
518 518
     {binary, Width};
519 519
 bin_type_summary({integer, _Line, Width}, default) ->
520 520
     {default_bin_type(), Width};
@@ -559,7 +559,7 @@ resolve_default_width(TypeWidth) ->
559 559
 
560 560
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561 561
 
562  
-clauses_arity([{clause, _, H, G, B}|_]) ->
  562
+clauses_arity([{clause, _, H, _G, _B}|_]) ->
563 563
     length(H).
564 564
 
565 565
 %%
@@ -600,7 +600,7 @@ counter(Name) ->
600 600
 %%   - introducing this may need some rewriting of sites where module name
601 601
 %%     is used, because of the use of vars vs. abstraction of ground terms
602 602
 
603  
-get_module_name([{attribute,Lm,module,Mod}|Xs]) ->
  603
+get_module_name([{attribute,_Lm,module,Mod}|_Xs]) ->
604 604
     Mod;
605 605
 %get_module_name([{attribute,Lm,module,Mod}|Xs]) ->
606 606
 %    case Mod of
@@ -614,9 +614,9 @@ get_module_name([_|Xs]) ->
614 614
 
615 615
 %%
616 616
 
617  
-function_name({function, Lf, F, A, Clss}) ->
  617
+function_name({function, _Lf, F, A, _Clss}) ->
618 618
     {F, A};
619  
-function_name(Other) ->
  619
+function_name(_Other) ->
620 620
     {not_a_function, no_name}.
621 621
 
622 622
 %%
@@ -651,7 +651,7 @@ mapform0(F, T) when is_tuple(T) ->
651 651
     F(list_to_tuple([ mapform0(F, Tsub) || Tsub <- tuple_to_list(T) ]));
652 652
 mapform0(F, Xs) when is_list(Xs) ->
653 653
     [ mapform0(F, X) || X <- Xs ];
654  
-mapform0(F, C) when is_atom(C) ; is_number(C) ->
  654
+mapform0(_F, C) when is_atom(C) ; is_number(C) ->
655 655
     C.
656 656
 
657 657
 %% detect + elide pattern in qualifier
@@ -680,7 +680,7 @@ vars_of(AbsTerm) ->
680 680
 
681 681
 vars_of({var, _, '_'}, Vs) ->
682 682
     Vs;
683  
-vars_of({var, _, X}=V, Vs) ->
  683
+vars_of({var, _, _X}=V, Vs) ->
684 684
     [V|Vs];
685 685
 vars_of(T, Vs0) when is_tuple(T) ->
686 686
     lists:foldl(
@@ -693,7 +693,7 @@ vars_of([X|Xs], Vs) ->
693 693
     vars_of(Xs, vars_of(X, Vs));
694 694
 vars_of([], Vs) ->
695 695
     Vs;
696  
-vars_of(X, Vs) ->
  696
+vars_of(_X, Vs) ->
697 697
     %% cannot be a variable or contain a variable
698 698
     Vs.
699 699
 

0 notes on commit 104efe6

Please sign in to comment.
Something went wrong with that request. Please try again.