-
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
cast_attachments
uploads files even when passed invalid changeset
#23
Comments
cast_attachments
uploads files even when passed changeset invalidcast_attachments
uploads files even when passed invalid changeset
Can you show me your schema / changesets? Arc should not be storing files via cast and cast_attachments in the same changeset. |
I was (i guess wrongly) trying to use different Arc file versions for two files of the same kind that are attached to my record (see schema). The code is roughly like the following, and the thing was that the image name validation succeeded, but the product and version of the metadata record were empty which is not allowed. Yet still it got uploaded... defmodule TestProject.TestModel do
use TestProject.Web, :model
use Arc.Ecto.Model
alias TestProject.TestModelFile
schema "test_models" do
field :product, :string
field :version, :integer
field :type_a_file, TestModelFile.Type
field :type_b_file, TestModelFile.Type
timestamps
end
@required_fields ~w(product version)
@optional_fields ~w()
@required_file_fields ~w(type_a_file type_b_file)
@optional_file_fields ~w()
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
|> cast_attachments(params, @required_file_fields, @optional_file_fields)
end
end
defmodule TestProject.TestModelFile do
use Arc.Definition
use Arc.Ecto.Definition
# This is another thing apart from this issue, but i was trying to upload a
# 'type_a' version and a 'type_b' version of the same kind of file -
# transformations where applied beforehand -
# until I noticed that I cannot pass in the version of the file that
# the two entries in the schema refer to
@versions [:type_a, :type_b]
def validate({file, _}), do: ~w(.img) |> Enum.member?(Path.extname(file.file_name))
def filename(_version, {_file, %{
product: product,
version: version_num}}) do
"#{product}-#{inspect version_num}.img"
end
def storage_dir(version, _opts) do
"uploads/#{version}_files"
end
end |
https://github.com/elixir-lang/ecto/blob/v1.1.8/lib/ecto/query/planner.ex#L29 calls But arity for https://github.com/stavro/arc_ecto/blob/v0.3.2/lib/arc_ecto/type.ex#L19 seems different:
Thank you! |
would it not be better to upload just the I did an implementation itself of |
It would appear to me we have 3 concerns. 2: The changeset is valid ("validate_attachments") 3: The attachments are stored ("store_attachments") And as side note about validation, what are the plans for caching the attachment if another field is invalid? Currently unless someone managed this by hand you would have to reselect the file in the form after another field failed. |
Anything new with this issue? I have the same problem.. |
pinging this issue. I'm trying to working around these problems manually, but the resulting code is not that clean. |
Just want to throw my 2 cents here. I think arc_ecto doesn't really function in a logical way. Apart from processing upload when changeset is invalid it's also not really possible to attach file to the newly created record. That's like the most important thing it should be able to do. I'm comparing it to paperclip for rails. Paperclip, while not perfect, manages to handle 99% of usecases correctly. Mostly because Right now I can only think about killing off arc_ecto and manually saving file from the controller after I can validate changeset and uploaded file validity. Then I can save record and save file so I have |
Hi @GBH, Even if your points make sense, I think you're comparing two different contexts. First of all, Elixir IS NOT an OOP language like Ruby, this means you don't have a mutable/internal state in your structure that let's you do As you said, all the around callbacks such as That said, I've spent several hours in the last week working on file uploads for my app and I've explored several paths until I ended up with plain
Before arriving to this solution, I've tried to pattern match the result from Hope this helps as inspiration for others with the same problem. I think I will publish some code/tutorial soon (when/if I'll have some spare time :P). cheers! |
@andreapavoni I'd love to see what you got. For now I'd do the uuid thing and not worry about files being created for no reason. |
@GBH I would love to read a detailed blog post on your strategy. |
To keep arc_ecto from saving files on disk until changeset is valid, I use ecto changeset function : prepare_changes in my schema. This function will call arc_ecto cast_attachments only when the changeset is valid and ready for database insertion. Something like this :
The only problem is when you have database constraints that could make ecto repo insertion fail. (For example an unique_constraint on a given field of your schema). But you can handle this in your controller by checking changeset errors and deleting the uploaded files if necesseray. :) |
@kurisusan using prepare_changes however only works for cases that has modified fields other than attachments. If only attachments are modified, cast_attachments won't be called. |
@xfumihiro you're right. I really hope this issue will finally be fixed someday. |
I'm using
cast_attachments
similar to the example provided with the README. I've experienced that the files are uploaded even though the normalcast
that ran before this failed.I'd expect the subsequent call to
cast_attachments
to not store files. In my specific case I was generating the filename from the scope data, which were invalid, so the filename was invalid too. Yet still the file was created on the S3 storage provided.Is this the expected behaviour, and if yes then why so? :)
The text was updated successfully, but these errors were encountered: