Permalink
Browse files

Support custom table names

  • Loading branch information...
1 parent 851ef26 commit adb111e986f56ec37bf566ae4258e8b588261454 @evanmiller evanmiller committed Jan 21, 2013
View
14 README.md
@@ -156,6 +156,20 @@ Accepted types are:
If the type validation fails, then validation_tests/0 will not be called.
+Working with existing SQL databases
+-----------------------------------
+
+By default, SQL columns must be underscored versions of the attribute names,
+and SQL tables must be plural versions of the model names. (If the model is
+"puppy", the database table should be "puppies".)
+
+You may want to override these defaults if you are working with an existing
+database. To specify your own column and table names, you can use the
+-columns() and -table() attributes in a model file like so:
+
+ -module(puppy, [Id, Name]).
+ -columns([{id, "puppy_id"}, {name, "puppy_name"}]).
+ -table("puppy_table").
Events
------
View
18 src/boss_record_compiler.erl
@@ -67,7 +67,8 @@ trick_out_forms(LeadingForms, Forms, ModuleName, Parameters, TokenInfo) ->
GeneratedForms =
attribute_names_forms(ModuleName, Parameters) ++
attribute_types_forms(ModuleName, TokenInfo) ++
- attribute_columns_forms(ModuleName, Parameters, Attributes) ++
+ database_columns_forms(ModuleName, Parameters, Attributes) ++
+ database_table_forms(ModuleName, Attributes) ++
validate_types_forms(ModuleName) ++
validate_forms(ModuleName) ++
save_forms(ModuleName) ++
@@ -132,10 +133,10 @@ export_forms([], Acc) ->
export_forms([{Name, Arity}|Rest], Acc) ->
export_forms(Rest, [erl_syntax:attribute(erl_syntax:atom(export), [erl_syntax:list([erl_syntax:arity_qualifier(erl_syntax:atom(Name), erl_syntax:integer(Arity))])])|Acc]).
-attribute_columns_forms(ModuleName, Parameters, Attributes) ->
+database_columns_forms(ModuleName, Parameters, Attributes) ->
DefinedColumns = proplists:get_value(Attributes, columns, []),
Function = erl_syntax:function(
- erl_syntax:atom(attribute_columns),
+ erl_syntax:atom(database_columns),
[erl_syntax:clause([], none, [erl_syntax:list(lists:map( fun(P) ->
LC = parameter_to_colname(P),
AC = list_to_atom(LC),
@@ -144,10 +145,19 @@ attribute_columns_forms(ModuleName, Parameters, Attributes) ->
end, Parameters))])]),
[erl_syntax:add_precomments([erl_syntax:comment(
- ["% @spec attribute_columns() -> [{atom(), string()}]",
+ ["% @spec database_columns() -> [{atom(), string()}]",
lists:concat(["% @doc A proplist of the database field names of each `", ModuleName, "' parameter."])])],
Function)].
+database_table_forms(ModuleName, Attributes) ->
+ DefinedTableName = proplists:get_value(Attributes, table, inflector:pluralize(atom_to_list(ModuleName))),
+ Function = erl_syntax:function(
+ erl_syntax:atom(database_table),
+ [erl_syntax:clause([], none, [erl_syntax:string(DefinedTableName)])]),
+ [erl_syntax:add_precomments([erl_syntax:comment(
+ ["% @spec database_table() -> string()",
+ lists:concat(["% @doc The name of the database table used to store `", ModuleName, "' records (if any)."])])],
+ Function)].
attribute_types_forms(ModuleName, TypeInfo) ->
[erl_syntax:add_precomments([erl_syntax:comment(
View
11 src/boss_record_lib.erl
@@ -6,7 +6,8 @@
dummy_record/1,
attribute_names/1,
attribute_types/1,
- attribute_columns/1,
+ database_columns/1,
+ database_table/1,
convert_value_to_type/2,
ensure_loaded/1
]).
@@ -54,9 +55,13 @@ attribute_types(Module) ->
DummyRecord = dummy_record(Module),
DummyRecord:attribute_types().
-attribute_columns(Module) ->
+database_columns(Module) ->
DummyRecord = dummy_record(Module),
- DummyRecord:attribute_columns().
+ DummyRecord:database_columns().
+
+database_table(Module) ->
+ DummyRecord = dummy_record(Module),
+ DummyRecord:database_table().
ensure_loaded(Module) ->
case code:ensure_loaded(Module) of
View
12 src/boss_sql_lib.erl
@@ -2,8 +2,7 @@
-export([keytype/1,
infer_type_from_id/1,
convert_id_condition_to_use_table_ids/1,
- is_foreign_key/1,
- type_to_table_name/1
+ is_foreign_key/1
]).
-define(DEFAULT_KEYTYPE, serial).
@@ -18,17 +17,12 @@ keytype(Record) when is_tuple(Record) andalso is_atom(element(1, Record)) ->
infer_type_from_id(Id) when is_list(Id) ->
[Type, TableId] = re:split(Id, "-", [{return, list}, {parts, 2}]),
TypeAtom = list_to_atom(Type),
- IdColumn = proplists:get_value(id, boss_record_lib:attribute_columns(TypeAtom)),
+ IdColumn = proplists:get_value(id, boss_record_lib:database_columns(TypeAtom)),
IdValue = case keytype(Type) of
uuid -> TableId;
serial -> list_to_integer(TableId)
end,
- {TypeAtom, type_to_table_name(Type), IdColumn, IdValue}.
-
-type_to_table_name(Type) when is_atom(Type) ->
- type_to_table_name(atom_to_list(Type));
-type_to_table_name(Type) when is_list(Type) ->
- inflector:pluralize(Type).
+ {TypeAtom, boss_record_lib:database_table(Type), IdColumn, IdValue}.
convert_id_condition_to_use_table_ids({Key, Op, Value}) when Op =:= 'equals'; Op =:= 'not_equals'; Op =:= 'gt';
Op =:= 'lt'; Op =:= 'ge'; Op =:= 'le' ->
View
14 src/db_adapters/boss_db_adapter_mysql.erl
@@ -71,7 +71,7 @@ find(Pid, Type, Conditions, Max, Skip, Sort, SortOrder) when is_atom(Type), is_l
count(Pid, Type, Conditions) ->
ConditionClause = build_conditions(Type, Conditions),
- TableName = boss_sql_lib:type_to_table_name(Type),
+ TableName = boss_record_lib:database_table(Type),
Res = fetch(Pid, ["SELECT COUNT(*) AS count FROM ", TableName, " WHERE ", ConditionClause]),
case Res of
{data, MysqlRes} ->
@@ -213,7 +213,7 @@ integer_to_id(Val, KeyString) ->
activate_record(Record, Metadata, Type) ->
AttributeTypes = boss_record_lib:attribute_types(Type),
- AttributeColumns = boss_record_lib:attribute_columns(Type),
+ AttributeColumns = boss_record_lib:database_columns(Type),
apply(Type, new, lists:map(fun
(id) ->
DBColumn = proplists:get_value('id', AttributeColumns),
@@ -252,8 +252,8 @@ sort_order_sql(ascending) ->
build_insert_query(Record) ->
Type = element(1, Record),
- TableName = boss_sql_lib:type_to_table_name(Type),
- AttributeColumns = Record:attribute_columns(),
+ TableName = boss_record_lib:database_table(Type),
+ AttributeColumns = Record:database_columns(),
{Attributes, Values} = lists:foldl(fun
({_, undefined}, Acc) -> Acc;
({'id', V}, {Attrs, Vals}) ->
@@ -280,7 +280,7 @@ build_insert_query(Record) ->
build_update_query(Record) ->
{_, TableName, IdColumn, TableId} = boss_sql_lib:infer_type_from_id(Record:id()),
- AttributeColumns = Record:attribute_columns(),
+ AttributeColumns = Record:database_columns(),
Updates = lists:foldl(fun
({id, _}, Acc) -> Acc;
({A, V}, Acc) ->
@@ -298,7 +298,7 @@ build_update_query(Record) ->
" WHERE ", IdColumn, " = ", pack_value(TableId)].
build_select_query(Type, Conditions, Max, Skip, Sort, SortOrder) ->
- TableName = boss_sql_lib:type_to_table_name(Type),
+ TableName = boss_record_lib:database_table(Type),
["SELECT * FROM ", TableName,
" WHERE ", build_conditions(Type, Conditions),
" ORDER BY ", atom_to_list(Sort), " ", sort_order_sql(SortOrder),
@@ -307,7 +307,7 @@ build_select_query(Type, Conditions, Max, Skip, Sort, SortOrder) ->
].
build_conditions(Type, Conditions) ->
- AttributeColumns = boss_record_lib:attribute_columns(Type),
+ AttributeColumns = boss_record_lib:database_columns(Type),
Conditions2 = lists:map(fun
({'id' = Key, Op, Value}) ->
Key2 = proplists:get_value(Key, AttributeColumns, Key),
View
19 src/db_adapters/boss_db_adapter_pgsql.erl
@@ -63,7 +63,7 @@ find(Conn, Type, Conditions, Max, Skip, Sort, SortOrder) when is_atom(Type), is_
count(Conn, Type, Conditions) ->
ConditionClause = build_conditions(Type, Conditions),
- TableName = type_to_table_name(Type),
+ TableName = boss_record_lib:database_table(Type),
{ok, _, [{Count}]} = pgsql:equery(Conn,
["SELECT COUNT(*) AS count FROM ", TableName, " WHERE ", ConditionClause]),
Count.
@@ -155,18 +155,13 @@ maybe_populate_id_value(Record) ->
_ -> Record
end.
-type_to_table_name(Type) when is_atom(Type) ->
- type_to_table_name(atom_to_list(Type));
-type_to_table_name(Type) when is_list(Type) ->
- inflector:pluralize(Type).
-
integer_to_id(Val, KeyString) ->
ModelName = string:substr(KeyString, 1, string:len(KeyString) - string:len("_id")),
ModelName ++ "-" ++ id_value_to_string(Val).
activate_record(Record, Metadata, Type) ->
AttributeTypes = boss_record_lib:attribute_types(Type),
- AttributeColumns = boss_record_lib:attribute_columns(Type),
+ AttributeColumns = boss_record_lib:database_columns(Type),
apply(Type, new, lists:map(fun
(id) ->
DBColumn = proplists:get_value('id', AttributeColumns),
@@ -205,8 +200,8 @@ sort_order_sql(ascending) ->
build_insert_query(Record) ->
Type = element(1, Record),
- TableName = type_to_table_name(Type),
- AttributeColumns = Record:attribute_columns(),
+ TableName = boss_record_lib:database_table(Type),
+ AttributeColumns = Record:database_columns(),
{Attributes, Values} = lists:foldl(fun
({_, undefined}, Acc) -> Acc;
({'id', V}, {Attrs, Vals}) ->
@@ -234,7 +229,7 @@ build_insert_query(Record) ->
build_update_query(Record) ->
{_, TableName, IdColumn, Id} = boss_sql_lib:infer_type_from_id(Record:id()),
- AttributeColumns = Record:attribute_columns(),
+ AttributeColumns = Record:database_columns(),
Updates = lists:foldl(fun
({id, _}, Acc) -> Acc;
({A, V}, Acc) ->
@@ -252,7 +247,7 @@ build_update_query(Record) ->
" WHERE ", IdColumn, " = ", pack_value(Id)].
build_select_query(Type, Conditions, Max, Skip, Sort, SortOrder) ->
- TableName = type_to_table_name(Type),
+ TableName = boss_record_lib:database_table(Type),
["SELECT * FROM ", TableName,
" WHERE ", build_conditions(Type, Conditions),
" ORDER BY ", atom_to_list(Sort), " ", sort_order_sql(SortOrder),
@@ -261,7 +256,7 @@ build_select_query(Type, Conditions, Max, Skip, Sort, SortOrder) ->
].
build_conditions(Type, Conditions) ->
- AttributeColumns = boss_record_lib:attribute_columns(Type),
+ AttributeColumns = boss_record_lib:database_columns(Type),
Conditions2 = lists:map(fun
({'id' = Key, Op, Value}) ->
Key2 = proplists:get_value(Key, AttributeColumns, Key),

0 comments on commit adb111e

Please sign in to comment.