Skip to content

Commit

Permalink
Fixed SQL adapter support for -belong_to_<module>(<field>) associations.
Browse files Browse the repository at this point in the history
  • Loading branch information
DiamondLovesYou committed May 15, 2013
1 parent 9e3a3a8 commit af04966
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 12 deletions.
4 changes: 4 additions & 0 deletions src/boss_record_lib.erl
Expand Up @@ -8,6 +8,7 @@
attribute_types/1,
database_columns/1,
database_table/1,
belongs_to_types/1,
convert_value_to_type/2,
ensure_loaded/1
]).
Expand Down Expand Up @@ -63,6 +64,9 @@ database_table(Module) ->
DummyRecord = dummy_record(Module),
DummyRecord:database_table().

belongs_to_types(Module) when is_atom(Module) ->
(dummy_record(Module)):belongs_to_types().

ensure_loaded(Module) ->
case code:ensure_loaded(Module) of
{module, Module} ->
Expand Down
31 changes: 30 additions & 1 deletion src/boss_sql_lib.erl
Expand Up @@ -2,7 +2,9 @@
-export([keytype/1,
infer_type_from_id/1,
convert_id_condition_to_use_table_ids/1,
is_foreign_key/2
is_foreign_key/2,
convert_possible_foreign_key/6,
get_retyped_foreign_keys/1
]).

-define(DEFAULT_KEYTYPE, serial).
Expand Down Expand Up @@ -51,6 +53,33 @@ is_foreign_key(Type, Key) when is_atom(Key) ->
end;
is_foreign_key(_Type, _Key) -> false.

get_retyped_foreign_keys(Type) when is_atom(Type) ->
% a list of belongs_to-s that use a different module and field names.
% this mainly to reduce the complexity from O(N*M) to O(N*L)
% where N is all fields, M is all of the belongs_to-s, and L is only the differing ones.
lists:foldl(fun ({X, X}, Acc) when is_atom(X) ->
Acc;
({X, Y}, Acc) when is_atom(X) andalso is_atom(Y) ->
[{X, Y} | Acc]
end, [], boss_record_lib:belongs_to_types(Type)).

integer_to_id(Val, KeyString) when is_list(KeyString) ->
ModelName = string:substr(KeyString, 1, string:len(KeyString) - string:len("_id")),
ModelName ++ "-" ++ boss_record_lib:convert_value_to_type(Val, string).

convert_possible_foreign_key(AwkwardAssociations, Type, Key, Value, AttrType, DBColumn) ->
case boss_sql_lib:is_foreign_key(Type, Key) of
true ->
case [ ModuleName || {FieldName, ModuleName} <- AwkwardAssociations, list_to_atom(atom_to_list(FieldName) ++ "_id") =:= Key] of
[] ->
integer_to_id(Value, DBColumn);
[Module] when is_atom(Module) ->
atom_to_list(Module) ++ "-" ++ boss_record_lib:convert_value_to_type(Value, string)
end;
false ->
boss_record_lib:convert_value_to_type(Value, AttrType)
end.

join([], _) -> [];
join([List|Lists], Separator) ->
lists:flatten([List | [[Separator,Next] || Next <- Lists]]).
14 changes: 7 additions & 7 deletions src/db_adapters/boss_db_adapter_mysql.erl
Expand Up @@ -216,13 +216,16 @@ migration_done(Pid, Tag, down) ->

% internal

integer_to_id(Val, KeyString) ->
ModelName = string:substr(KeyString, 1, string:len(KeyString) - string:len("_id")),
ModelName ++ "-" ++ integer_to_list(Val).
%% integer_to_id(Val, KeyString) ->
%% ModelName = string:substr(KeyString, 1, string:len(KeyString) - string:len("_id")),
%% ModelName ++ "-" ++ integer_to_list(Val).

activate_record(Record, Metadata, Type) ->
AttributeTypes = boss_record_lib:attribute_types(Type),
AttributeColumns = boss_record_lib:database_columns(Type),

RetypedForeignKeys = boss_sql_lib:get_retyped_foreign_keys(Type),

apply(Type, new, lists:map(fun
(id) ->
DBColumn = proplists:get_value('id', AttributeColumns),
Expand All @@ -236,10 +239,7 @@ activate_record(Record, Metadata, Type) ->
undefined -> undefined;
{datetime, DateTime} -> boss_record_lib:convert_value_to_type(DateTime, AttrType);
Val ->
case boss_sql_lib:is_foreign_key(Type, Key) of
true -> integer_to_id(Val, DBColumn);
false -> boss_record_lib:convert_value_to_type(Val, AttrType)
end
boss_sql_lib:convert_possible_foreign_key(RetypedForeignKeys, Type, Key, Val, AttrType, DBColumn)
end
end, boss_record_lib:attribute_names(Type))).

Expand Down
8 changes: 4 additions & 4 deletions src/db_adapters/boss_db_adapter_pgsql.erl
Expand Up @@ -190,6 +190,9 @@ integer_to_id(Val, KeyString) ->
activate_record(Record, Metadata, Type) ->
AttributeTypes = boss_record_lib:attribute_types(Type),
AttributeColumns = boss_record_lib:database_columns(Type),

RetypedForeignKeys = boss_sql_lib:get_retyped_foreign_keys(Type),

apply(Type, new, lists:map(fun
(id) ->
DBColumn = proplists:get_value('id', AttributeColumns),
Expand All @@ -203,10 +206,7 @@ activate_record(Record, Metadata, Type) ->
undefined -> undefined;
null -> undefined;
Val ->
case boss_sql_lib:is_foreign_key(Type, Key) of
true -> integer_to_id(Val, DBColumn);
false -> boss_record_lib:convert_value_to_type(Val, AttrType)
end
boss_sql_lib:convert_possible_foreign_key(RetypedForeignKeys, Type, Key, Val, AttrType, DBColumn)
end
end, boss_record_lib:attribute_names(Type))).

Expand Down

0 comments on commit af04966

Please sign in to comment.