Search code examples
elixirphoenix-frameworkecto

Use Ecto in a mix task


In a Phoenix Framework application I have a model Product with the field name. I want to create a mix task which lists all product names.

In Ruby on Rails this would be the code to solve the problem:

namespace :list do
  desc "List all products"
  task products: :environment do
    Product.all.each do |product|
      puts product.name
    end
  end
end

In Phoenix I can't even get the list of all products from the database. Here is the task code:

lib/mix/tasks/list.product.ex

defmodule Mix.Tasks.List.Product do                                    
  use Mix.Task
  import Mix.Ecto
  alias App.Repo
  alias App.Product

  def run(_args) do
    products = Repo.all(Product)
  end
end

When I run this task I get this error message:

** (UndefinedFunctionError) function Ecto.Queryable.__using__/1 
is undefined or private

What do I have to do to fetch all products from the database in this mix task?


Solution

  • The hard way:

    defmodule Mix.Tasks.MyTask do
      use Mix.Task
      import Ecto.Query
      alias MyApp.Repo
    
      @start_apps [
        :postgrex,
        :ecto,
        :ecto_sql
      ]
    
      @repos Application.get_env(:my_app, :ecto_repos, [])
    
      def run(args) do
        start_services()
    
        # Run Ecto...
    
        stop_services()
      end
    
      defp start_services do
        Enum.each(@start_apps, &Application.ensure_all_started/1)
        Enum.each(@repos, & &1.start_link(pool_size: 2))
      end
    
      defp stop_services do
        :init.stop()
      end
    end
    

    or the easy way ;)

    defmodule Mix.Tasks.MyTask do
      use Mix.Task
      import Ecto.Query
      alias MyApp.Repo
    
      def run(args) do
        Mix.Task.run("app.start")
        # Run Ecto...
      end
    end