@@ -545,133 +545,94 @@ defmodule Mongo.Collection do
545
545
|> Enum . map ( fn { name , opts } -> { name , opts [ :default ] } end )
546
546
|> Enum . filter ( fn { _name , fun } -> is_function ( fun ) end )
547
547
548
- case @ timestamps != [ ] do
549
- true ->
550
- def new ( ) do
551
- new_timestamps ( % __MODULE__ { unquote_splicing ( Collection . struct_args ( args ) ) } )
552
- end
553
-
554
- false ->
555
- def new ( ) do
556
- % __MODULE__ { unquote_splicing ( Collection . struct_args ( args ) ) }
557
- end
548
+ def new do
549
+ if @ timestamps != [ ] ,
550
+ do: new_timestamps ( % __MODULE__ { unquote_splicing ( Collection . struct_args ( args ) ) } ) ,
551
+ else: % __MODULE__ { unquote_splicing ( Collection . struct_args ( args ) ) }
558
552
end
559
553
end
560
554
561
555
load_function =
562
556
quote unquote: false do
563
- attribute_names = @ attributes |> Enum . map ( & elem ( & 1 , 0 ) )
557
+ attribute_names = Enum . map ( @ attributes , fn { name , opts } -> { name , opts [ :name ] } end )
564
558
565
559
embed_ones =
566
560
@ embed_ones
567
561
|> Enum . filter ( fn { _name , mod , _opts } -> Collection . has_load_function? ( mod ) end )
568
- |> Enum . map ( fn { name , mod , _opts } -> { name , mod } end )
562
+ |> Enum . map ( fn { name , mod , opts } -> { name , { opts [ :name ] , mod } } end )
569
563
570
564
embed_manys =
571
565
@ embed_manys
572
566
|> Enum . filter ( fn { _name , mod , _opts } -> Collection . has_load_function? ( mod ) end )
573
- |> Enum . map ( fn { name , mod , _opts } -> { name , mod } end )
567
+ |> Enum . map ( fn { name , mod , opts } -> { name , { opts [ :name ] , mod } } end )
574
568
575
- def load ( map , use_atoms \\ false )
569
+ def load ( _map , _use_atoms \\ false )
570
+ def load ( nil , _use_atoms ) , do: nil
571
+ def load ( xs , use_atoms ) when is_list ( xs ) , do: Enum . map ( xs , fn map -> load ( map , use_atoms ) end )
576
572
577
- def load ( nil , _use_atoms ) do
578
- nil
579
- end
580
-
581
- def load ( xs , use_atoms ) when is_list ( xs ) do
582
- Enum . map ( xs , fn map -> load ( map , use_atoms ) end )
583
- end
584
-
585
- def load ( map , false ) when is_map ( map ) do
586
- struct =
587
- Enum . reduce (
588
- unquote ( attribute_names ) ,
589
- % __MODULE__ { } ,
590
- fn name , result ->
591
- Map . put ( result , name , map [ Atom . to_string ( name ) ] )
592
- end
593
- )
573
+ def load ( map , use_atoms ) when is_map ( map ) do
574
+ struct = Enum . reduce ( unquote ( attribute_names ) , % __MODULE__ { } , fn { name , src_name } , result -> Map . put ( result , name , map [ src_name ( src_name , use_atoms ) ] ) end )
594
575
595
576
struct =
596
577
unquote ( embed_ones )
597
- |> Enum . map ( fn { name , mod } -> { name , mod . load ( map [ Atom . to_string ( name ) ] ) } end )
578
+ |> Enum . map ( fn { name , { src_name , mod } } -> { name , mod . load ( map [ src_name ( src_name , use_atoms ) ] , use_atoms ) } end )
598
579
|> Enum . reduce ( struct , fn { name , doc } , acc -> Map . put ( acc , name , doc ) end )
599
580
600
581
unquote ( embed_manys )
601
- |> Enum . map ( fn { name , mod } -> { name , mod . load ( map [ Atom . to_string ( name ) ] ) } end )
582
+ |> Enum . map ( fn { name , { src_name , mod } } -> { name , mod . load ( map [ src_name ( src_name , use_atoms ) ] , use_atoms ) } end )
602
583
|> Enum . reduce ( struct , fn { name , doc } , acc -> Map . put ( acc , name , doc ) end )
603
584
|> @ after_load_fun . ( )
604
585
end
605
586
606
- def load ( map , true ) when is_map ( map ) do
607
- struct =
608
- Enum . reduce (
609
- unquote ( attribute_names ) ,
610
- % __MODULE__ { } ,
611
- fn name , result ->
612
- Map . put ( result , name , map [ name ] )
613
- end
614
- )
615
-
616
- struct =
617
- unquote ( embed_ones )
618
- |> Enum . map ( fn { name , mod } -> { name , mod . load ( map [ name ] , true ) } end )
619
- |> Enum . reduce ( struct , fn { name , doc } , acc -> Map . put ( acc , name , doc ) end )
620
-
621
- unquote ( embed_manys )
622
- |> Enum . map ( fn { name , mod } -> { name , mod . load ( map [ name ] , true ) } end )
623
- |> Enum . reduce ( struct , fn { name , doc } , acc -> Map . put ( acc , name , doc ) end )
624
- |> @ after_load_fun . ( )
625
- end
587
+ defp src_name ( { src_name , _ } , true ) , do: src_name
588
+ defp src_name ( { _ , src_name } , _ ) , do: src_name
626
589
end
627
590
628
591
dump_function =
629
592
quote unquote: false do
593
+ attribute_names = Enum . map ( @ attributes , fn { name , opts } -> { name , opts [ :name ] } end )
594
+
630
595
embed_ones =
631
596
@ embed_ones
632
597
|> Enum . filter ( fn { _name , mod , _opts } -> Collection . has_dump_function? ( mod ) end )
633
- |> Enum . map ( fn { name , mod , _opts } -> { name , mod } end )
598
+ |> Enum . map ( fn { name , mod , opts } -> { name , { opts [ :name ] , mod } } end )
634
599
635
600
embed_manys =
636
601
@ embed_manys
637
602
|> Enum . filter ( fn { _name , mod , _opts } -> Collection . has_dump_function? ( mod ) end )
638
- |> Enum . map ( fn { name , mod , _opts } -> { name , mod } end )
603
+ |> Enum . map ( fn { name , mod , opts } -> { name , { opts [ :name ] , mod } } end )
639
604
640
- def dump ( nil ) do
641
- nil
642
- end
605
+ def dump ( nil ) , do: nil
606
+ def dump ( xs ) when is_list ( xs ) , do: Enum . map ( xs , fn struct -> dump ( struct ) end )
643
607
644
- def dump ( xs ) when is_list ( xs ) do
645
- Enum . map ( xs , fn struct -> dump ( struct ) end )
646
- end
647
-
648
- def dump ( % __MODULE__ { } = struct ) do
649
- struct =
608
+ def dump ( % { } = map ) do
609
+ map =
650
610
unquote ( embed_ones )
651
- |> Enum . map ( fn { name , mod } -> { name , mod . dump ( Map . get ( struct , name ) ) } end )
652
- |> Enum . reduce ( struct , fn { name , doc } , acc -> Map . put ( acc , name , doc ) end )
611
+ |> Enum . map ( fn { name , { _src_name , mod } } -> { name , mod . dump ( Map . get ( map , name ) ) } end )
612
+ |> Enum . reduce ( map , fn { name , doc } , acc -> Map . put ( acc , name , doc ) end )
653
613
654
- struct =
614
+ map =
655
615
unquote ( embed_manys )
656
- |> Enum . map ( fn { name , mod } -> { name , mod . dump ( Map . get ( struct , name ) ) } end )
657
- |> Enum . reduce ( struct , fn { name , doc } , acc -> Map . put ( acc , name , doc ) end )
616
+ |> Enum . map ( fn { name , { _src_name , mod } } -> { name , mod . dump ( Map . get ( map , name ) ) } end )
617
+ |> Enum . reduce ( map , fn { name , doc } , acc -> Map . put ( acc , name , doc ) end )
658
618
659
- struct
619
+ map
660
620
|> Map . drop ( unquote ( @ derived ) )
661
621
|> @ before_dump_fun . ( )
662
622
|> Collection . dump ( )
623
+ |> Enum . into ( % { } , fn { name , value } ->
624
+ case unquote ( attribute_names ) [ name ] || unquote ( embed_ones ) [ name ] || unquote ( embed_manys ) [ name ] do
625
+ { { src_name , _ } , _mod } -> { src_name , value }
626
+ { src_name , _ } -> { src_name , value }
627
+ end
628
+ end )
663
629
end
664
630
end
665
631
666
632
timestamps_function =
667
633
quote unquote: false do
668
- def timestamps ( nil ) do
669
- nil
670
- end
671
-
672
- def timestamps ( xs ) when is_list ( xs ) do
673
- Enum . map ( xs , fn struct -> timestamps ( struct ) end )
674
- end
634
+ def timestamps ( nil ) , do: nil
635
+ def timestamps ( xs ) when is_list ( xs ) , do: Enum . map ( xs , fn struct -> timestamps ( struct ) end )
675
636
676
637
def timestamps ( struct ) do
677
638
updated_at = @ timestamps [ :updated_at ]
@@ -700,6 +661,41 @@ defmodule Mongo.Collection do
700
661
end
701
662
end
702
663
664
+ @ doc """
665
+ Inserts name option for the attribute, embeds_one and embeds_many.
666
+ """
667
+ def add_name ( mod , opts , name ) do
668
+ opts =
669
+ case opts [ :name ] do
670
+ nil -> Keyword . put ( opts , :name , { name , to_string ( name ) } )
671
+ name when is_atom ( name ) -> Keyword . replace ( opts , :name , { name , to_string ( name ) } )
672
+ name when is_binary ( name ) -> Keyword . replace ( opts , :name , { String . to_atom ( name ) , name } )
673
+ _ -> raise ArgumentError , "name must be an atom or a binary"
674
+ end
675
+
676
+ { src_name , _ } = opts [ :name ]
677
+
678
+ if name_exists? ( mod , src_name ) ,
679
+ do: raise ( ArgumentError , "attribute #{ inspect ( name ) } has duplicate name option key\n \n [name: #{ inspect ( src_name ) } ] already exist\n " ) ,
680
+ else: opts
681
+ end
682
+
683
+ defp name_exists? ( mod , name ) do
684
+ name_exists? ( mod , :attributes , name ) || name_exists? ( mod , :embed_ones , name ) || name_exists? ( mod , :embed_manys , name )
685
+ end
686
+
687
+ defp name_exists? ( mod , :attributes , name ) do
688
+ mod
689
+ |> Module . get_attribute ( :attributes )
690
+ |> Enum . any? ( fn { _name , opts } -> elem ( opts [ :name ] , 0 ) == name end )
691
+ end
692
+
693
+ defp name_exists? ( mod , embeds , name ) do
694
+ mod
695
+ |> Module . get_attribute ( embeds )
696
+ |> Enum . any? ( fn { _name , _mod , opts } -> elem ( opts [ :name ] , 0 ) == name end )
697
+ end
698
+
703
699
@ doc """
704
700
Inserts the specified `@id_generator` to the list of attributes. Calls `add_id/3`.
705
701
"""
@@ -720,7 +716,7 @@ defmodule Mongo.Collection do
720
716
721
717
def add_id ( mod , { id , type , fun } , _name ) do
722
718
Module . put_attribute ( mod , :types , { id , type } )
723
- Module . put_attribute ( mod , :attributes , { id , default: fun } )
719
+ Module . put_attribute ( mod , :attributes , { id , default: fun , name: { :_id , "_id" } } )
724
720
end
725
721
726
722
@ doc """
@@ -791,7 +787,7 @@ defmodule Mongo.Collection do
791
787
Adds the struct to the `embeds_one` list.
792
788
"""
793
789
def __embeds_one__ ( mod , name , target , opts ) do
794
- Module . put_attribute ( mod , :embed_ones , { name , target , opts } )
790
+ Module . put_attribute ( mod , :embed_ones , { name , target , add_name ( mod , opts , name ) } )
795
791
end
796
792
797
793
@ doc """
@@ -809,7 +805,7 @@ defmodule Mongo.Collection do
809
805
"""
810
806
def __embeds_many__ ( mod , name , target , type , opts ) do
811
807
Module . put_attribute ( mod , :types , { name , type } )
812
- Module . put_attribute ( mod , :embed_manys , { name , target , opts } )
808
+ Module . put_attribute ( mod , :embed_manys , { name , target , add_name ( mod , opts , name ) } )
813
809
end
814
810
815
811
@ doc """
@@ -825,34 +821,44 @@ defmodule Mongo.Collection do
825
821
Adds the attribute to the attributes list.
826
822
"""
827
823
def __attribute__ ( mod , name , type , opts ) do
828
- case opts [ :derived ] do
829
- true -> Module . put_attribute ( mod , :derived , name )
830
- _ -> [ ]
831
- end
824
+ if opts [ :derived ] ,
825
+ do: Module . put_attribute ( mod , :derived , name ) ,
826
+ else: [ ]
832
827
833
828
Module . put_attribute ( mod , :types , { name , type } )
834
- Module . put_attribute ( mod , :attributes , { name , opts } )
829
+ Module . put_attribute ( mod , :attributes , { name , add_name ( mod , opts , name ) } )
830
+ end
831
+
832
+ @ doc """
833
+ Inserts src_name for the timestamp attribute
834
+ """
835
+ def timestamp ( opts , name ) when is_atom ( name ) do
836
+ case Keyword . get ( opts , name , { name , name } ) do
837
+ { name , src_name } -> { name , src_name }
838
+ name -> { name , name }
839
+ end
835
840
end
836
841
837
842
@ doc """
838
843
Defines the `timestamps/1` function.
839
844
"""
840
845
defmacro timestamps ( opts \\ [ ] ) do
841
846
quote bind_quoted: [ opts: opts ] do
842
- inserted_at = Keyword . get ( opts , :inserted_at , :inserted_at )
843
- updated_at = Keyword . get ( opts , :updated_at , :updated_at )
847
+ { inserted_at , inserted_at_name } = timestamp ( opts , :inserted_at )
848
+ { updated_at , updated_at_name } = timestamp ( opts , :updated_at )
849
+
844
850
type = Keyword . get ( opts , :type , DateTime )
845
851
846
- new_opts =
852
+ ops =
847
853
opts
848
854
|> Keyword . drop ( [ :inserted_at , :updated_at , :type ] )
849
855
|> Keyword . put_new ( :default , & DateTime . utc_now / 0 )
850
856
851
857
Module . put_attribute ( __MODULE__ , :timestamps , { :inserted_at , inserted_at } )
852
858
Module . put_attribute ( __MODULE__ , :timestamps , { :updated_at , updated_at } )
853
859
854
- Collection . __attribute__ ( __MODULE__ , inserted_at , Macro . escape ( type ) , new_opts )
855
- Collection . __attribute__ ( __MODULE__ , updated_at , Macro . escape ( type ) , new_opts )
860
+ Collection . __attribute__ ( __MODULE__ , inserted_at , Macro . escape ( type ) , Keyword . put ( ops , :name , inserted_at_name ) )
861
+ Collection . __attribute__ ( __MODULE__ , updated_at , Macro . escape ( type ) , Keyword . put ( ops , :name , updated_at_name ) )
856
862
end
857
863
end
858
864
@@ -863,8 +869,7 @@ defmodule Mongo.Collection do
863
869
end
864
870
865
871
def dump ( % { __struct__: _ } = struct ) do
866
- map = Map . from_struct ( struct )
867
- :maps . map ( & dump / 2 , map ) |> filter_nils ( )
872
+ :maps . map ( & dump / 2 , Map . from_struct ( struct ) ) |> filter_nils ( )
868
873
end
869
874
870
875
def dump ( map ) , do: :maps . map ( & dump / 2 , map )
@@ -882,16 +887,16 @@ defmodule Mongo.Collection do
882
887
defp ensure_nested_map ( % { __struct__: BSON.LongNumber } = data ) , do: data
883
888
884
889
defp ensure_nested_map ( % { __struct__: _ } = struct ) do
885
- map = Map . from_struct ( struct )
886
- :maps . map ( & dump / 2 , map ) |> filter_nils ( )
890
+ :maps . map ( & dump / 2 , Map . from_struct ( struct ) ) |> filter_nils ( )
887
891
end
888
892
889
893
defp ensure_nested_map ( list ) when is_list ( list ) , do: Enum . map ( list , & ensure_nested_map / 1 )
890
894
891
895
defp ensure_nested_map ( data ) , do: data
892
896
893
897
def filter_nils ( map ) when is_map ( map ) do
894
- Enum . reject ( map , fn { _key , value } -> is_nil ( value ) end )
898
+ map
899
+ |> Enum . reject ( fn { _key , value } -> is_nil ( value ) end )
895
900
|> Enum . into ( % { } )
896
901
end
897
902
0 commit comments