Repository: phoenixframework/phoenix (elixir)

Issue:
Generators omit default scope fields inside umbrella projects
---

### Environment

- **Elixir version**: 1.18.3 (compiled with Erlang/OTP 27)  
- **Phoenix version**: 1.8.0-rc.1  
- **Operating system**: Linux hs-lws 6.12.21-4-MANJARO  x86_64 GNU/Linux

---

### Actual Behavior

When using generators inside an umbrella project, scoped fields (like `user_id`) are not being created as expected.

Steps to reproduce:

```bash
mix phx.new myapp --umbrella
cd myapp/apps/my_app_web
mix phx.gen.auth ...
mix phx.gen.live UserServices UserService user_services service_id:references:services start_date:date end_date:date --prefix info
```

Generated migration:

```elixir
defmodule MyApp.Repo.Migrations.CreateUserServices do
  use Ecto.Migration

  def change do
    create table(:user_services, prefix: :info) do
      add :start_date, :date
      add :end_date, :date

      add :service_id, references(:services, on_delete: :nothing)
      timestamps()
    end

    create index(:user_services, [:service_id])
  end
end
```

---

### Expected Behavior

I expected the generator to include a default scoped reference like `user_id` in the migration, similar to how it behaves in non-umbrella apps:

```elixir
defmodule MyApp.Repo.Migrations.CreateUserServices do
  use Ecto.Migration

  def change do
    create table(:user_services, prefix: :info) do
      add :start_date, :date
      add :end_date, :date

      add :service_id, references(:services, on_delete: :nothing)
      add :user_id, references(:users, on_delete: :nothing)
      timestamps()
    end

    create index(:user_services, [:service_id])
    create index(:user_services, [:user_id])
  end
end
```

---

Pull request description:
use context_app for scopes
Closes #6219.
Closes #6220.

Patch:
diff --git a/lib/mix/phoenix/schema.ex b/lib/mix/phoenix/schema.ex
index cd4692c86..25aaf45b9 100644
--- a/lib/mix/phoenix/schema.ex
+++ b/lib/mix/phoenix/schema.ex
@@ -83,7 +83,7 @@ defmodule Mix.Phoenix.Schema do
     repo_alias = if String.ends_with?(Atom.to_string(repo), ".Repo"), do: "", else: ", as: Repo"
     file = Mix.Phoenix.context_lib_path(ctx_app, basename <> ".ex")
     table = opts[:table] || schema_plural
-    scope = Mix.Phoenix.Scope.scope_from_opts(otp_app, opts[:scope], opts[:no_scope])
+    scope = Mix.Phoenix.Scope.scope_from_opts(ctx_app, opts[:scope], opts[:no_scope])
     {cli_attrs, uniques, redacts} = extract_attr_flags(cli_attrs)
     {assocs, attrs} = partition_attrs_and_assocs(module, attrs(cli_attrs))
     types = types(attrs)
diff --git a/priv/templates/phx.gen.auth/schema.ex b/priv/templates/phx.gen.auth/schema.ex
index 1ee64e0e6..28d55502f 100644
--- a/priv/templates/phx.gen.auth/schema.ex
+++ b/priv/templates/phx.gen.auth/schema.ex
@@ -7,7 +7,6 @@ defmodule <%= inspect schema.module %> do
     field :email, :string
     field :password, :string, virtual: true, redact: true
     field :hashed_password, :string, redact: true
-    field :current_password, :string, virtual: true, redact: true
     field :confirmed_at, <%= inspect schema.timestamp_type %>
     field :authenticated_at, <%= inspect schema.timestamp_type %>, virtual: true
 


Test patch:
diff --git a/test/mix/tasks/phx.gen.schema_test.exs b/test/mix/tasks/phx.gen.schema_test.exs
index 407c73091..20ba172e0 100644
--- a/test/mix/tasks/phx.gen.schema_test.exs
+++ b/test/mix/tasks/phx.gen.schema_test.exs
@@ -213,9 +213,7 @@ defmodule Mix.Tasks.Phx.Gen.SchemaTest do
 
   test "allows a custom migration dir", config do
     in_tmp_project(config.test, fn ->
-      Gen.Schema.run(
-        ~w(Blog.Post blog_posts title:string --migration-dir priv/custom_dir)
-      )
+      Gen.Schema.run(~w(Blog.Post blog_posts title:string --migration-dir priv/custom_dir))
 
       assert [migration] = Path.wildcard("priv/custom_dir/*_create_blog_posts.exs")
 
@@ -240,9 +238,7 @@ defmodule Mix.Tasks.Phx.Gen.SchemaTest do
 
   test "does not add maps to the required list", config do
     in_tmp_project(config.test, fn ->
-      Gen.Schema.run(
-        ~w(Blog.Post blog_posts title:string tags:map published_at:naive_datetime)
-      )
+      Gen.Schema.run(~w(Blog.Post blog_posts title:string tags:map published_at:naive_datetime))
 
       assert_file("lib/phoenix/blog/post.ex", fn file ->
         assert file =~ "cast(attrs, [:title, :tags, :published_at]"
@@ -283,9 +279,7 @@ defmodule Mix.Tasks.Phx.Gen.SchemaTest do
 
   test "generates unique indices", config do
     in_tmp_project(config.test, fn ->
-      Gen.Schema.run(
-        ~w(Blog.Post posts title:unique secret:redact unique_int:integer:unique)
-      )
+      Gen.Schema.run(~w(Blog.Post posts title:unique secret:redact unique_int:integer:unique))
 
       assert [migration] = Path.wildcard("priv/repo/migrations/*_create_posts.exs")
 
@@ -556,6 +550,48 @@ defmodule Mix.Tasks.Phx.Gen.SchemaTest do
         assert [_] = Path.wildcard("another_app/priv/repo/migrations/*_create_blog_posts.exs")
       end)
     end
+
+    test "generates scoped schema", config do
+      in_tmp_umbrella_project(config.test, fn ->
+        Application.put_env(:phoenix, :generators, context_app: {:another_app, "another_app"})
+
+        with_scope_env(
+          :another_app,
+          [
+            org: [
+              default: true,
+              module: MyApp.Accounts.Scope,
+              assign_key: :current_scope,
+              access_path: [:user, :org_id],
+              schema_key: :org_id,
+              schema_type: :id,
+              schema_table: :organizations
+            ]
+          ],
+          fn ->
+            Gen.Schema.run(~w(Blog.Post blog_posts title:string --scope org --binary-id))
+
+            assert_file("another_app/lib/another_app/blog/post.ex", fn file ->
+              assert file =~ "@primary_key {:id, :binary_id, autogenerate: true}"
+              assert file =~ "field :org_id, :id"
+            end)
+
+            assert [migration] =
+                     Path.wildcard("another_app/priv/repo/migrations/*_create_blog_posts.exs")
+
+            assert_file(migration, fn file ->
+              assert file =~ "create table(:blog_posts, primary_key: false) do"
+              assert file =~ "add :id, :binary_id, primary_key: true"
+
+              assert file =~
+                       "add :org_id, references(:organizations, type: :id, on_delete: :delete_all)"
+
+              assert file =~ "create index(:blog_posts, [:org_id])"
+            end)
+          end
+        )
+      end)
+    end
   end
 
   test "generates scoped schema", config do