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

Yield instance to Object#with block #50470

Merged
merged 1 commit into from
Jan 7, 2024

Conversation

seanpdoyle
Copy link
Contributor

Detail

The introduction of the block argument means that Object#with can now accept a Symbol#to_proc as the block argument:

client.with(timeout: 5_000, &:ping)

Checklist

Before submitting the PR make sure the following are checked:

  • This Pull Request is related to one change. Changes that are unrelated should be opened in separate PRs.
  • Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex: [Fix #issue-number]
  • Tests are added or updated if you fix a bug or add a feature.
  • CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.

@byroot
Copy link
Member

byroot commented Dec 31, 2023

I'm not really convinced about the usefulness of it, nor it's readability.

@dhh
Copy link
Member

dhh commented Dec 31, 2023

I'd rather have #with return self so you can do client.with(timeout: 5_000).ping.

@byroot
Copy link
Member

byroot commented Jan 5, 2024

I'd rather have #with return self so you can do client.with(timeout: 5_000).ping

The idea of with is to set and restore state around a block, I'm not a fan of having another mode were it doesn't restore state.

@dhh
Copy link
Member

dhh commented Jan 5, 2024

True. You wouldn't be able to scope it just to the call chain that followed.

But I actually do think the original works, even if I don't like the &:ping. Because this is going to be 3.4 code and is quite nice: client.with(timeout: 5_000) { it.ping }.

@dhh
Copy link
Member

dhh commented Jan 6, 2024

Because let's do the AB:

client.with(timeout: 5_000) { client.ping }

I prefer the it version for sure:

client.with(timeout: 5_000) { it.ping }

The longer the class/variable name, the better it gets.

Copy link
Member

@byroot byroot left a comment

Choose a reason for hiding this comment

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

Alright, I think you convinced me. To be honest I didn't quite forsee the use of with on an object you'd use in a block, I had more globals in mind.

@byroot byroot force-pushed the object-with-block-argument branch 2 times, most recently from 46af381 to 101b99c Compare January 7, 2024 19:47
@@ -28,7 +28,7 @@ def with(**attributes)
old_values[key] = public_send(key)
public_send("#{key}=", value)
end
yield
yield self
Copy link
Member

Choose a reason for hiding this comment

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

I took the liberty to improve the implementation though, calling yield_safe(&block) instead of just yield safe in unnecessary overhead AFAICT.

Copy link
Contributor Author

@seanpdoyle seanpdoyle Jan 7, 2024

Choose a reason for hiding this comment

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

While I acknowledge that the change is a mix of optimization (I don't think I'll ever trust my intuition on what is and is not an allocation optimization with regard to blocks) and taste, I wonder if the documentation would benefit from the &block argument's presence in the method signature. While the examples outline that there's a block involved, I find it easier for readers to grasp when a block argument is explicitly mentioned.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, it's more the role of the documentation. I can update it further.

Copy link
Member

Choose a reason for hiding this comment

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

How is it now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that's an improvement!

The introduction of the block argument means that `Object#with` can now
accept a `Symbol#to_proc` as the block argument:

```ruby
client.with(timeout: 5_000) do |c|
  c.get("/commits")
end
```
@byroot byroot merged commit 9c712f8 into rails:main Jan 7, 2024
4 checks passed
@seanpdoyle seanpdoyle deleted the object-with-block-argument branch January 7, 2024 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants