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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove direct struct subclassing #1491

Merged
merged 1 commit into from
Feb 8, 2023

Conversation

bdewater
Copy link
Contributor

@bdewater bdewater commented Feb 7, 2023

Description

This is a follow-up to #1489 - I noticed I was still missing Faraday::Request#body= from Tapioca's generated definitions.

Since it also overrides #[] and #[]= it was impossible to set Struct members, so refactored this to a PORO that mostly (but not exactly) looks like the struct it used to be.
Edit: aliased the original member getter/setters so we can override #[] and #[]=. This retains methods inherited from Struct people might be relying on (like #== which is tested in Faraday via Marshal dump/load).

Also did Faraday::Adapter::Test::Stub while I was here for consistency.

@bdewater bdewater force-pushed the proper-struct-subclass-2 branch from c3bf77e to 1d8b9dc Compare February 7, 2023 19:00
This is a follow-up to 39f1b35 - I noticed I was still missing Faraday::Request#body= from Tapioca's generated definitions. Also did Faraday::Adapter::Test::Stub while we're here for consistency.
@bdewater bdewater force-pushed the proper-struct-subclass-2 branch from 1d8b9dc to 2477fe2 Compare February 7, 2023 19:42
@olleolleolle
Copy link
Member

@bdewater Thanks for adding the context of the change, that makes a lot of sense.

Comment on lines +30 to +31
alias_method :member_get, :[]
private :member_get
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

member_get doesn't seem to be used in this file. Is it still necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a leftover from an earlier iteration, it could be removed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I'll merge this as-is and cleanup in my other PR 👍

Comment on lines +32 to +33
alias_method :member_set, :[]=
private :member_set
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, I understood why member_set is required. Previously, Request inherited an anonymous class generated by Struct, but in this PR, it becomes just a Struct and cannot use super. Is it correct?

As far as I see, #params= and #headers= don't follow the documentation: " Replace params, preserving the existing hash type." In other words, their implementations are different from their documents. I think they don't have to be explicitly declared by overriding themselves. What about simply removing #params= and #headers= and delegating the functionalities to Struct? Struct has "#attribute=" out of the box.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are correct for why I added member_set :)

I believe the docs for #params= and #headers= are correct. Normally you don't build a Request directly but use methods on Faraday::Connection. Connection builds Utils::ParamsHash and Utils::Headers (both subclasses of Hash) in the initializer and passes these to Faraday::Request.create. If you merge in additional params or headers (probably using a regular Hash) like this:

connection.get do |req|
  request.headers = { foo: "bar" }
end

this code ensures headers stays a Utils::Headers instance (and does things like stringifying the key) instead of becoming a regular Hash with symbol keys.

Removing these overridden setters leads to one (not very clear) test failure on this line:

expect(req.params['b']).to eq('b')

  1) Faraday::Connection request params with url and extra params allows to override all params
     Failure/Error: expect(req.params['b']).to eq('b')
     
       expected: "b"
            got: nil
     
       (compared using ==)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you both for adding even more context to this detail!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @bdewater, and sorry if this struct is a mess 🙄.
Can't wait to get rid of them in v3.0 🙌!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! That's a great explanation 👍 The document seems to be good because it says "preserving the existing hash type".

So, member_set is aliased as Struct's original #[]= before it is overridden.

def []=(key, value)
headers[key] = value
end

LGTM

@iMacTia iMacTia merged commit 450b0d9 into lostisland:main Feb 8, 2023
@bdewater bdewater deleted the proper-struct-subclass-2 branch February 8, 2023 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants