-
Notifications
You must be signed in to change notification settings - Fork 7
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
Attribute Aliases #43
Conversation
For e.g. this would be useful for logging usage of alias if you're interested in deprecating it.
@@ -81,8 +81,25 @@ def self.new(*attributes,&block) | |||
end | |||
end | |||
|
|||
@@aliases = {} |
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've never really used a class variable in Ruby before, but I think it's appropriate here. It's roughly equivalent (in my mind) to module attributes from Elixir (for lack of a better example).
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.
Please double check if it's thread safe in your use case.
@@aliases = {} | ||
|
||
def self.alias_attribute(aliaz, attr, &block) | ||
@@aliases.store(aliaz, [attr, block]) |
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 is probably "primitive obsession", but I had a hard time convincing myself that we really needed a custom type for this data... A likely causing factor of primitive obsession 😅 💦
@@aliases.store(aliaz, [attr, block]) | ||
end | ||
|
||
def method_missing(m, *_args, &_block) |
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 build failed initially with the signature method_missing(m, *_, &_)
. I assume it's because Ruby doesn't like the underscores in this case, but I didn't dig all the way down on the cause of failure.
@@aliases.store(aliaz, [attr, block]) | ||
end | ||
|
||
def method_missing(m, *_args, &_block) |
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.
Should I override respond_to?
also?
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.
Actually consider def respond_to_missing?
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 the correction 👍
private | ||
|
||
def map_aliases(attrs) | ||
attrs.transform_keys { |k| |
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.
Uh oh, looks like I didn't realize how new Hash#transform_keys is.
Closing this out after having some internal discussion. The pain that pushed me to come up with this solution seems more localized than I had originally thought. |
@januszm Thanks for the review! We decided this isn't a desirable feature for a library that's meant to stay lean. |
Problem
Let's say you want to adjust the trajectory of a value object, but there are existing external dependencies on its interface. How can you begin the process of renaming without breaking compatibility?
Solution
Provide a mechanism for aliasing attributes. This allows you to take the interface of a data object in a different direction without breaking existing references to it. Additionally, aliases might provide a hook which is invoked when they are referenced so that you may log usage and iterate towards their deprecation and eventual removal.