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

Add update_heritable_value_of #39487

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jonathanhefner
Copy link
Member

@jonathanhefner jonathanhefner commented May 30, 2020

Using a class_attribute for inheritance of values in a Hash is tricky. When storing a new value in a subclass's Hash, you must be careful to not modify the superclass's Hash. On the flip side, when storing a new value in a superclass's Hash, you must ensure the subclass can access the value if and only if it has not already been overridden in the subclass's Hash. (See #39467, #39468, and #39473 for examples of addressing the latter.)

update_heritable_value_of handles both of these requirements:

A = Class.new
B = Class.new(A)
C = Class.new(B)

A.class_attribute :settings, default: {}

A.update_heritable_value_of(:settings, :foo, "A")
A.update_heritable_value_of(:settings, :bar, "A")
B.update_heritable_value_of(:settings, :bar, "B")
C.update_heritable_value_of(:settings, :qux, "C")
A.update_heritable_value_of(:settings, :qux, "A")

A.settings  # == {:foo=>"A", :bar=>"A", :qux=>"A"}
B.settings  # == {:foo=>"A", :bar=>"B", :qux=>"A"}
C.settings  # == {:foo=>"A", :bar=>"B", :qux=>"C"}

/cc @eugeneius
/cc @kamipo

This is an alternative approach to what was being discussed in #39467 (comment) and #39467 (comment).

@eugeneius
Copy link
Member

(Whoops!)

It's hard to reason about this whether this is useful on its own - do you think you could convert some code that currently uses class_attribute to use this instead as an example?

@jonathanhefner
Copy link
Member Author

jonathanhefner commented May 31, 2020

@eugeneius Sure! I added some additional commits to showcase its usage.

The tests are currently failing because one of the commits does not preserve the Hash iteration order from this line. I'll give some thought to how to accommodate that.

@jonathanhefner jonathanhefner force-pushed the add-class_store branch 2 times, most recently from ece3b0d to 6cd7151 Compare June 4, 2020 05:51
kamipo added a commit to kamipo/rails that referenced this pull request Jun 14, 2020
I've partly picked `LiloHash` from rails#39487.

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
@jonathanhefner jonathanhefner force-pushed the add-class_store branch 2 times, most recently from 0fcd6cf to b4451ea Compare June 14, 2020 07:37
@rafaelfranca
Copy link
Member

Can we avoid the dynamic method generation? It is hard to document and find documentation to it. Instead of update_delivery_methods_with_heritable_value can we use update_with_heritable_value(:delivery_methods)? This way we can document update_with_heritable_value and if you search where that method is defined it is easy to find.

@jonathanhefner jonathanhefner force-pushed the add-class_store branch 4 times, most recently from a3d6875 to b7cf5ba Compare June 16, 2020 21:43
@jonathanhefner jonathanhefner changed the title Add Class::class_store Add update_heritable_value_of Jun 23, 2020
@jonathanhefner
Copy link
Member Author

@rafaelfranca Does the current API in the PR description look all right? If so, I can begin squashing, rebasing, writing tests, etc.

Base automatically changed from master to main January 14, 2021 17:01
@rails-bot
Copy link

rails-bot bot commented Apr 14, 2021

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions.

@rails-bot rails-bot bot added the stale label Apr 14, 2021
@rails-bot rails-bot bot removed the stale label Apr 19, 2021
@jonathanhefner jonathanhefner force-pushed the add-class_store branch 3 times, most recently from 2e9006e to 1fbcad6 Compare April 19, 2021 17:41
@jonathanhefner jonathanhefner marked this pull request as ready for review April 19, 2021 17:57
@rails-bot
Copy link

rails-bot bot commented Jul 18, 2021

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions.

@rails-bot
Copy link

rails-bot bot commented Oct 17, 2021

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions.

@rails-bot
Copy link

rails-bot bot commented Jan 16, 2022

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions.

@rails-bot
Copy link

rails-bot bot commented Apr 20, 2022

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions.

@rails-bot rails-bot bot added the stale label Apr 20, 2022
@rails-bot rails-bot bot closed this Apr 27, 2022
@rails-bot rails-bot bot removed the stale label Apr 28, 2022
Using a `class_attribute` for inheritance of values in a Hash is tricky.
When storing a new value in a subclass's Hash, you must be careful to
not modify the superclass's Hash.  On the flip side, when storing a new
value in a superclass's Hash, you must ensure the subclass can access
the value if and only if it has not already been overridden in the
subclass's Hash.

`update_heritable_value_of` handles both of these requirements:

```ruby
A = Class.new
B = Class.new(A)
C = Class.new(B)

A.class_attribute :settings, default: {}

A.update_heritable_value_of(:settings, :foo, "A")
A.update_heritable_value_of(:settings, :bar, "A")
B.update_heritable_value_of(:settings, :bar, "B")
C.update_heritable_value_of(:settings, :qux, "C")
A.update_heritable_value_of(:settings, :qux, "A")

A.settings # => {:foo=>"A", :bar=>"A", :qux=>"A"}
B.settings # => {:foo=>"A", :bar=>"B", :qux=>"A"}
C.settings # => {:foo=>"A", :bar=>"B", :qux=>"C"}
```
@jonathanhefner jonathanhefner changed the title Add update_heritable_value_of Add update_heritable_value_of Apr 28, 2022
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