Search code examples
elixirphoenix-frameworkecto

Ecto equivalent for Rails' acts_as_list?


For Rails, there is the excellent acts_as_list gem, which allows the definition of has-many associations that are ordered by an position integer field. Is there a similar library for Ecto and Phoenix, or does Ecto even implement something like that itself?


Solution

  • Looks like there's a small Ecto extension that could help: https://github.com/zovafit/ecto-ordered


    Though (at least the ordering part of) this could be accomplished fairly easily using some Ecto basics alone:

    web/models/invoice.ex

    defmodule MyApp.Invoice do
      use MyApp.Web, :model
    
      schema "invoices" do
        has_many :line_items, MyApp.LineItem
    
        timestamps
      end
    
      # ...
    end
    

    web/models/line_item.ex

    defmodule MyApp.LineItem do
      use MyApp.Web, :model
    
      schema "line_items" do
        belongs_to :invoice, MyApp.Invoice
        field :position, :integer
    
        timestamps
      end
    
      def positioned do
        from l in __MODULE__,
        order_by: [asc: l.position]
      end
    
      # ...
    end
    

    Then you could query your positioned items like so:

    Repo.all(MyApp.LineItem.positioned)
    

    Or preload them like so:

    Repo.get(MyApp.Invoice, id) |> Repo.preload(line_items: MyApp.LineItem.positioned)
    

    You can read some context about including scopes or conditions into Ecto.Schema.has_many/3 here: https://github.com/elixir-lang/ecto/issues/659