-
Notifications
You must be signed in to change notification settings - Fork 149
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’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
arc_ecto not working with ecto 3 #104
Comments
Can you try from master now? Should be fixed with #103 |
Hi, it did install fine from Master :) and is working well. Thank you very much for your speedy update on that :) Have 3 little glitches that may be of interest:
Is it possible to pass in client_id or set one constant UUID for each version stored in the db? My uploader file and controller look as follows. The function is to update, so ideally we can delete the existing versions automatically via arc or I can write some logic to do so. CONTROLLER FUNCTION UPLOADER FILE use Arc.Definition def __storage, do: Arc.Storage.Local @versions [:original] @versions [:original, :thumb] def validate({file, _}) do def transform(:thumb, _) do def filename(version, _) do def storage_dir(version, _) do |
Everything seems to be working fine. Only problem seems to be extracting id out of scope.
#{scope.id} isn’t working. If I inspect scope it shows:
%UserApp.Auth.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 1,
inserted_at: ~N[2018-11-16 02:25:49],
password: "$2b$12$zn/rUYLyX73iJRYi00/H4OiXcF9VZSFiM1bzexWhPqio0zO4yBy3y",
photo: %{file_name: "Andrea5.jpg", updated_at: ~N[2018-11-19 06:57:46]},
updated_at: ~N[2018-11-19 06:57:46],
username: "scooby"
}
|
@AppyCat try using the ID from the scope instead of generating a uuid. Each time the filename function is called it will generate a new uuid which I think is the root of it misbehaving. |
Thanks, I dropped the UUID for filenaming, and am trying to use scope.id for a unique directory per user. I am working on a test app trying the Addict dep for authentication, bu dropped it in favor of writing custom auth I get this message when I try to access scope.id scope is accessible with IO.inspect and shows values, but scope.id throws the following error. [error] Task #PID<0.532.0> started from #PID<0.516.0> terminating |
Here's some example code that works for me. Can you compare and see where the difference may be? # document.ex
defmodule MyApp.Library.Document do
@moduledoc """
Defines how to store documents
"""
use Arc.Definition
use Arc.Ecto.Definition
@acl :public_read
@allowed_extensions ~w(.doc .docx .xls .xlsx .pdf)
def allowed_extensions, do: @allowed_extensions
@doc """
Overrides Arc.Definition function.
Validate the file before uploading.
Accepts {version, {file, scope}}
Return true/false
"""
def validate({file, _}) do
extension = Path.extname(file.file_name)
Enum.member?(allowed_extensions(), extension)
end
@doc """
Overrides Arc.Definition function.
Set the uploaded file's filename
Accepts {version, {file, scope}}
Return a string of the filename without extension.
"""
def filename(version, {file, resource}) do
extension = Path.extname(file.file_name)
basename =
file.file_name
|> Path.basename(extension)
|> sanitize_filename()
"#{resource.id}-#{basename}-#{version}"
end
@doc """
Overrides Arc.Definition function.
Set the uploaded file's directory
Accepts {version, {file, scope}}
Return a string of the relative file path from root.
"""
def storage_dir(_version, {_file, _resource}) do
"uploads/resources/activities"
end
@spec sanitize_filename(String.t()) :: String.t()
def sanitize_filename(filename) do
filename |> String.replace(~r/[^A-Za-z0-9]/, "_", global: true)
end
end
# my schema
defmodule MyApp.Library.Resource do
@moduledoc """
Represents resources in the library.
"""
use Ecto.Schema
use Arc.Ecto.Schema
import Ecto.Changeset
@primary_key {:id, :binary_id, autogenerate: true}
schema "resources" do
field(:activity_file, Library.Document.Type)
timestamps(type: :utc_datetime)
end
@required_fields ~w()a
@optional_fields ~w()a
@attachment_fields ~w(activity_file)a
@doc false
def changeset(struct, attrs) do
struct
|> cast(attrs, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
|> ensure_uuid(:id)
|> cast_attachments(attrs, @attachment_fields)
end
@doc "Ensure there's a UUID in the given field"
@spec ensure_uuid(Ecto.Changeset.t(), atom()) :: Ecto.Changeset.t()
def ensure_uuid(changeset, field) do
case get_field(changeset, field) do
nil -> changeset |> put_change(field, Ecto.UUID.generate())
_ -> changeset
end
end
end |
filename and storage are not working if I override either. Filename change is reflected in the outputted file as version, but in the db its the original file name. storage can't override as I'm unable to get scope.id Am using Phoenix 1.4.0, Elixir 1.7.3 and arc_ecto 3.0.1 Thanks for all your help. |
Here's a wish list if in sync with your project roadmap:
I tried a new test project using just arc and arc_ecto and filename and storage override not working on Phoenix 1.4.0, Elixir 1.7.3 and latest versions of arc and arc_ecto (from master branch) If I can be of any help with the above, please let me know. |
@AppyCat it's hard to debug without any of your code. Thanks for your thoughts on what you'd like from ArcEcto. Heads up, Arc provides the ability to delete your assets from storage. It's your responsibility to manage the deletion of the records, and if it's deleted, then also use Arc to delete the asset. |
I tried some of your code, but am unable to pass in a scope that can be used within filename or storage override. I did get delete functionality working just fine, very smooth. Here's my code ref the other 2 issues. defmodule Arco.Photo do use Arc.Ecto.Definition @versions [:original] @versions [:original, :thumb] def validate({file, _}) do def transform(:thumb, _) do def filename(version, {file, user}) do
end @SPEC sanitize_filename(String.t()) :: String.t() And my two controller functions: CREATEdef create(conn, %{"user" => user_params}) do
end UPDATEdef update(conn, %{"id" => id, "user" => user_params}) do
end |
@AppyCat and the changeset code? And what error are you getting? |
Here's the changeset: defmodule Arco.Members.User do schema "users" do
end @doc false Here's the error code trying to use user.id or scope.id once I set it to user in the controller: [error] Task #PID<0.883.0> started from #PID<0.877.0> terminating |
@AppyCat try not casting Also, when creating new records, they don't yet have an ID, which you're telling Arc to use to determine how it should be named or stored. You'll notice in my example I have a Alternatively you could insert the record first without an attachment, and then immediately update it to add the attachment. |
Also, I don't think this is about Ecto 3.0 anymore or a compatibility issue. If you would please close this issue, I'll also be happy to continue debugging here. |
It works beautifully by simply removing :photo from cast() Now I just need to figure out how to save it to get the ID before processing arc. Thanks for your help. |
Hi, I'm using Elixir 1.7.3 with Phoenix 1.4.0 with Arc 0.11.0 and Ecto 3.0
Problem is arc_ecto 0.11.0 wants Ecto 2.0
Can arc_ecto work with Ecto 3 on any other branch?
The text was updated successfully, but these errors were encountered: