Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Create Ash module to deal with file resources / uploads. #1052

Open
jakeschurch opened this issue Apr 23, 2024 · 4 comments
Open
Labels
enhancement New feature or request

Comments

@jakeschurch
Copy link

Is your feature request related to a problem? Please describe.
Ash is great. We're missing interacting with files! I'm open to contributing at the very minimum an MVP to solve this 馃槃

Describe the solution you'd like
Use waffle_ecto under the hood for new module `AshFile.Resource.

Create a composite type {:file, MyApp.Uploader.Foo}

With a composite type of {:file, :uploader}:

  • we could provide mix task for file uploader definition creation based that would map to
    waffle_ecto's Uploader resource definition with ash integration.
  • allows us to centralize file upload logic that could be reused in other resources, e.g. MyApp.Avatar.Type across multiple resources
  • rely much more on waffle_ecto work to get MVP ready, implementation could be as simple as a macro def and some mix tasks
  • all :uploader types auto-added to custom ash types
  • potential to embed as an AshFile.Resource, all arguments defined in relevant sections in related module, centralizing logic

Describe alternatives you've considered

With a inline singleton to an Ash.Resource:

Macro expansion could define sub-module Uploaders with embedded waffle_ecto resource,
with use Ash.Resource, extensions: [Ash.File] for 1-1 mapping and feature parity with waffle_ecto.

Definitely way more implementation work up-front to get MVP ready (for me), but seems more ash
design-compliant than composite type approach.

This would allow us to define a global ash_files extension api with default
options, override-able at attribute level.

E.g:

defmodule MyApp.Accounts.User do
  use Ash.Resource,
  extensions: [Ash.File]
  
  ...
  
  attributes do
    ...
    attribute :avatar, :file, allow_nil?: false, constraints: [
      storage: (:s3 | :local),
      validate_file?: (:bool | :fn),  # for form uploads
      s3_opts: [
        access_key_id: :string,
        secret_access_key: :string,
        bucket: :string,
        asset_host: :string,
        storage_dir: (:string | :fn)
        storage_dir_prefix (:string | :fn)
        async?: :bool,
        acl: :enum
      ],
      common_opts: [
        accepts: ({:list :string} | :fn) # file type
        filename: (:fn),
        versions: ({:list :string}, :string, :fn)
        ...  
      ],
      local_opts: [
        ...
      ]
    ]
  end
end

Express the feature either with a change to resource syntax, or with a change to the resource interface

Due to extent of change, I'd like to get to an agreement on API design before filling this section out if ok.

Additional context

I'm currently leaning towards the composite approach due to less time needed for
implementation, but the decision in the end is ultimately left up to @zachdaniel 馃槃

@jakeschurch jakeschurch added enhancement New feature or request needs review labels Apr 23, 2024
@jimsynz
Copy link
Contributor

jimsynz commented Apr 23, 2024

I love this, but I think it should be added as a configurable extension with multiple strategies ala ash authentication.

@jakeschurch
Copy link
Author

jakeschurch commented Apr 24, 2024

@jimsynz could you say more? Waffle ecto allows for s3 and local - if you are referring to multiple storage providers.

If you are referring to blob datatypes, I wonder if that would better fall under repos like ash_postgres.

This at the very least could be an interim tool.

What other strategies would you like to see?

@zachdaniel
Copy link
Contributor

Its interesting...if it can be encapsulated with a type then it should probably be done fully within the bounds of a type as opposed to an extension, but we'll really have to see how it takes shape.

@zachdaniel
Copy link
Contributor

I think let's start with the type-first approach you've got here, and see how far it can go. For now, let's call it ash_waffle, as opposed to ash_file or ash_file_upload or w/e. If we determine that this is the defecto strategy for a certain type of file uploads, we can make ash_file or ash_file_upload depend on this package, for example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants