-
Notifications
You must be signed in to change notification settings - Fork 7
Simple interface #59
base: master
Are you sure you want to change the base?
Simple interface #59
Conversation
c5cd01f
to
dfd22cf
Compare
fd8f170
to
4a9b6d3
Compare
89cf005
to
4fab8b0
Compare
- a Client instance can create a tranfer (and add files on the go) - split Transfers' .new and .create, - new only initializes, - create also sends it to WeTransfers' Public API - need to have a seperate add_file method to make this work - MiniIO introduced to get wrap all things IO, in a very slim interface
- - DRY up request headers - NullMiniIO: all methods are empty - rename old spec files so they wont run, move them to a specific directory transform request params to JSON as late (and as once) as possible add more old spec files to the ignore list - Add RemoteFile and RemoteTransfer modules that change the corresponding instances *in place*. It sets instance variables and getter methods. - Transfer.find works, very limited test, though - Make upgrading a transfer (a bit) less magical. finalize call for transfers operational File upload implemented Implement file completion Refactorings for readability, less complexity Move communication to CommunicationHelper class More focus in integration test Expose #to_json on a transfer Refactoring * use class<<self instead of private_class_method on def self.foobar things refactor: Remove duplication remove unused image refactor get rid of useless example
4fab8b0
to
9ee34dc
Compare
Start documenting the behavior better
83cc068
to
bcf0a45
Compare
dde3876
to
963ea55
Compare
5242b54
to
6d1f239
Compare
small refactorings for chainging methods on a transfer, and unfuddle the :ensure_ok_status!
Document that 0.10.x only offers transfer support Document high level usage better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great progress 🚀 I would say the only thing I am wary of is the reuse of file names as identifiers for files when uploading "in steps". The rest is cosmetic.
upload.add_file(name: 'README.txt', io: StringIO.new("You should read All the Things!")) | ||
transfer = client.create_transfer_and_upload_files(message: 'All the Things') do |transfer| | ||
# Add a file using File.open. If you do it like this, :name and :io params are optional | ||
transfer.add_file(io: File.open('Gemfile')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we provide auto-DWIM-ing of the filename from the File
object we pass in io:
it would be good to document how it works exactly. For example, will it only use the basename? Will it call #path
on the file? I think I would even go as far as make the method "overloaded" - hit a different code path when you pass in a file:
keyword argument and nothing else, and raise if you, say, pass both file:
and name:
. The rationale being mostly: if we provide "'magic'"™® it should be easy for the end-user to understand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, The SDK relies on File.basename
deeper buried inside as a fallback only. You can rename the file by passing in a name.
Will add documentation to express this behaviour.
# Add a file with File.open, but give it a different name inside the transfer | ||
transfer.add_file( | ||
name: 'hello_world.rb', | ||
io: File.open('path/to/file/with/different_name.rb') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The README in this case encourages leaking file descriptors. For example, if I encountered a README like this I would probably assume that it is the add_file
call that is going to perform #read
on the passed IO objects, and I can (and should) actually call it like this:
File.open('/path/to/myfile', 'rb') do |fi|
transfer.add_file(name: 'myfile', io: fi)
end
but with this example this will probably break as the actual reading of the file data will happen at block exit. Can there be a way to demonstrate it in the readme?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's have an IRL conversation, since I'm unsure if I understand the ins and outs of your point.
# Specifying the size is not very useful in this case, but feel free to explicitly | ||
# communicate the size of the coming io. | ||
# | ||
# The :name param is compulsory if it cannot be derived from the IO. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we say "cannot be derived" we probably need to explain how it will be derived if that is possible (by calling #path
?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self: See here for a closely related issue.
end | ||
|
||
# Upload the file. The Ruby SDK will upload the file in chunks. | ||
transfer.upload_file(name: "small_file", io: StringIO.new("#" * 80)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This enforces addressing files "by name" whereas in practice the server gives you file IDs at transfer create. It is in our best interest to stimulate the consumer of the SDK to either use an abstraction layer that handles ID binding for them:
transfer.files.first.upload(io: ...)
or encourage them to explore the related file metadata:
transfer.files #=> [<RemoteFile id: ...>]
Our approach to "auto-intuiting" the file IDs from the filenames has led to problems as we destructively sanitize the filenames when they enter our systems
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name that the user provided may not be equal to what the WT stack makes of it. This is documented in the Public API. The sdk allows you to call your file 'the-weather-is:.jpg', and reusing that name, while it will be
But from the high-level view of the SDK, I want users to not worry about this. Just as the sdk hides the uploading in chunks, this method hides the file naming details.
Can you agree to this if this is documented better, or do you want the SDK to get rid of this, and use the WT file naming logic only?
## Boards | ||
|
||
**NOTE**: **Boards are disabled from version 0.10.x** of the Ruby SDK. The latest releases that include **board support is found in version 0.9.x** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we remove Boards support from this version probably the documentation has to be removed as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove the docs, but keep the comment about version 0.9, so peeps will know where to go to.
transfer.instance_variable_set "@#{i_var}", data[i_var] | ||
end | ||
|
||
RemoteFile.upgrade( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still on the fence about the "upgrade" terminology. What does it mean that a transfer has been "upgraded" versus when it hasn't?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will express intent better. This is cruft I overlooked after fixing the Remotefile .upgrade
fubar.
# WeTransferFile | ||
# | ||
def name | ||
File.basename(@io) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you really do File.basename(<#File>)
? I thought it only worked with path strings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will investigate
|
||
let(:client) { WeTransfer::Client.new(api_key: ENV.fetch("WT_API_KEY")) } | ||
|
||
it "Convenience method create_transfer_and_upload_files does it all!" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok this is probably being too annoying but when naming RSpec stuff the following guideline can often be useful:
If we string all the describe/context/it
block titles together, does it create a "Noun + verb" sentence that makes sense when printed? For example:
describe "An invigorated Shlobulator" do
context "when connected to a stuffed Frobnicator" do
it "confabricates correctly" do
....
end
end
end
gives us the following output:
An invigorated Shlobulator when connected to a stuffed Frobnicator confabricates correctly
which would make sense when printed in one line. With a wording like this we would see
transfer integration Convenience method create_transfer_and_upload_files does it all!
which does not form a sentence. It's a small thing but one of the gains from well-named examples/contexts is that they usually look good no matter which Rspec formatter is used ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had big issues naming this spec, so I am on your side. Will reinvestigate.
@@ -37,3 +25,5 @@ def test_logger | |||
config.default_formatter = 'doc' | |||
config.order = :random | |||
end | |||
|
|||
RSpec::Mocks.configuration.verify_partial_doubles = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😍
.to raise_error(WeTransfer::CommunicationError) | ||
end | ||
|
||
it "showing the error from the API to the user" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above re. example titles
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all good tips, will push some changes.
|
||
def request_as | ||
@request_as ||= Faraday.new(API_URL_BASE) do |c| | ||
minimal_faraday_config(c) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
transfer.instance_variable_set "@#{i_var}", data[i_var] | ||
end | ||
|
||
RemoteFile.upgrade( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will express intent better. This is cruft I overlooked after fixing the Remotefile .upgrade
fubar.
# WeTransferFile | ||
# | ||
def name | ||
File.basename(@io) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will investigate
|
||
let(:client) { WeTransfer::Client.new(api_key: ENV.fetch("WT_API_KEY")) } | ||
|
||
it "Convenience method create_transfer_and_upload_files does it all!" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had big issues naming this spec, so I am on your side. Will reinvestigate.
upload.add_file_at(path: '/path/to/another/local/file.jpg') | ||
upload.add_file(name: 'README.txt', io: StringIO.new("You should read All the Things!")) | ||
transfer = client.create_transfer_and_upload_files(message: 'All the Things') do |transfer| | ||
# Add a file using File.open. If you do it like this, :name and :io params are optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will propose a change, keep you posted
end | ||
|
||
# Upload the file. The Ruby SDK will upload the file in chunks. | ||
transfer.upload_file(name: "small_file", io: StringIO.new("#" * 80)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name that the user provided may not be equal to what the WT stack makes of it. This is documented in the Public API. The sdk allows you to call your file 'the-weather-is:.jpg', and reusing that name, while it will be
But from the high-level view of the SDK, I want users to not worry about this. Just as the sdk hides the uploading in chunks, this method hides the file naming details.
Can you agree to this if this is documented better, or do you want the SDK to get rid of this, and use the WT file naming logic only?
## Boards | ||
|
||
**NOTE**: **Boards are disabled from version 0.10.x** of the Ruby SDK. The latest releases that include **board support is found in version 0.9.x** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove the docs, but keep the comment about version 0.9, so peeps will know where to go to.
transfer | ||
.upload_files | ||
.complete_files | ||
.finalize |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could even get rid of the transfer
helper var, but it expresses intent so beautifully :)
UPLOAD_URL_URI = "/v2/transfers/%s/files/%s/upload-url/%s" | ||
|
||
DEFAULT_HEADERS = { | ||
"User-Agent" => "WetransferRubySdk/#{WeTransfer::VERSION} Ruby #{RUBY_VERSION}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, from both a debugging and spying perspective 🕵️♂️.
although the Public API doesn't store it anywhere, and I cannot seem to find it in transfer either.
# frozen_string_literal: true | ||
|
||
module WeTransfer | ||
# Wrapper around an IO object, delegating only methods we need for creating |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reword: creating files and sending in chunks
Proposed changes
Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue.
Types of changes
What types of changes does your code introduce to wetransfer_ruby_sdk?
Put an
x
in the boxes that applyChecklist
Put an
x
in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.Further comments
If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...