Understanding Hash Value Omission in Ruby

Ask questions Research chat →

https://allaboutcoding.ghinda.com/hash-value-omission-an-introduction-and-some-examples · scraped

ruby

Attachments

Scraped Content

— 1436 words · 2026-05-19 12:35:06 UTC ·

Excerpt

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721805296524/7ff5695e-5939-467c-8572-94af8cc5bd82.png?w=1600&h=840&fit=crop&crop=entropy&auto=compress,format&format=webp) ## Table of contents The hash literal value omission was added to Ruby version 3.1 in 2021. This is the feature proposal that describes the feature request and the one that was implemented. ## What does it mean? Hash literal value omission (or hash value omission) means that { name: } is a shortcut for { name: name } This works also for method calls with keyword arguments: And of course you can use it to pass values via keyword arguments to other methods when calling from inside current method: It also searches through the methods inside the current object: Notice there inside the method to_meta_tags there are no local variables named title, description or keywords, but there are private methods with that name. So when composing the hash, Ruby will look not only at local variables, but also try to fin
![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721805296524/7ff5695e-5939-467c-8572-94af8cc5bd82.png?w=1600&h=840&fit=crop&crop=entropy&auto=compress,format&format=webp) ## Table of contents The hash literal value omission was added to Ruby version 3.1 in 2021. This is the feature proposal that describes the feature request and the one that was implemented. ## What does it mean? Hash literal value omission (or hash value omission) means that { name: } is a shortcut for { name: name } This works also for method calls with keyword arguments: And of course you can use it to pass values via keyword arguments to other methods when calling from inside current method: It also searches through the methods inside the current object: Notice there inside the method to_meta_tags there are no local variables named title, description or keywords, but there are private methods with that name. So when composing the hash, Ruby will look not only at local variables, but also try to find them among the methods of the current object. What you see here is, in my opinion, the most powerful use of hash literal omission when combined with endless methods: a concise way to create a hash with some computed attributes while keeping the methods very short (one line). ## How it works? The following code is an approximation (like a pseudocode) of how it works. I discovered this simple explanation by Akinori Musha in the feature request: It also has a nice explanatory error message that describes in a way how it works. Let's write a simple example inside a file called error_message.rb. When executed with ruby error_message.rb, it will display the following error message: The error message is explicit: - it says "undefined local variable or method", hinting on the fact that it tries to get the value for name either from a local variable or a method called name. Before going into my own explanation I think this short reply from Victor Shepelev in Reddit makes a good compelling case for this feature: ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721804241162/e6a884e8-5440-4ef9-86db-8cabaae70326.png?auto=compress,format&format=webp) I will touch some of these points below, but I think Victor is doing here a great job explaining in a coincise way why this feature is not hard to understand or to use. I think this kind of code can be easily found in multiple projects: And with hash value omission it can be transformed into: The following idiom is pretty common in a Rails application that uses keyword arguments: It can easily go into a longer line: or this expression can be split into multiple lines: There might be two issues with this type of code: 1. Repeating the same label multiple times 2. This makes the line longer and sometimes requires splitting it into multiple lines. A shorter version could help keep the code on a single line. None of these indicate poor code quality. This feature is more about making things a bit better rather than fixing bad code. In both cases, the code can be written in a more concise form: When reading the feature request Matz decides to accept the proposal with the following argument: After the RubyKaigi 2021 sessions, we have discussed this issue and I was finally persuaded. Our mindset has been updated (mostly due to mandatory keyword arguments). Accepted. It is not that clear from reading the notes there what was the other argument that convincend him along with keyword arguments. Looking at Dev Meeting Log the following was noted: matz: Yes, they should. I was convinced by the points knu made. Thus I asked Akinori Musha via Ruby.social about what were the arguments and he shared the following: ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721718946896/0436b692-54fa-4925-a611-ed122173bea0.png?auto=compress,format&format=webp) A post by Akinori MUSHA (@knu@mr.am) discusses the implementation of pattern-matching with value omission. It gives an example using and explains that it is shorthand for . ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721718977144/cf2aa606-1c54-4404-9f93-32c15a5db4b1.png?auto=compress,format&format=webp) A post by Akinori MUSHA describing how he convinced Matz to introduce value omission in hash literal syntax for symmetry. The tweet includes Ruby code defining and methods, and a method call showing returns 42 when decomposed. In this case hash value omission is seen as a composition, while pattern matching is using decomposition. I think it is an elegant way to think about this feature. He also mentioned that the actual example he used in that discussion was one shared also in the Ruby issue tracker where you can see the same idea of composition and decomposition in a single method: ### It is a known syntax I know that the main argument against this syntax is that is is weird. And I read this weirdness more in the direction of not being familiar. But you can see this syntax in at least two places: 1. Keyword arguments 2. Pattern matching Here is an example from keyword arguments: And here is an example from pattern matching (but in pattern matching this kind of syntax is common): Let's take a look how this can be used in a Rails controller. Assume we have a controller that should create an RSS feed something like this: You can notice the repetition happening at: Let's do a couple of changes to this code: 1. Removing hash values: We could stop at this change, but I think we can make it a bit more concise or at least play a bit more with the advantage that hash value omission allows the use of methods. 1. Move posts and rendered to their one methods I am using here the endless method but it will work the same with normal method: Now it will look like this: That for me it is concise enough and has the avdantage that the index action is only concerned with the response and composing what is needed for the response while the posts and rendereder method are creating the necessary objects outside the action because those objects does not depend on the request/response 1. Push it a bit more The following change is push the changes a bit too far by extracting also locals in a separate method. This can have the advantage that it isolates the purpose of the action method even more about composing the response while delegating the actual composition to the locals method. Insofar that if I want to add one more variable to be passed to the response, I don't need any change in the action (which remains focused on composing the response without knowing too much about the internals) and I need only to change the locals method. But it has the disadvantage that is hides those variables in the method so when reading the action index it is not clear in a quick glance what will be passed on to the response. ### Do not mix hash value omission with providing explicit values I agree here with Rubocop rule that either omit value for all hash keys or provide explicit values but don't mix them. It makes reading the code easier for a lot of people. I personally don't have a big issue with reading also mixed style, but I heared a lot of people complain about it. There are some edge cases where using the hash value omission might create undesired effects. Let's assume there are two methods: And now let's test what happens when we try to call foo with hash value omission and then run bar after it. The output of this will be: But what if we try to make the calls without paranthesis: Can you guess what will be the output? It will be: This happens because it will execute b: bar(b) as in: Conclusion: Always use paranthesis with hash value omission ## An extra trick The following trick was shared by Shugo Maeda, the author of the proposal, on the request feature. Because of how it works you can replace the code that looks like this: With code that looks like this: And it is faster too. This benchmark: will output the following results on my machine (Macbook M3 Pro): If you want to read more about this feature I recommend: - The release notes of Ruby 3.1: https://www.ruby-lang.org/en/news/2021/12/25/ruby-3-1-0-released/ - The Ruby Change log entry about this feature: https://rubyreferences.github.io/rubychanges/3.1.html#values-in-hash-literals-and-keyword-arguments-can-be-omitted - A deep dive by Victor Shepelev https://zverok.space/blog/2023-11-10-syntax-sugar3-hash-values-omission.html - A critique from Bozhidar Batsov https://batsov.com/articles/2022/01/20/bad-ruby-hash-value-omission - A proposal to adop hash value omission I wrote when I was working at Cookpad to merge it to our style guides: https://github.com/cookpad/global-style-guides/pull/195 Enjoyed this article? 👐 Subscribe to my Ruby and Ruby on Rails courses over email at learn.shortruby.com- effortless learning about Ruby anytime, anywhere 👉 Join my Short Ruby Newsletter for weekly Ruby updates from the community and visit rubyandrails.info, a directory with learning content about Ruby. 🎥 Follow me on my YouTube channel for short videos about Ruby https://embeds.hashnode.co?p=5fbe0c72e210ba2ff8ad5cde&w=tinylytics

Visibility

Visible to everyone

Reading Status

Related Bookmarks

My Note


Saved!

Annotations

Export as Markdown
+ Annotate selection

Add Annotation