Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

start/stop for app, init/terminate for connection

  • Loading branch information...
commit e0c6e907953f565b0767e43eccad71870dbbe33a 1 parent d44c938
Evan Miller authored
View
30 README.md
@@ -74,6 +74,9 @@ Then compile it like:
...and you're ready to go.
+Associations
+------------
+
BossDB supports database associations. Suppose you want to model the dog breed
(golden retriever, poodle, etc). You would create a model file with a special
"-has" attribute, like:
@@ -99,7 +102,10 @@ Similarly, you could iterate over all the puppies of a particular breed:
io:format("Puppy: ~p~n", [Puppy:name()])
end, Breed:puppies())
-You can achieve the same thing with a database query, for example:
+Querying
+--------
+
+You can search the database with the boss_db:find functions. Example:
Puppies = boss_db:find(puppy, [{breed_id, 'equals', "breed-47"}])
@@ -108,7 +114,11 @@ you'll be able to write the more simple expression:
Puppies = boss_db:find(puppy, [breed_id = "breed-47"])
-BossDB supports many query operators; see the API references at the top.
+BossDB supports many query operators, as well as sorting, offsets, and limits;
+see the API references at the top.
+
+Validating and saving
+---------------------
To create and save a new record, you would write:
@@ -129,6 +139,22 @@ to your model file, e.g.
If validation fails, the save/0 function will return a list of error messages
instead of the saved record.
+You can also provide spec strings in the parameter declaration if you want to
+validate the attribute types before saving, e.g.
+
+ -module(puppy, [Id, Name::string(), BirthDate::datetime()]).
+
+Accepted types are:
+
+* string()
+* binary()
+* datetime()
+* timestamp() [e.g. returned by erlang:now()]
+* integer()
+* float()
+
+If the type validation fails, then validation_tests/0 will not be called.
+
Events
------
View
2  src/boss_cache.erl
@@ -11,7 +11,7 @@ start() ->
start(Options) ->
Adapter = proplists:get_value(adapter, Options, boss_cache_adapter_memcached_bin),
- Adapter:init(Options),
+ Adapter:start(Options),
boss_cache_sup:start_link(Options).
stop() ->
View
4 src/boss_cache_controller.erl
@@ -20,7 +20,7 @@ start_link(Args) ->
init(Options) ->
AdapterName = proplists:get_value(adapter, Options, memcached_bin),
Adapter = list_to_atom(lists:concat(["boss_cache_adapter_", AdapterName])),
- {ok, Conn} = Adapter:start(Options),
+ {ok, Conn} = Adapter:init(Options),
{ok, #state{ adapter = Adapter, connection = Conn }}.
handle_call({get, Prefix, Key}, _From, State) ->
@@ -42,7 +42,7 @@ handle_cast(_Request, State) ->
terminate(_Reason, State) ->
Adapter = State#state.adapter,
Conn = State#state.connection,
- Adapter:stop(Conn).
+ Adapter:terminate(Conn).
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
View
4 src/boss_db.erl
@@ -35,7 +35,7 @@
start(Options) ->
AdapterName = proplists:get_value(adapter, Options, mock),
Adapter = list_to_atom(lists:concat(["boss_db_adapter_", AdapterName])),
- Adapter:init(Options),
+ Adapter:start(Options),
lists:foldr(fun(ShardOptions, Acc) ->
case proplists:get_value(db_shard_models, ShardOptions, []) of
[] -> Acc;
@@ -44,7 +44,7 @@ start(Options) ->
undefined -> Adapter;
ShortName -> list_to_atom(lists:concat(["boss_db_adapter_", ShortName]))
end,
- ShardAdapter:init(ShardOptions ++ Options),
+ ShardAdapter:start(ShardOptions ++ Options),
Acc
end
end, [], proplists:get_value(shards, Options, [])),
View
2  src/boss_db_adapter.erl
@@ -4,7 +4,7 @@
%% @spec behaviour_info( atom() ) -> [ {Function::atom(), Arity::integer()} ] | undefined
behaviour_info(callbacks) ->
[
- {start, 0}, {start, 1}, {stop, 1}, {init, 1},
+ {start, 1}, {stop, 0}, {init, 1}, {terminate, 1},
{find, 2}, {find, 7}, {count, 3},
{delete, 2}, {counter, 2}, {incr, 3}, {save_record, 2}
];
View
4 src/boss_db_controller.erl
@@ -27,7 +27,7 @@ init(Options) ->
Adapter = list_to_atom(lists:concat(["boss_db_adapter_", AdapterName])),
CacheEnable = proplists:get_value(cache_enable, Options, false),
CacheTTL = proplists:get_value(cache_exp_time, Options, 60),
- {ok, Conn} = Adapter:start(Options),
+ {ok, Conn} = Adapter:init(Options),
{Shards, ModelDict} = lists:foldr(fun(ShardOptions, {ShardAcc, ModelDictAcc}) ->
case proplists:get_value(db_shard_models, ShardOptions, []) of
[] ->
@@ -148,7 +148,7 @@ handle_cast(_Request, State) ->
terminate(_Reason, State) ->
Adapter = State#state.adapter,
Conn = State#state.connection,
- Adapter:stop(Conn),
+ Adapter:terminate(Conn),
lists:map(fun({A, C}) ->
A:stop(C)
end, State#state.shards).
View
15 src/db_adapters/boss_db_adapter_mnesia.erl
@@ -1,24 +1,25 @@
-module(boss_db_adapter_mnesia).
-behaviour(boss_db_adapter).
--export([init/1, start/0, start/1, stop/1, find/2, find/7]).
+-export([init/1, terminate/1, start/1, stop/0, find/2, find/7]).
-export([count/3, counter/2, incr/3, delete/2, save_record/2]).
-export([transaction/2]).
%-define(TRILLION, (1000 * 1000 * 1000 * 1000)).
-init(_) ->
+start(_) ->
application:start(mnesia).
+stop() ->
+ application:stop(mnesia).
+
% -----
-start() ->
- start([]).
-start(_Options) ->
+init(_Options) ->
{ok, undefined}.
% -----
-stop(_) ->
- application:stop(mnesia).
+terminate(_) ->
+ ok.
% -----
find(_, Id) when is_list(Id) ->
View
15 src/db_adapters/boss_db_adapter_mock.erl
@@ -1,11 +1,11 @@
% In-memory database for fast tests and easy setup
-module(boss_db_adapter_mock).
-behaviour(boss_db_adapter).
--export([init/1, start/0, start/1, stop/1]).
+-export([init/1, terminate/1, start/1, stop/0]).
-export([find/2, find/7, count/3, counter/2, incr/3, delete/2, save_record/2]).
-export([push/2, pop/2, dump/1, transaction/2]).
-init(Options) ->
+start(Options) ->
case proplists:get_value(is_master_node, Options, true) of
true ->
boss_db_mock_sup:start_link();
@@ -13,16 +13,13 @@ init(Options) ->
ok
end.
-start() ->
- start([]).
+stop() ->
+ ok.
-start(_Options) ->
+init(_Options) ->
{ok, undefined}.
-stop(undefined) ->
- ok;
-stop(MockSup) ->
- exit(MockSup),
+terminate(_) ->
ok.
find(_, Id) ->
View
12 src/db_adapters/boss_db_adapter_mongodb.erl
@@ -1,6 +1,6 @@
-module(boss_db_adapter_mongodb).
-behaviour(boss_db_adapter).
--export([init/1, start/0, start/1, stop/1, find/2, find/7]).
+-export([start/1, stop/0, init/1, terminate/1, find/2, find/7]).
-export([count/3, counter/2, incr/2, incr/3, delete/2, save_record/2]).
-export([execute/2]).
-export([push/2, pop/2]).
@@ -14,13 +14,13 @@
-define(CONTAINS_FORMAT, "this.~s.indexOf('~s') != -1").
-define(NOT_CONTAINS_FORMAT, "this.~s.indexOf('~s') == -1").
-init(_Options) ->
+start(_Options) ->
application:start(mongodb).
-start() ->
- start([]).
+stop() ->
+ ok.
-start(Options) ->
+init(Options) ->
Host = proplists:get_value(db_host, Options, "localhost"),
Port = proplists:get_value(db_port, Options, 27017),
Database = proplists:get_value(db_database, Options, test),
@@ -30,7 +30,7 @@ start(Options) ->
% We pass around arguments required by mongo:do/5
{ok, {WriteMode, ReadMode, Connection, Database}}.
-stop({_, _, Connection, _}) ->
+terminate({_, _, Connection, _}) ->
mongo:disconnect(Connection).
execute({WriteMode, ReadMode, Connection, Database}, Fun) ->
View
13 src/db_adapters/boss_db_adapter_mysql.erl
@@ -1,16 +1,16 @@
-module(boss_db_adapter_mysql).
-behaviour(boss_db_adapter).
--export([init/1, start/0, start/1, stop/1, find/2, find/7]).
+-export([init/1, terminate/1, start/1, stop/0, find/2, find/7]).
-export([count/3, counter/2, incr/3, delete/2, save_record/2]).
-export([push/2, pop/2, dump/1, execute/2, transaction/2]).
-init(_) ->
+start(_) ->
ok.
-start() ->
- start([]).
+stop() ->
+ ok.
-start(Options) ->
+init(Options) ->
DBHost = proplists:get_value(db_host, Options, "localhost"),
DBPort = proplists:get_value(db_port, Options, 3306),
DBUsername = proplists:get_value(db_username, Options, "guest"),
@@ -21,7 +21,8 @@ start(Options) ->
mysql_conn:start(DBHost, DBPort, DBUsername, DBPassword, DBDatabase,
fun(_, _, _, _) -> ok end, Encoding, DBIdentifier).
-stop(_Pid) -> ok.
+terminate(Pid) ->
+ exit(Pid, normal).
find(Pid, Id) when is_list(Id) ->
{Type, TableName, TableId} = infer_type_from_id(Id),
View
12 src/db_adapters/boss_db_adapter_pgsql.erl
@@ -1,16 +1,16 @@
-module(boss_db_adapter_pgsql).
-behaviour(boss_db_adapter).
--export([init/1, start/0, start/1, stop/1, find/2, find/7]).
+-export([init/1, terminate/1, start/1, stop/0, find/2, find/7]).
-export([count/3, counter/2, incr/3, delete/2, save_record/2]).
-export([push/2, pop/2, dump/1, execute/2, transaction/2]).
-init(_) ->
+start(_) ->
ok.
-start() ->
- start([]).
+stop() ->
+ ok.
-start(Options) ->
+init(Options) ->
DBHost = proplists:get_value(db_host, Options, "localhost"),
DBPort = proplists:get_value(db_port, Options, 5432),
DBUsername = proplists:get_value(db_username, Options, "guest"),
@@ -19,7 +19,7 @@ start(Options) ->
pgsql:connect(DBHost, DBUsername, DBPassword,
[{port, DBPort}, {database, DBDatabase}]).
-stop(Conn) ->
+terminate(Conn) ->
pgsql:close(Conn).
find(Conn, Id) when is_list(Id) ->
View
14 src/db_adapters/boss_db_adapter_riak.erl
@@ -1,6 +1,6 @@
-module(boss_db_adapter_riak).
-behaviour(boss_db_adapter).
--export([init/1, start/0, start/1, stop/1, find/2, find/7]).
+-export([init/1, terminate/1, start/1, stop/0, find/2, find/7]).
-export([count/3, counter/2, incr/2, incr/3, delete/2, save_record/2]).
-export([push/2, pop/2]).
@@ -8,21 +8,21 @@
-define(HUGE_INT, 1000 * 1000 * 1000 * 1000).
-init(_Options) ->
+start(_Options) ->
% TODO: crypto is needed for unique_id_62/0. Remove it when
% unique_id_62/0 is not needed.
crypto:start().
-start() ->
- start([]).
+stop() ->
+ ok.
-start(Options) ->
+init(Options) ->
Host = proplists:get_value(db_host, Options, "localhost"),
Port = proplists:get_value(db_port, Options, 8087),
riakc_pb_socket:start_link(Host, Port).
-stop(_) ->
- ok.
+terminate(Conn) ->
+ riakc_pb_socket:stop(Conn).
find(Conn, Id) ->
{Type, Bucket, Key} = infer_type_from_id(Id),
View
14 src/db_adapters/boss_db_adapter_tyrant.erl
@@ -1,24 +1,24 @@
-module(boss_db_adapter_tyrant).
-behaviour(boss_db_adapter).
--export([init/1, start/0, start/1, stop/1, find/2, find/7]).
+-export([init/1, terminate/1, start/1, stop/0, find/2, find/7]).
-export([count/3, counter/2, incr/3, delete/2, save_record/2]).
-define(TRILLION, (1000 * 1000 * 1000 * 1000)).
-init(_) ->
+start(_) ->
ok.
-start() ->
- start([]).
+stop() ->
+ ok.
-start(Options) ->
+init(Options) ->
Host = proplists:get_value(db_host, Options, "localhost"),
Port = proplists:get_value(db_port, Options, 1978),
Options = [{hostname, Host}, {port, Port}],
principe:connect(Options).
-stop(_) ->
- ok.
+terminate(Conn) ->
+ gen_tcp:close(Conn).
find(Conn, Id) when is_list(Id) ->
Type = infer_type_from_id(Id),
Please sign in to comment.
Something went wrong with that request. Please try again.