How to use ex_machina in umbrella apps

I have two apps restaurant_app and graphql_api_app in an umbrella.
I have ex_machina added as dependency to restaurant_app and properly configured there.
In graphql_api_app I want to use the same Factories from restaurant_app for fixtures.
How can i properly setup and configure my tests in graphql_api_app

Found a solution but I don’t know if it’s the right one!
Do this in the second app.

# apps/api/test/test_helper.ex
ExUnit.start()
Ecto.Adapters.SQL.Sandbox.mode(Restaurant.Repo, :manual) # add this line

# apps/api/test/api_web/schema/schema_test.exs
defmodule ApiWeb.Schema.SchemaTest do
  use ApiWeb.ConnCase

  import Restaurant.Factory

 # add this setup block 
  setup _ do
    Ecto.Adapters.SQL.Sandbox.checkout(Restaurant.Repo)
  end

 # code ....

end

Back when we used umbrella apps, we had like a “base” app that all other apps depended on, which would have common or shared factories. Then each app would depend on that base app and also have their own factories.

We recently collapsed our umbrella app into a single OTP app, and we just use environment variables to determine what processes to start. It much more simple and gets you out of dependency hell, but still lets you scale “services” independently.

1 Like
2 Likes

@cjbottaro
It will be helpful if you provide some guide lines on making such app ( I mean the alternative to umbrella apps ), a guide on how to structure the project and how to use the environment variables in this case.
Thank you in advance.

@thojanssens1
The Ecto 2.0 ebook from Plataformatec was helpful.
Thank you so much.

Who is Dave Lucia? I figured he would be the creator of ex_machina or something, but I check the GitHub page and he’s not on the list of contributors.

I also was not really a fan of using ex_machina, and tried to encourage people to just create records using plain Ecto functions instead… but I recently gave it another shot and it’s a bit easier to create associated records, so I’m giving it a shot again.

So every app in the umbrella just becomes a normal dir under lib in a normal mix project. We have several top level modules; not everything is nested under one module. I found that to be fine so far.

Then in runtime.exs we have sections like this…

if System.get_env("START_FOO") || System.get_env("START_ALL") do
  config :my_app, Foo, start: true
end

if System.get_env("START_BAR") || System.get_env("START_ALL") do
  config :my_app, Bar, start: true
end

And finally in lib/my_app/application.ex

...
children = [
  # things you always want started
]
|> add_if_started(Foo)
|> add_if_started(Bar)
...

defp add_if_started(children, mod) do
  start = Application.get_env(:my_app, mod, [])
  |> Keyword.get(:start, false)

  if start do
    children ++ [module]
  else
    children
  end
end

Then if you just want to startup foo, you can do:

START_FOO=1 mix run

Our original umbrella had over a dozen apps in it, but we rewrote it this way because we had lots of circular dependency problems. Our mix projects were filled with xref exceptions.

Also, it’s much easier to navigate this way. Much less config files and mix project files, etc.

3 Likes

Well, this is a strange argument. You don’t have to contribute code to the project you don’t like just to have a permission to criticize it. But, if you appeal to authorities, then there are comments by Saša Jurić in the Twitter thread, who also dislikes ex_machina.

I mean, I find it kind of strange to just show a random tweet with zero context of someone saying they don’t like it. I just assumed it was supposed to be someone that I know.

No explanation or anything. Could have at least said something like, “While this question is specifically about how to use ex_machina, you should be aware that a lot of the community doesn’t recommend it.”

3 Likes

I think it’s not random and it’s in the context of the question, if one takes time to read the tweets.
I’m not obliged to write more lengthy quality content in the forum, nonetheless my intention is to help out and share tips on best practices. I considered the tweet self explanatory and left the reader to own judgement.
I do consider that my reply added value for members who were not aware that some known Elixir devs do not recommend ex_machina (doesn’t mean those devs are always right) and want fellow devs to think twice before using ex_machina after they took note of the tweet.

Now I took the time to write :joy::writing_hand:

I don’t use Twitter; it never occurred to me to click on the link. I thought it was just a standalone statement and clicking would just show me the same statement, but on Twitter’s website instead.

But now that I see, yeah, I agree with that (just using Ecto functions) and was my recommendation for a while, but my team still opted to use ex_machina for some reason. And I thought there was something easier about building assocs with it, but looking at the blurb, it doesn’t look any easier at all.

1 Like