@@ -31,7 +31,7 @@ defmodule ContextKit.CRUD.Scoped do
3131
3232 ## Optional Options
3333
34- * `:except` - List of operation types to exclude (`:list`, `:get`, `:one`, `:delete`, `:create`, `:update`, `:change`, `:subscribe`, `:broadcast`)
34+ * `:except` - List of operation types to exclude (`:new`, `: list`, `:get`, `:one`, `:delete`, `:create`, `:update`, `:change`, `:subscribe`, `:broadcast`)
3535 * `:plural_resource_name` - Custom plural name for list functions (defaults to singular + "s")
3636
3737 ## Generated Functions
@@ -43,6 +43,11 @@ defmodule ContextKit.CRUD.Scoped do
4343 * `query_comments/1` - Returns a filtered query based on options (without executing)
4444 * `query_comments/2` - Returns a scoped and filtered query if `:scope` is configured
4545
46+ ### New Operations
47+ * `new_comment/0` - Returns a new comment
48+ * `new_comment/1` - Returns a new comment with params
49+ * `new_comment/2` - Returns a new comment with params and opts
50+
4651 ### List Operations
4752 * `list_comments/0` - Returns all comments
4853 * `list_comments/1` - Returns filtered comments based on options
@@ -120,6 +125,9 @@ defmodule ContextKit.CRUD.Scoped do
120125 query = MyApp.Blog.query_comments(socket.assigns.current_scope, status: :published)
121126 MyApp.Repo.aggregate(query, :count)
122127
128+ # New comment
129+ MyApp.Blog.new_comment()
130+
123131 # List all comments
124132 MyApp.Blog.list_comments()
125133
@@ -379,7 +387,7 @@ defmodule ContextKit.CRUD.Scoped do
379387 iex> query_#{ unquote ( plural_resource_name ) } (field: 123) |> Repo.aggregate(:count)
380388 123
381389 """
382- @ spec unquote ( :"query_#{ plural_resource_name } " ) ( opts :: Keyword . t ( ) ) :: Ecto.Query . t ( )
390+ @ spec unquote ( :"query_#{ plural_resource_name } " ) ( opts :: keyword ( ) ) :: Ecto.Query . t ( )
383391 def unquote ( :"query_#{ plural_resource_name } " ) ( opts ) when is_list ( opts ) do
384392 { query , custom_query_options } =
385393 Query . build ( Query . new ( unquote ( schema ) ) , unquote ( schema ) , opts )
@@ -406,7 +414,7 @@ defmodule ContextKit.CRUD.Scoped do
406414 iex> query_#{ unquote ( plural_resource_name ) } (socket.assigns.current_scope, field: 123) |> Repo.aggregate(:count)
407415 123
408416 """
409- @ spec unquote ( :"query_#{ plural_resource_name } " ) ( unquote ( scope_module ) . t ( ) , opts :: Keyword . t ( ) ) :: Ecto.Query . t ( )
417+ @ spec unquote ( :"query_#{ plural_resource_name } " ) ( unquote ( scope_module ) . t ( ) , opts :: keyword ( ) ) :: Ecto.Query . t ( )
410418 def unquote ( :"query_#{ plural_resource_name } " ) ( % unquote ( scope_module ) { } = scope , opts \\ [ ] ) do
411419 opts = Keyword . put ( opts , :scope , scope )
412420
@@ -420,6 +428,52 @@ defmodule ContextKit.CRUD.Scoped do
420428 ]
421429 end
422430
431+ if :new not in unquote ( except ) do
432+ @ doc """
433+ Returns a `%#{ unquote ( schema_name ) } {}`.
434+
435+ Fields can be passed as a map. Optionally, you can pass preloads via the opts
436+ keyword list to preload associations on the returned struct.
437+
438+ ## Examples
439+
440+ iex> new_#{ unquote ( resource_name ) } ()
441+ %#{ unquote ( schema_name ) } {}
442+
443+ iex> new_#{ unquote ( resource_name ) } (%{foo: "bar"})
444+ %#{ unquote ( schema_name ) } {foo: "bar"}
445+
446+ iex> new_#{ unquote ( resource_name ) } (%{assoc_id: 123}, preload: [:assoc])
447+ %#{ unquote ( schema_name ) } {assoc_id: 123, assoc: %Assoc{}}
448+ """
449+ @ spec unquote ( :"new_#{ resource_name } " ) ( ) :: unquote ( schema ) . t ( )
450+ def unquote ( :"new_#{ resource_name } " ) ( ) do
451+ unquote ( :"new_#{ resource_name } " ) ( % { } , [ ] )
452+ end
453+
454+ @ spec unquote ( :"new_#{ resource_name } " ) ( params :: map ( ) ) :: unquote ( schema ) . t ( )
455+ def unquote ( :"new_#{ resource_name } " ) ( params ) when is_map ( params ) do
456+ unquote ( :"new_#{ resource_name } " ) ( params , [ ] )
457+ end
458+
459+ @ spec unquote ( :"new_#{ resource_name } " ) ( params :: map ( ) , opts :: keyword ( ) ) :: unquote ( schema ) . t ( )
460+ def unquote ( :"new_#{ resource_name } " ) ( params , opts ) when is_map ( params ) and is_list ( opts ) do
461+ record =
462+ unquote ( schema ) . __struct__ ( )
463+ |> Ecto.Changeset . change ( )
464+ |> Ecto.Changeset . cast ( params , unquote ( schema ) . __schema__ ( :fields ) )
465+ |> Ecto.Changeset . apply_changes ( )
466+
467+ if opts [ :preload ] , do: unquote ( repo ) . preload ( record , opts [ :preload ] ) , else: record
468+ end
469+
470+ defoverridable [
471+ { unquote ( :"new_#{ resource_name } " ) , 0 } ,
472+ { unquote ( :"new_#{ resource_name } " ) , 1 } ,
473+ { unquote ( :"new_#{ resource_name } " ) , 2 }
474+ ]
475+ end
476+
423477 if :list not in unquote ( except ) do
424478 @ doc """
425479 Returns the list of `%#{ unquote ( schema_name ) } {}`.
@@ -450,7 +504,7 @@ defmodule ContextKit.CRUD.Scoped do
450504 iex> list_#{ unquote ( plural_resource_name ) } (field: "value")
451505 [%#{ unquote ( schema_name ) } {}, ...]
452506 """
453- @ spec unquote ( :"list_#{ plural_resource_name } " ) ( opts :: Keyword . t ( ) | map ( ) ) ::
507+ @ spec unquote ( :"list_#{ plural_resource_name } " ) ( opts :: keyword ( ) | map ( ) ) ::
454508 [ unquote ( schema ) . t ( ) ] | { [ unquote ( schema ) . t ( ) ] , ContextKit.Paginator . t ( ) }
455509 def unquote ( :"list_#{ plural_resource_name } " ) ( opts ) when is_list ( opts ) or is_non_struct_map ( opts ) do
456510 { query , custom_query_options } =
@@ -499,7 +553,7 @@ defmodule ContextKit.CRUD.Scoped do
499553 iex> list_#{ unquote ( plural_resource_name ) } (socket.assigns.current_scope, field: "value")
500554 [%#{ unquote ( schema_name ) } {}, ...]
501555 """
502- @ spec unquote ( :"list_#{ plural_resource_name } " ) ( unquote ( scope_module ) . t ( ) , opts :: Keyword . t ( ) ) ::
556+ @ spec unquote ( :"list_#{ plural_resource_name } " ) ( unquote ( scope_module ) . t ( ) , opts :: keyword ( ) ) ::
503557 [ unquote ( schema ) . t ( ) ] | { [ unquote ( schema ) . t ( ) ] , ContextKit.Paginator . t ( ) }
504558 def unquote ( :"list_#{ plural_resource_name } " ) ( % unquote ( scope_module ) { } = scope , opts \\ [ ] ) do
505559 opts = Keyword . put ( opts , :scope , scope )
@@ -547,7 +601,7 @@ defmodule ContextKit.CRUD.Scoped do
547601 iex> get_#{ unquote ( resource_name ) } (1, field: "test")
548602 nil
549603 """
550- @ spec unquote ( :"get_#{ resource_name } " ) ( id :: term ( ) , opts :: Keyword . t ( ) | Ecto.Query . t ( ) ) ::
604+ @ spec unquote ( :"get_#{ resource_name } " ) ( id :: term ( ) , opts :: keyword ( ) | Ecto.Query . t ( ) ) ::
551605 unquote ( schema ) . t ( ) | nil
552606 def unquote ( :"get_#{ resource_name } " ) ( id , opts ) when is_list ( opts ) or is_struct ( opts , Ecto.Query ) do
553607 { query , custom_query_options } =
@@ -578,7 +632,7 @@ defmodule ContextKit.CRUD.Scoped do
578632 @ spec unquote ( :"get_#{ resource_name } " ) (
579633 scope :: unquote ( scope_module ) . t ( ) ,
580634 id :: term ( ) ,
581- opts :: Keyword . t ( )
635+ opts :: keyword ( )
582636 ) :: unquote ( schema ) . t ( ) | nil
583637 def unquote ( :"get_#{ resource_name } " ) ( % unquote ( scope_module ) { } = scope , id , opts \\ [ ] ) do
584638 opts = Keyword . put ( opts , :scope , scope )
@@ -626,7 +680,7 @@ defmodule ContextKit.CRUD.Scoped do
626680 """
627681 @ spec unquote ( :"get_#{ resource_name } !" ) (
628682 id :: term ( ) ,
629- opts :: Keyword . t ( ) | Ecto.Query . t ( )
683+ opts :: keyword ( ) | Ecto.Query . t ( )
630684 ) :: unquote ( schema ) . t ( )
631685 def unquote ( :"get_#{ resource_name } !" ) ( id , opts ) when is_list ( opts ) or is_struct ( opts , Ecto.Query ) do
632686 { query , custom_query_options } =
@@ -657,7 +711,7 @@ defmodule ContextKit.CRUD.Scoped do
657711 @ spec unquote ( :"get_#{ resource_name } !" ) (
658712 scope :: unquote ( scope_module ) . t ( ) ,
659713 id :: term ( ) ,
660- opts :: Keyword . t ( )
714+ opts :: keyword ( )
661715 ) :: unquote ( schema ) . t ( )
662716 def unquote ( :"get_#{ resource_name } !" ) ( % unquote ( scope_module ) { } = scope , id , opts \\ [ ] ) do
663717 opts = Keyword . put ( opts , :scope , scope )
@@ -686,7 +740,7 @@ defmodule ContextKit.CRUD.Scoped do
686740 iex> one_#{ unquote ( resource_name ) } (opts)
687741 nil
688742 """
689- @ spec unquote ( :"one_#{ resource_name } " ) ( opts :: Keyword . t ( ) | Ecto.Query . t ( ) ) ::
743+ @ spec unquote ( :"one_#{ resource_name } " ) ( opts :: keyword ( ) | Ecto.Query . t ( ) ) ::
690744 unquote ( schema ) . t ( ) | nil
691745 def unquote ( :"one_#{ resource_name } " ) ( opts ) when is_list ( opts ) or is_struct ( opts , Ecto.Query ) do
692746 { query , custom_query_options } =
@@ -715,7 +769,7 @@ defmodule ContextKit.CRUD.Scoped do
715769 """
716770 @ spec unquote ( :"one_#{ resource_name } " ) (
717771 scope :: unquote ( scope_module ) . t ( ) ,
718- opts :: Keyword . t ( )
772+ opts :: keyword ( )
719773 ) :: unquote ( schema ) . t ( ) | nil
720774 def unquote ( :"one_#{ resource_name } " ) ( % unquote ( scope_module ) { } = scope , opts \\ [ ] ) do
721775 opts = Keyword . put ( opts , :scope , scope )
@@ -741,7 +795,7 @@ defmodule ContextKit.CRUD.Scoped do
741795 iex> one_#{ unquote ( resource_name ) } !(opts)
742796 nil
743797 """
744- @ spec unquote ( :"one_#{ resource_name } !" ) ( opts :: Keyword . t ( ) | Ecto.Query . t ( ) ) :: unquote ( schema ) . t ( )
798+ @ spec unquote ( :"one_#{ resource_name } !" ) ( opts :: keyword ( ) | Ecto.Query . t ( ) ) :: unquote ( schema ) . t ( )
745799 def unquote ( :"one_#{ resource_name } !" ) ( opts ) when is_list ( opts ) or is_struct ( opts , Ecto.Query ) do
746800 { query , custom_query_options } =
747801 Query . build ( Query . new ( unquote ( schema ) ) , unquote ( schema ) , opts )
@@ -769,7 +823,7 @@ defmodule ContextKit.CRUD.Scoped do
769823 """
770824 @ spec unquote ( :"one_#{ resource_name } !" ) (
771825 scope :: unquote ( scope_module ) . t ( ) ,
772- opts :: Keyword . t ( )
826+ opts :: keyword ( )
773827 ) :: unquote ( schema ) . t ( )
774828 def unquote ( :"one_#{ resource_name } !" ) ( % unquote ( scope_module ) { } = scope , opts \\ [ ] ) do
775829 opts = Keyword . put ( opts , :scope , scope )
@@ -794,7 +848,7 @@ defmodule ContextKit.CRUD.Scoped do
794848 iex> delete_#{ unquote ( resource_name ) } (id: 1)
795849 {:ok, %#{ unquote ( schema_name ) } {}}
796850 """
797- @ spec unquote ( :"delete_#{ resource_name } " ) ( opts :: Keyword . t ( ) | map ( ) | Ecto.Query . t ( ) ) ::
851+ @ spec unquote ( :"delete_#{ resource_name } " ) ( opts :: keyword ( ) | map ( ) | Ecto.Query . t ( ) ) ::
798852 { :ok , unquote ( schema ) . t ( ) } | { :error , Ecto.Changeset . t ( ) }
799853 def unquote ( :"delete_#{ resource_name } " ) ( opts ) when is_list ( opts ) do
800854 { query , custom_query_options } =
0 commit comments