How to create a schema using generator in an ecto project under umbrella project?

Hello All,

How to create a schema using generator in an ecto project under umbrella project? This is what I tried:

I created an umbrella project, and within that project I created an ecto project using the following commands:

mix phx.new hello --umbrella
cd hello_umbrella
mix ecto.create
cd apps
mix phx.new.ecto hello_ecto
cd hello_ecto
mix ecto.create

Now, how do I create a schema in the hello_ecto repo using the generator phx.gen.schema?

The generator command is not available in the hello_ecto project directory. It is available in the hello_umbrella root directory and in the apps/hello_web directory. I tried issuing the schema generator command from the umbrella root directory but I get the error:

(Mix) mix phx.gen.schema can only be run inside an application directory

So I tried from the apps/hello_web directory, but the schema files are generated in the apps/hello/lib/hello and apps/hello/priv/repo/migrations directories.

How do I generate schema for the hello_ecto umbrella project under the hello_ecto directory?

Edit: I ran the following command under hello_web directory:

mix phx.gen.schema HelloSchema hello_schemas name:unique desc --context-app hello_ecto

Now I get the following error:

** (FunctionClauseError) no function clause matching in Mix.Phoenix.context_lib_path/2

The following arguments were given to Mix.Phoenix.context_lib_path/2:

1

   "hello_ecto"

2

   "hello_schema.ex"

Attempted function clauses (showing 1 out of 1):

def context_lib_path(ctx_app, rel_path) when is_atom(ctx_app)

lib/mix/phoenix.ex:224: Mix.Phoenix.context_lib_path/2
lib/mix/phoenix/schema.ex:53: Mix.Phoenix.Schema.new/4
lib/mix/tasks/phx.gen.schema.ex:93: Mix.Tasks.Phx.Gen.Schema.run/1
(mix) lib/mix/task.ex:301: Mix.Task.run_task/3
(mix) lib/mix/cli.ex:75: Mix.CLI.run_task/2

Is this the right way to generate schema in the correct umbrella ecto project? Any help on how to resolve this?

When You run

mix phx.new hello --umbrella

You already create an ecto repo. It is located under /apps/hello.

Is it on purpose that You generate a second one?

mix phx.new.ecto hello_ecto

BTW I would use phx.new.ecto in umbrella project created with the --no-ecto flag

So does that mean there can be only one Repo in an umbrella project?

I am learning Phoenix and trying to understand umbrella project structure. Hence I am trying to create the following project structure as an exercise:

hello_umbrella
 |
 +---apps
      |
      +---hello_ecto
      |
      +---hello_common
      |
      +---hello
      |
      +---hello_web
      |
      +---hello1
      |
      +---hello1_web

Where the hello_ecto project represents a thin API which will be infrequently used by other projects in the umbrella to access a slow database. The hello_common project, which will have it’s own repo, represents common domain logic for projects hello/hello_web and hello1/hello1_web. And the hello and hello1 projects, which have their own respective repos, represents domain logic for hello_web and hello1_web apps respectively

So in the above umbrella project structure there are multiple repos. Is it possible to create this umbrella project structure using generators?

It is fine to use multiple ecto repo inside an umbrella.

I don’t know how to configure the web part for selecting among multiple repos, but in config, ecto_repos accept a list.

Also, as a quick workaround, You don’t have access to phx generators, but You have access to ecto generators… You can go to apps/hello_ecto and run this

$ mix --help | grep ecto
mix ecto               # Prints Ecto help information
mix ecto.create        # Creates the repository storage
mix ecto.drop          # Drops the repository storage
mix ecto.dump          # Dumps the repository database structure
mix ecto.gen.migration # Generates a new migration for the repo
mix ecto.gen.repo      # Generates a new repository
mix ecto.load          # Loads previously dumped database structure
mix ecto.migrate       # Runs the repository migrations
mix ecto.migrations    # Displays the repository migration status
mix ecto.rollback      # Rolls back the repository migrations

You can use ecto.gen.migration instead.

Thank You for the help!

Another workaround I found out to generate ecto repos in their correct destination folders is by modifying the app’s mix.exs and config.exs files to include the concerned ecto project as umbrella dependency and as generator context app respectively. So the mix.exs file of the hello_web app should contain the following in it’s deps:

{:hello_ecto, in_umbrella: true},

and the config.exs should contain the following:

config :hello_web, :generators,
    context_app: :hello_ecto

Now the Phoenix schema generator from hello_web app directory creates schema files in the correct hello_ecto project directory. But this does not feel like the right solution to me. The more appropriate solution would be to either enable schema generator option with command line parameter of --context-app from the umbrella root, or provide the schema generator option for all projects within the umbrella projects. Interestingly the command line option --context-app did not work for me from the hello_web app directory as mentioned in my first post.

1 Like

Glad You could solve it