-
Notifications
You must be signed in to change notification settings - Fork 275
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
UploadedFile#close should leave uploaded_file in a state where #opened? is false #656
Conversation
…? is false This means removing the reference to the now-closed (and unusable) IO object. Which meant refactoring an existing test slightly, as it tried to refer to the IO object after UploadedFile#close.
The intention behind not resetting the The I wanted to have this behavior to prevent unintentionally opening the same uploaded file multiple times, which is costly. If developers want to do this, they have to be explicit about it. |
OK, interesting, thanks. But you currently can call uploaded_file.open
# do things
uploaded_file.close
uploaded_file.open
# do things
uploaded_file.close
# no problem Is this a mistake, are you not meant to be able to do this? What about It seems odd to me that you can do this, and you can call Calling It calls stream: shrine/lib/shrine/uploaded_file.rb Line 123 in bf43c6d
Which calls shrine/lib/shrine/uploaded_file.rb Line 147 in bf43c6d
So opening more than once is not an accident, it's meant to be supported, I think? Is it intentional that you can call
I am not following this. Can you suggest a code example of a way to do this intentionally while being explicit about it? |
Yes, it's intentional that you can call Here is a code example that I would consider to be implicit re-opening: uploaded_file.open
# do things
uploaded_file.close
uploaded_file.read Here I want an exception to be raised, to alert the developer that they probably didn't want to close the file before, and find ways to reuse the already downloaded content that |
Thanks. I'm having trouble following, but specifically, is it intentional that after calling You can call If I want to call # part A
uploaded_file.open
# do things
uploaded_file.close
# part B
# I think this will work?
uploaded_file.open
tmpfile = uploaded_file.download
uploaded_file.close While this seems relatively straightforward when written like this, it can be entirely different code sites (even in different modules/libraries/gems), that do part A and part B. But I guess you do have access to if uploaded_file.opened?
uploaded_file.open
uploaded_file.download
uploaded_file.close
else
uploaded_file.download
end Wait, that's no good either, becuase Am I making any sense, do you see my point? Or am I misunderstanding? To me it seems a problem that if I don't know what's happened to the file before it arrived at my call site, I can't know how to safely But okay, I guess maybe you're saying that you basically shouldn't write code like that, it's meant to be infeasible to (eg) |
I like the rationale, it seems this will make working with |
Thanks! |
This means removing the reference to the now-closed (and unusable) IO object. Which meant refactoring an existing test slightly, as it tried to refer to the IO object after UploadedFile#close.
Use case where I encountered this
Normally you can call UploadedFile#download without having previously opened, it takes care of it.
AND normally you can open and close an UploadedFile multiple times, no problem.
BUT if you have first opened and closed an UploadedFile THEN try to call #download, it complains -- and it's because the UploadedFile actually still thinks it's #opened?
This is because
close
leaves the UploadedFile in an inconsistent state where it's underlyingio
is closed, BUT the UploadedFile still thinks it'sopened
, which #stream uses to assume the underlying IO is in fact readable.The solution seems to be making sure
#close
leaves the UploadedFile in a symmetrical state as if it had never beenopen
ed in the first place -- that is, unset the@io
tonil
, which will make it no longer opened?NOTE if you use #open in it's block arg form, it already was nil'ing out
@io
. This further supports the idea it's a bugfix to makeclose
do so too.shrine/lib/shrine/uploaded_file.rb
Line 102 in b586fb2
Backwards compat?
The fact that I also had to change that test for rake made me nervous -- is it a backwards incompat to make
uploaded_file.to_io
no longer refer to the closedio
object afterclose
?But I can't think of any actual use case for this OTHER than a test like this -- why would you ever want
to_io
to return a closed unusable IO object? I think this was a bug all along, and is a bug fix, and anything relying on the previous behavior was relying on buggy behavior -- but it's very unlikely anything was, I can't think of any use case for wanting a closed unusable IO object back fromto_io
!