Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Revamped tutorial

  • Loading branch information...
commit ab8711e04cac65d8ea9f7b422cf4916d577fd481 1 parent 05e166b
Evan Miller authored
View
2  README
@@ -1 +1 @@
-This is the example application created in Chicago Boss: A Rough Introduction
+This is the example application built in Chicago Boss: A Rough Introduction
View
BIN  TUTORIAL.pdf
Binary file not shown
View
0  log/.gitignore
No changes.
View
11 priv/init/cb_tutorial_news.erl
@@ -6,16 +6,7 @@
% return a list of WatchIDs that should be cancelled if the
% script is ever reloaded (for example, via the admin application).
init() ->
- {ok, WatchId} = boss_news:watch("messages",
- fun(created, NewMessage) ->
- error_logger:info_msg("New message! ~p~n",
- [NewMessage:message_contents()]),
- boss_mq:push("new-messages", NewMessage);
- (deleted, OldMessage) ->
- error_logger:info_msg("Message go poof! ~p~n",
- [OldMessage:message_contents()])
- end),
- {ok, [WatchId]}.
+ {ok, []}.
%%%%%%%%%%% Ideas
% boss_news:watch("user-42.*",
View
71 src/controller/cb_tutorial_account_controller.erl
@@ -1,71 +0,0 @@
--module(cb_tutorial_account_controller, [Req, SessionID]).
--compile(export_all).
-
-login('GET', []) ->
- {ok, [{redirect, Req:header(referer)}]};
-login('POST', []) ->
- Email = Req:post_param("email"),
- Password = Req:post_param("password"),
- Redirect = Req:post_param("redirect"),
- Result = case boss_db:find(account, [email = Email]) of
- [Account] ->
- case Account:check_password(Password) of
- true ->
- boss_session:set_session_data(SessionID,
- "account",
- Account:id()),
- true;
- false -> false
- end;
- _ -> false
- end,
- case Result of
- true -> {redirect, Req:post_param("redirect")};
- false ->
- {ok, [{redirect, Redirect}, {email, Email},
- {errors, ["Invalid email/password combination"]}]}
- end.
-
-logout('GET', []) ->
- boss_session:remove_session_data(SessionID, "account"),
- {redirect, "/"}.
-
-create('GET', []) ->
- ok;
-create('POST', []) ->
- Email = Req:post_param("email"),
- Password1 = Req:post_param("password1"),
- Password2 = Req:post_param("password2"),
- ValidationTests = [{length(Password1) >= 6,
- "Password must be at least 6 characters!"},
- {Password1 =:= Password2,
- "Passwords didn't match!"},
- {boss_db:count(account, [email = Email]) =:= 0,
- "An account with that email exists"}],
- ValidationFailures = lists:foldr(fun
- ({true, _}, Acc) -> Acc;
- ({false, Message}, Acc) -> [Message|Acc]
- end, [], ValidationTests),
- Account = boss_record:new(account, [{email, Email}]),
- ErrorList = case ValidationFailures of
- [] ->
- PasswordHash = Account:hash_for_password(Password1),
- Account1 = Account:set(password_hash, PasswordHash),
- case Account1:save() of
- {ok, SavedAccount} ->
- boss_session:set_session_data(SessionID,
- "account", SavedAccount:id()),
- [];
- {error, List} -> List
- end;
- _ -> ValidationFailures
- end,
- case ErrorList of
- [] -> {redirect, [{controller, "message"},
- {action, "hello"}]};
- _ -> {ok, [{errors, ErrorList}, {account, Account}]}
- end.
-
-view('GET', [Id]) ->
- Account = boss_db:find(Id),
- {ok, [{account, Account}]}.
View
38 src/controller/cb_tutorial_greeting_controller.erl
@@ -0,0 +1,38 @@
+-module(cb_tutorial_greeting_controller, [Req]).
+-compile(export_all).
+
+before_(_) ->
+ {ok, Req:peer_ip() =:= {127, 0, 0, 1}}.
+
+hello('GET', []) ->
+ {ok, [{greeting, "Hello, world!"}]}.
+
+list('GET', [], IsMe) ->
+ Greetings = boss_db:find(greeting, []),
+ {ok, [{greetings, Greetings}, {is_me, IsMe}]}.
+
+create('GET', []) ->
+ ok;
+create('POST', []) ->
+ GreetingText = Req:post_param("greeting_text"),
+ NewGreeting = greeting:new(id, GreetingText),
+ case NewGreeting:save() of
+ {ok, SavedGreeting} ->
+ {redirect, [{action, "list"}]};
+ {error, ErrorList} ->
+ {ok, [{errors, ErrorList}, {new_msg, NewGreeting}]}
+ end.
+
+goodbye('POST', [], true) ->
+ boss_db:delete(Req:post_param("greeting_id")),
+ {redirect, [{action, "list"}]}.
+
+pull('GET', [LastTimestamp]) ->
+ {ok, Timestamp, Greetings} = boss_mq:pull("new-greetings",
+ list_to_integer(LastTimestamp)),
+ {json, [{timestamp, Timestamp}, {greetings, Greetings}]}.
+
+live('GET', []) ->
+ Greetings = boss_db:find(greeting, []),
+ Timestamp = boss_mq:now("new-greetings"),
+ {ok, [{greetings, Greetings}, {timestamp, Timestamp}]}.
View
39 src/controller/cb_tutorial_message_controller.erl
@@ -1,39 +0,0 @@
--module(cb_tutorial_message_controller, [Req, SessionID]).
--compile(export_all).
-
-before_(_) ->
- case boss_session:get_session_data(SessionID, "account") of
- undefined ->
- {redirect, [{controller, "account"},
- {action, "login"}]};
- AccountID ->
- {ok, Req:peer_ip() =:= {127, 0, 0, 1}}
- end.
-
-hello('GET', [], IsLocal) ->
- Messages = boss_db:find(message, []),
- {ok, [{messages, Messages}, {is_local, IsLocal}]};
-hello('POST', [], IsLocal) ->
- MessageContents = Req:post_param("message_contents"),
- AccountID = boss_session:get_session_data(SessionID, "account"),
- NewMessage = message:new(id, MessageContents, AccountID),
- case NewMessage:save() of
- {ok, SavedMessage} ->
- {redirect, [{action, "hello"}]};
- {error, ErrorList} ->
- {ok, [{errors, ErrorList}, {new_msg, NewMessage}]}
- end.
-
-goodbye('POST', [], true) ->
- boss_db:delete(Req:post_param("message_id")),
- {redirect, [{action, "hello"}]}.
-
-pull('GET', [LastTimestamp]) ->
- {ok, Timestamp, Messages} = boss_mq:pull("new-messages",
- list_to_integer(LastTimestamp)),
- {json, [{timestamp, Timestamp}, {messages, Messages}]}.
-
-live('GET', []) ->
- Messages = boss_db:find(message, []),
- Timestamp = boss_mq:now("new-messages"),
- {ok, [{messages, Messages}, {timestamp, Timestamp}]}.
View
14 src/model/account.erl
@@ -1,14 +0,0 @@
--module(account, [Id, Email, PasswordHash]).
--compile(export_all).
--has({messages, many}).
-
-hash_for_password(Password) ->
- PasswordSalt = mochihex:to_hex(erlang:md5(Email)),
- mochihex:to_hex(erlang:md5(PasswordSalt ++ Password)).
-
-check_password(Password) ->
- hash_for_password(Password) =:= PasswordHash.
-
-validation_tests() ->
- [{fun() -> string:chr(Email, $@) > 0 end,
- "Email must contain an @ symbol!"}].
View
14 src/model/greeting.erl
@@ -0,0 +1,14 @@
+-module(greeting, [Id, GreetingText]).
+-compile(export_all).
+
+validation_tests() ->
+ [{fun() -> length(GreetingText) > 0 end,
+ "Greeting must be non-empty!"},
+ {fun() -> length(GreetingText) =< 140 end,
+ "Greeting must be tweetable"}].
+
+before_create() ->
+ NewRecord = set(greeting_text,
+ re:replace(GreetingText, "masticate", "chew",
+ [{return, list}])),
+ {ok, NewRecord}.
View
9 src/model/message.erl
@@ -1,9 +0,0 @@
--module(message, [Id, MessageContents, AccountId]).
--compile(export_all).
--belongs_to(account).
-
-validation_tests() ->
- [{fun() -> length(MessageContents) > 0 end,
- "Message must be non-empty!"},
- {fun() -> length(MessageContents) =< 140 end,
- "Message must be 140 characters or fewer!"}].
View
10 src/view/account/create.html
@@ -1,10 +0,0 @@
-{% list_errors errors=errors %}
-
-<form method="post">
-Email address: <input name="email"
- value="{% if account %}{{ account.email }}{% endif %}"><br>
-Password once: <input name="password1" type="password"><br>
-Password again: <input name="password2" type="password"><br>
-<input type="hidden" name="redirect" value="{{ redirect }}">
-<input type="submit">
-</form>
View
8 src/view/account/login.html
@@ -1,8 +0,0 @@
-{% list_errors errors=errors %}
-
-<form method="post">
-Email address: <input name="email"
- value="{% if email %}{{ email }}{% endif %}"><br>
-Password: <input name="password" type="password"><br><input type="submit">
-</form>
-<a href="{% url action="create" %}">Create an account</a>
View
7 src/view/account/view.html
@@ -1,7 +0,0 @@
-<h1>{{ account.email }}</h1>
-All messages:
-<ul>
- {% for msg in account.messages %}
- <li>{{ msg.message_contents }}
- {% endfor %}
-</ul>
View
13 src/view/greeting/create.html
@@ -0,0 +1,13 @@
+{% if errors %}
+<ul>
+ {% for error in errors %}
+ <li><font color=red>{{ error }}</font>
+ {% endfor %}
+</ul>
+{% endif %}
+<form method="post">
+Enter a new greeting:
+<textarea name="greeting_text">{% if new_msg %}{{ new_msg.greeting_text }}{% endif %}</textarea>
+<input type="submit">
+</form>
+
View
1  src/view/greeting/hello.html
@@ -0,0 +1 @@
+<b>{{ greeting }}</b>
View
23 src/view/greeting/list.html
@@ -0,0 +1,23 @@
+<ul>
+{% if greetings %}
+{% for greeting in greetings %}
+<li>{{ greeting.greeting_text }}
+{% endfor %}
+{% else %}
+<li>No greetings!
+{% endif %}
+</ul>
+
+<p><a href="{% url action="create" %}">Create a new greeting...</a></p>
+
+{% if is_me %}
+<form method="post" action="{% url action="goodbye" %}">
+ Delete:
+<select name="greeting_id">
+{% for greeting in greetings %}
+<option value="{{ greeting.id }}">{{ greeting.greeting_text }}
+{% endfor %}
+</select>
+<input type="submit">
+</form>
+{% endif %}
View
17 src/view/message/live.html → src/view/greeting/live.html
@@ -2,11 +2,11 @@
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<script>
function listen_for_events(timestamp) {
- $.ajax("/message/pull/"+timestamp, { success:
+ $.ajax("/greeting/pull/"+timestamp, { success:
function(data, code, xhr) {
- for (var i=0; i<data.messages.length; i++) {
- var msg = data.messages[i].message_contents;
- $("#msg_list").append("<li>"+msg);
+ for (var i=0; i<data.greetings.length; i++) {
+ var msg = data.greetings[i].greeting_text;
+ $("#greeting_list").append("<li>"+msg);
}
listen_for_events(data.timestamp);
} });
@@ -17,12 +17,11 @@
</script>
</head>
<body>
- Live messages:
- <ul id="msg_list">
- {% for msg in messages %}
- <li>{{ msg.message_contents }}
+ <ul id="greeting_list">
+ {% for greeting in greetings %}
+ <li>{{ greeting.greeting_text }}
{% empty %}
- <li>No messages!
+ <li>No greetings!
{% endfor %}
</ul>
</body>
View
7 src/view/lib/list_errors.html
@@ -1,7 +0,0 @@
-{% if errors %}
-<ul>
- {% for error in errors %}
- <li><font color=red>{{ error }}</font>
- {% endfor %}
-</ul>
-{% endif %}
View
34 src/view/message/hello.html
@@ -1,34 +0,0 @@
-{% if errors %}
-{% list_errors errors=errors %}
-{% else %}
-<ul>
- {% if messages %}
- {% for msg in messages %}
- <li>{{ msg.message_contents }}
- {% if msg.account %}--<a href="{% url controller="account" action="view" id=msg.account.id %}">{{ msg.account.email }}</a>{% endif %}
- {% endfor %}
- {% else %}
- <li>No messages!
- {% endif %}
-</ul>
-{% endif %}
-
-<form method="post">
- Enter a new message:
-<textarea name="message_contents">
-{% if new_msg %}{{ new_msg.message_contents }}{% endif %}
-</textarea>
- <input type="submit">
-</form>
-
-{% if is_local %}
-<form method="post" action="{% url action="goodbye" %}">
- Delete:
- <select name="message_id">
- {% for msg in messages %}
- <option value="{{ msg.id }}">{{ msg.message_contents }}
- {% endfor %}
- </select>
- <input type="submit">
-</form>
-{% endif %}
Please sign in to comment.
Something went wrong with that request. Please try again.