Context module name and Ecto schema module name for more than one word database tables

Normally, for a simple one word table, I would be using something like this:

$ mix phx.gen.context Cars Car cars model:string price:string

But what about if I want to have a table called cars_all and cars_from_alternative_universe?

How would the mix phx.gen.context look like for these two cases?

The docs show the --table option to customize the table name: mix phx.gen.context — Phoenix v1.6.4

Though the generators are not general purpose code generators. They’re meant to get you started, but not to be and end to all code generation needs. So you’ll still run into cases, where you need to manually adjust what the generators supply or even ditch the generators completely for more custom needs.

So, let’s say my table name should be cars_all, how would the mix command look like to generate the context module, Ecto module and db table?

My problem is should it be:

$ mix phx.gen.context Cars_All Car_All cars_all ....

or

$ mix phx.gen.context Cars_all Car_all cars_all ....

or

$ mix phx.gen.context CarsAll CarAll cars_all ....

or something else?

Are you asking about the command or the common naming convention? How would you want to have the context, schema and table to be named?

Convention.

Especially for those long DB tables like: cars_from_alternative_universe

So, let’s say: with the table cars it’s trivial and it would be:

  1. $ mix phx.gen.context Cars Car cars alias:string etc...

But how would you do it for these cases?:

  1. cars_all
  2. cars_from_alternative_universe
  3. men_women_children

Anything that works for you. The convention is to have:

  • Plural for context,
  • Singular for schema,
  • Plural for table name,
  • Singular for controller/view.

But you’re free to break away from the conventions anytime. For example, I store person records. While I could get away with “persons”, I chose to use “people” where I see fit:

  • Context: People,
  • Schema: Person,
  • Table: people,
  • Controller/view: Person.

Please, try with my three examples if possible ;):

  1. cars_all
  2. cars_from_alternative_universe
  3. men_women_children

Also, it would be cool if you could use this notation if possible:

$ mix phx.gen.context Cars_All Car_All cars_all ....

mix phx.gen.context YouCanNameThese WhateverYouWant mumbles --table cars_all

There’s no requirement at all for those names, apart from the first two being a valid Elixir module name.

The convention is to spell those with UpperCamelCase but there’s no need to do so.

1 Like

How would you do it with aforementioned examples of mine?:

  1. cars_all
  2. cars_from_alternative_universe
  3. men_women_children

I don’t think we can give you any useful tips without understanding what these entities model. For example, what is cars_all?

Why not have Cars context, Car schema and cars table? If cars is already taken, what’s the difference between cars and cars_all?

Same goes for the other two examples.

1 Like

Hi @kalkatfyodor!

I think I see what you are trying to ask. Let me give it a go. Let’s first see what the generator uses (using your example):

mix phx.gen.context Cars Car cars model:string price:string

Let’s take each of the args and analyze them:

  • mix → tool that runs the command
  • phx.gen.context → name of the task
  • Cars → name of the context
  • Car → name of the schema
  • cars → name of the db table
  • model:string → column + type
  • price:string → column + type

I created a dummy Phoenix app with mix phx.new hi. If you run the above command, you’d end up with the following diff.

I won’t focus on why or why not you’d want to do that (XY problem) as I think there is a lot of learning when one chases the X :slight_smile: . With that said, let’s try to answer what you asked. Your original question was:

But what about if I want to have a table called cars_all and cars_from_alternative_universe?

Let’s assume you want to share the same context of Cars and want to tackle cars_all:

mix phx.gen.context Cars CarAll cars_all model:string price:string

Let’s take each of the args and analyze them:

  • mix → tool that runs the command
  • phx.gen.context → name of the task
  • Cars → name of the context, the generator will change the file to add the new functions
  • CarAll → name of the schema (this just needs to be a valid CamelCaseModuleName
  • cars_all → name of the db table
  • model:string → column + type
  • price:string → column + type

If you run the above command, you’d end up with the following diff.

I won’t show the last case as it is identical to this last case.

I hope this helps you with your original question! The generators are very powerful and instill good practices we find valuable in the community. I hope you saw the context concept here, how the generator creates a module to serve as the boundary for everything within that context. It’s great stuff.

1 Like

Thanks a lot. The only problem is that I already have Cars context and although it could look similar to you, the data stored there are very different - that is the reason for a different table name.

Could you try that again if you know this information? I mean only the shell commands themselves - you don’t have to write the description of each element.

Also, for cars_from_alternative_universe and men_women_children tables, please. Thank you in advance.

Hi!

The only problem is that I already have Cars context

Could you try that again if you know this information?

Sure! Alright, so you want a different context name? You can give it a context name of your choice, you don’t need to use the same one:

mix phx.gen.context KalkatfyodorAwesomeContextname CarAll cars_all model:string price:string

It’s good to play with the generators, they are very powerful.

Also, for cars_from_alternative_universe and men_women_children tables

Given what I shared above, what have you tried so far? Please share and we can discuss further.

mix phx.gen.context KalkatfyodorAwesomeContextname CarAll cars_all model:string price:string

That’s not what I want to find out. I am fully aware of the possibility of having a name for context that doesn’t resemble the schema and/or table name.

Can you try that with cars_from_alternative_universe and men_women_children tables? If it’s not possible, then OK, I will try to ask on SQL forums or something, but I would like to see how you (and others) reason and how you try make things as consistent and logical as possible - especially when it comes to Phoenix/Ecto conventions.

That’s not what I want to find out. I am fully aware of the possibility of having a name for context that doesn’t resemble the schema and/or table name.

:+1:

Can you try that with cars_from_alternative_universe and men_women_children tables? If it’s not possible, then OK, I will try to ask on SQL forums or something

I think this is beyond me at this time. Please go ahead and ask in the SQL forums. After you do, do you mind reporting back? I’d love to know how you solved this when you do. Thanks!

1 Like

OK, thank you anyway. Also, it would be interesting to hear Chris or some other Phoenix heavyweights on this topic and how would they solve this task :slight_smile:

Alright I’ll bite. So first off, let’s just establish that one single context can have more than one schema inside of it. So if you already have

mix phx.gen.context Cars Car car....

Now your application needs to deal with cars that come from an alternate universe, which have enough different details that you want to keep them in a different table, but they’re similar enough to our dimensional cars that you still want to use the Cars module to manage them. You could then do

mix phx.gen.context Cars CarFromAlternativeUniverse cars_from_alternative_universe...

OK, so what about your other example? Let’s say you now need to track who bought your cars, you could do

mix phx.gen.context Purchaser ManWomanChild men_women_children...

Now it’s also possible to have two schemas in two different contexts refer to the same database table. Let’s say our car application also wants to know, in addition to who purchased the car, who is the riders in the car for any given trip. We could create a Riders context to handle all the logic around tracking riders, and then do

mix phx.gen.context Riders ManWomanChild men_women_children...

This now creates a new context which has a schema which refers to the same table that we created before. You can have some of the fields on the table exposed in the Purchaser schema, and some in the Riders schema. Your schema doesn’t need to have all of the fields that the table has. You can also safely refer to the same database fields from both the Riders and Purchaser schema.

Hope this helps! I’m still not certain on what exactly database structure you had in mind, so I’m not sure where cars_all would fit in, but hopefully you can see how the schema, context, and database all relate from these examples.

3 Likes

Thank you. A nice explanation. Especially with the two contexts for the same table. I didn’t know about that.