Level Up Your Ruby Skillz: Working With Hashes

Level Up Your Ruby Skillz: Working With Hashes

A guide to some of the most useful methods for working with arrays in Ruby...

Last week I tackled Ruby arrays and shared some of the methods I find the most useful for working with them. This week I want to talk about HASHES! Before I dive head first into my favorite methods, I want to give a quick summary of what a hash is in Ruby and how it works. The definition of a Hash straight from the docs themselves:

A Hash is a dictionary-like collection(If you are a Java person, think maps) of unique keys and their values. Also called associative arrays(honestly, I have never heard this before but 🤷), they are similar to Arrays, but where an Array uses integers as its index, a Hash allows you to use any object type.
One of the keys(pun intended 😉) in that definition is that a Hash allows you to use any object type as your index. Most people when they think of a Hash think of this.

{ a: 1, b: 2, c: 3 }

But hashes can be so much more in Ruby! For example, all of these are Hashes.

# String Keys
{ "a" => 1, "b" => 2, "c" => 3 }

# Integer Keys 
{ 1 => "a", 2 => "b", 3 => "c" } 

# Symbol Keys (Hashrocket notation) 
{ :a => 1, :b => 2, :c => 3 } 

# Array Keys
{ ['a'] => 1, ['b'] => 2, ['c'] => 3 } 

# Hash Keys 
{ { :a => 1 } => 2, { :b => 2 } => 3 } 

Any object type your heart desires can be a Hash key. Now that we have the semantics and the definition down, let's get to the methods!

  • [each](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#each "each")
  • [each_key](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#each_key_value "each_key")/[each_value](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#each_key_value "each_value")
  • [keys](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#keys_values "keys") / [values](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#keys_values "values")
  • [key?](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#key_value? "key?")/[value?](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#key_value? "value?")
  • [transform_keys](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#transform_keys "transform_keys")/ [transform_values](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#transform_values "transform_values")
  • [dig](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#dig "dig")
  • [fetch](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#fetch "fetch")
  • [select](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#select "select")
  • [reject](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#reject "reject")
  • [slice](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#slice "slice")
  • [chaining](https://dev.to/molly_struve/level-up-your-ruby-skillz-working-with-hashes-4bid#chaining "chaining")

NOTE: Just like in the array tutorial, if you see irb in the code snippets that means I am working in a Ruby console. Also, I made a code CHEAT SHEETif you want the code without all the explanations.

[each](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-each "each")

One of the most valuable things you can do with a hash is iterate over it. One of the easiest ways to loop over a hash is to use [each](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-each "each"). I don't know about you, but when I started out using Ruby, my hash each statements looked like this.

irb> { a: 1, b: 2, c: 3 }.each do |pair|
  puts "#{pair.first} #{pair.last}"
end
a 1
b 2
c 3
=> {:a=>1, :b=>2, :c=>3}

Here, I am executing my each method the same way I did for my arrays. The difference now is that pair is an array itself. The first element is my key and the second element is my value. NOTE: After executing the block for each of our key/value pairs, the original hash that we iterated over is returned.

The above way works, but there is an even slicker way, you can separate that pair by passing two arguments to your block. This means you can rewrite the above like this:

irb> { a: 1, b: 2, c: 3 }.each do |key, value|
  puts "#{key} #{value}"
end
a 1
b 2
c 3
=> {:a=>1, :b=>2, :c=>3}

Now we have two separate variables, one representing the key and one representing the value.

[each_key](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-each_key "each_key")/[each_value](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-each_value "each_value")

But what if we don't want all the keys and values? What if we just want the keys or just want the values? There are methods for each of those!

irb> { a: 1, b: 2, c: 3 }.each_key do |key|
  puts key
end
a
b 
c
=> {:a=>1, :b=>2, :c=>3}

irb> { a: 1, b: 2, c: 3 }.each_value do |value|
  puts value
end
a
b 
c
=> {:a=>1, :b=>2, :c=>3}

Notice, that once again, regardless if we use each_key or each_value, we still get the original hash back after we are done iterating over it.

[keys](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-keys "keys")/ [values](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-values "values")

Let's say you just want an array of the keys or you just want an array of the values from a hash. To do this, you can use keys or values. Both will return an array of the keys or values for a given hash.

irb> { a: 1, b: 2, c: 3 }.keys 
=> [:a, :b, :c]
irb> { a: 1, b: 2, c: 3 }.values 
=> [1, 2, 3]

[key?](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-key-3F "key?")/ [value?](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-value-3F "value?")

Another couple of pretty straight forward methods are the key and value predicates. If you want to know if a key or a value exists in a Hash then you can use key? or value?.

irb> { a: 1, b: 2 }.key?(:b)
=> true
irb> { a: 1, b: 2 }.value?(2)
=> true
irb> { a: 1, b: 2 }.value?(5)
=> false

This is pretty straightforward, but there are a couple of nuances I want to point out. For starters, when you are looking for a key, you have to make sure you are looking for the proper datatype. For example, if you have a hash with symbol keys, searching for a string will return false.

irb> { a: 1, b: 2 }.key?("b")
=> false

Make sure the datatype you are searching for matches the datatype of your keys or values.

[fetch](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-fetch "fetch")

Now we know how we can check if we have a specific key or value, but what if we want to actually look up the value for a key? Well, there is always the standard way to do it and this is what I learned first.

irb> h = { a: 1, b: 2, c: 3 }
irb> h[:a] 
=> 1
irb> h[:d] 
=> nil

Simple and easy. If the key is there, we return its value. If the key is not there we return nil. But what if we have some more complicated logic? For example, what if we want to return the key's value OR, if the key does not exist, we want to return some default, like 0? With what we know so far we could do this

h = { a: 1, b: 2, c: 3 }
if h[:a]
  result = h[:a]
else
  result = 0
end

It works, but it is a pretty decent chunk of code to get it done. Instead, we can replace that large chunk of code with one simple method, fetch. fetchhas a lot of options and behaviors so lets unpack each, one at a time.

  1. **fetch**** with NO arguments** will return the value if it is present. If the value is not present, fetch will raise an error. This is great if you want to raise an error when a key cannot be found.
irb> h = { a: 1, b: 2, c: 3 }
irb> h.fetch(:a) 
=> 1
irb> h.fetch(:d) 
KeyError: key not found: :d
    from (irb):13:in `fetch'
    from (irb):13

  1. **fetch**** WITH arguments** will return the value if it is present, just like before. Here is where it gets slick and can help us out with our original use case, if you pass fetch an argument and the key is not present, it will return the argument! 🔥
irb> h = { a: 1, b: 2, c: 3 }
irb> h.fetch(:a, 0) 
=> 1
irb> h.fetch(:d, 0) 
=> 0

[dig](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-dig "dig")

fetch works great when you have a single level hash and want to return a value from it using a key. But what if you have several nested hashes? For example

h = { a: { b: { c: 1 } } }

Normally to get the value of c you would want to do

irb> h[:a][:b][:c] 
=> 1

which would traverse your nested hashes and return your value. But what if you are not sure whether all those levels are present? For example, let's say you are working with an API to get user data. Sometimes you find the user you are looking for and get this back.

{ user: { first: 'mary', last: 'sue' } }

Other times, you don't find the user you want and you get this back,

{ status: 'not found' }

In this case, we can't just assume we have the user information, because if we don't have the user information, we will end up raising an error.

irb> h = { status: 'not found' }
irb> h[:user][:first] 
=> NoMethodError: undefined method `[]' for nil:NilClass

To avoid this, we could do

h = { status: 'not found' }
if h[:user].present?
  result = h[:user][:first]
else
  result = nil
end

This ensures if we have the user data, we return the first name. If we don't have the data, then we return nil. Turns out, we can avoid ALL of this by using dig. [dig](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-dig "dig") extracts the nested value specified by a sequence of key objects. However, if any one of those nested keys do not exist, it will return nil. 🎉

irb> h = { user: { first: 'mary', last: 'sue' } }
irb> h.dig(:user, :first) 
=> 'mary'
irb> h = { status: 'not found' }
irb> h.dig(:user, :first) 
=> nil

dig is great when you want to traverse a hash but are not sure what its structure might be. It allows you to work with a hash without worrying about handling a bunch of errors or doing a bunch of present? checks using if/else blocks.

[transform_keys](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-transform_keys "transform_keys") (Only available in Ruby 2.5 and above)

Now we are going to kick it up a notch. What if we have a hash where all the keys are symbols, but we want to change them all to strings? In the early days we would do this.

new_hash = {}
{ a: 1, b: 2, c: 3 }.each do |key, value|
  new_hash[key.to_s] = value
end
# new_hash = { "a" => 1, "b" => 2, "c" => 3 }

It works, but you guessed it, now there is a better way. That better way is transform_keys. [transform_keys](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-transform_keys "transform_keys") allows you to iterate over a hash and will return a new hash. The new hash keys will be the result from executing the block for each of the original keys.

h = { a: 1, b: 2, c: 3 }
new_hash = h.transform_keys do |k| 
  k.to_s 
end  
# new_hash = { "a" => 1, "b" => 2, "c" => 3 }       

IMPORTANT transform_keys(above) and transform_values(below) are only available in Ruby 2.5 and above. If you get the following error, then you are likely working with a version of Ruby below 2.5 NoMethodError: undefined methodtransform_keysfor {:a=>1, :b=>2, :c=>3}:Hash

[transform_values](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-transform_values "transform_values") (Only available in Ruby 2.5 and above)

transform_values works the exact same way as transform_keys, except it allows you to update the values. When it is done executing your block, it will return a new hash with the new set of values.

h = { a: 1, b: 2, c: 3 }
new_hash = h.transform_values do |value| 
  value * 2 
end  
# new_hash = { :a => 2, :b => 4, :c => 6 }      

[select](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-select "select")

Now we are going to get into some familiar territory if you read my first array tutorial. Just like for arrays, you can use select for hashes! [select](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-select "select") for a hash works basically the same as an array, it returns a new hash with the key/value pairs that your block evaluated true for.

# clunky way
new_hash = {}
h = { a: 1, b: 2, c: 3, d: 4 }
h.each do |key, value| 
  new_hash[key] = value if value.even?
end  
# new_hash = { :b => 2, :d => 4 }

# slick select way
h = { a: 1, b: 2, c: 3, d: 4 }
new_hash = h.select do |key, value| 
  value.even?
end  
# new_hash = { :b => 2, :d => 4 }

[slice](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-slice "slice")

Let's say you have a hash and you just want back a specific set of keys and their values. You could do something like this

key_list = [:a, :d]
h = { a: 1, b: 2, c: 3, d: 4 }
new_hash = h.select do |key, value| 
  key_list.include?(key)
end  
# new_hash = { :a => 1, :d => 4 }

But Ruby has a simpler way and that is by using slice. [slice](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-slice "slice") will return a hash with only the keys you request via your arguments. What we have above can be simplified to

h = { a: 1, b: 2, c: 3, d: 4 }
new_hash = h.slice(:a, :d) 
# new_hash = { :a => 1, :d => 4 }

[reject](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-reject "reject")

Back we go again to familiar array territory. reject for a hash works the same way it does for an array. [reject](https://ruby-doc.org/core-2.6.0.preview2/Hash.html#method-i-reject "reject") will return a new hash consisting of all the key/value pairs for which your block returns false.

h = { a: 1, b: 2, c: 3, d: 4 }
new_hash = h.reject do |key, value| 
  value.even?
end  
# new_hash = { :a => 1, :c => 3 }

chaining

Last, but not least, we need to cover chaining. Any of the methods above that return a hash, you can chain together. For these examples I am going to use bracket notation because I think it's easier to read chaining methods from left to right, rather than up and down.

Here is an example of chaining some of the above methods together.

h = { a: 1, b: 2, c: 3, d: 4 }
result = h.transform_keys{|k| k.to_s}.slice("a", "b").reject{|k, v| v == 2}.transform_values{|value| "hi #{value}"} 
# result = {"a"=>"hi 1"}

Let's break down what is happening here given what we learned above.

  1. transform_keys changes each of the hash's keys to a string and returns { "a" => 1, "b" => 2, "c" => 3 , "d" => 4}

  2. slice will select only keys "a" and "b" and their values and return { "a" => 1, "b" => 2 }

  3. reject will remove any key/value pair where the value is equal to 2, that leaves us with { "a" => 1 }

  4. Our final transform_values will change our hash's values into a string with "hi" and our number following it. The final result is {"a"=>"hi 1"}

BOOM!💥

You made it to the end!!! Hopefully you are feeling a little more comfortable with Ruby hashes now and have a couple more methods in your toolbox that you can use. If you have any questions or anything needs clarification please don't hesitate to drop a question in the comments!

If you want a quick reference for these methods I made a handy cheat sheetwith just the code from each example.

Ruby vs Ruby on Rails web framework

Rails is a development tool which gives web developers a framework, providing structure for all the code they write. The Rails framework helps developers to build websites and applications. Ruby is a programming language stronger than Perl and more object-oriented than Python. It is being developed with increasing productivity.

Ruby on Rails vs PHP

Ruby on Rails vs PHP

Understanding the pros and cons of Ruby on Rails versus PHP is important when deciding how to create your business-critical applications.

Originally published at https://www.engineyard.com

There’s more than one way to build a web application. No matter what type of application you are trying to create, your programmers have their preferred approach and their preferred code languages to accomplish the task. In the world of web applications, most program developers have to decide between Ruby on Rails versus PHP.

Ruby on Rails consists of Ruby, which is a scripting language, and Rails, which is a web development framework; PHP is a server-side scripting language. Both programming languages have been around since the mid-1990s, but PHP rules the web, while Ruby on Rails is more popular for business web applications. Understanding the pros and cons of Ruby on Rails versus PHP is important when deciding how to create your business-critical applications.

Ruby on Rails Versus PHP at First Glance

Both Ruby on Rails and PHP are open source, so there are no licensing fees. However, because PHP is used to run most of today’s web systems, there are more PHP programmers than Ruby developers, which means there is a larger pool of PHP experts and a larger open source library to draw from.

Part of the reason PHP is more popular with web developers is because it is easier to learn. PHP is also an object-oriented programming language, which makes it easier to be more creative and tackle tougher software challenges.

Once web developers master PHP, many of them choose to add Ruby on Rails to their expertise because of the advantages and power that Ruby on Rails offers for business application development. Ruby and Rails were created together to deliver web solutions, and the primary difference between PHP and Ruby on Rails is that Rails requires you to understand the full stack, including the web server, application server, and database engine.

Since both Ruby and PHP are open source, the support of the programming communities is an important differentiator. PHP has more deployments so it has a larger developer community, but the Ruby on Rails community is very skilled and enthusiastic and they want to share, so there is a growing library of ready-to-use Ruby gems.

Differences in Deployment

When it comes to deployment, PHP is very easy to implement. You simply transfer files to the web server via FTP and that’s it. With PHP, you don’t need to worry about the web stack. Most hosting services use a combination of open source for the stack, including Linux, Apache, MySQL, and PHP (LAMP), so once the files are loaded, they just run. That’s the advantage of server-side software.

Ruby on Rails is more complex to deploy because you have to know the full stack. That means knowing the details of the web server (e.g., Apache or NginX), as well as the database. You have to go through more steps, such as precompiling assets to make sure all the right files are there. This is the price of being able to design and deploy more complex applications.

Where Ruby on Rails really shines is in the software development process itself. Since Ruby is an object-intensive language, everything is an object, including classes and modules, with Rails providing an integrated test framework. PHP is not always object-oriented, so coding can be laborious and time-consuming. Applications can be built and tested in Ruby on Rails much faster than in PHP, so even if there is some debugging involved, Ruby on Rails dramatically reduces the time to deployment.

As noted above, PHP applications are relatively simple to deploy since there is no stack to worry about, and they are relatively inexpensive to host. Hosting Ruby on Rails applications is another story. Not all hosting providers will support Ruby on Rails, and those that do usually add additional a la carte fees because Ruby applications require more services.

The Business Case for Ruby on Rails versus PHP

While it’s clear that Ruby is a more difficult programming language to master, in many ways, it is a more robust language that is better suited for creating business applications. PHP was created specifically for the web, but Ruby on Rails offers much more.

For one thing, Ruby on Rails applications tend to be cleaner and more compact. Because PHP is so simple, it lends itself to sloppy coding that can be impossible to maintain. Ruby has the advantage of being more elegant and concise, and the documentation for Ruby applications tends to be generated with the code so anyone can make revisions or upgrades.

Most importantly, Ruby on Rails lends itself to agile software practices and rapid application development (RAD). Rails is a mature framework that allows programmers to create maintainable software, and it has integrated testing tools that shorten the developer cycle. When you consider the cost of talented programmers (and you know that time is money), reducing development time can mean substantial savings.

Depending on your business development needs, you may be leaning toward PHP or Ruby on Rails. Each has its strengths and weaknesses, but Ruby on Rails continues to gain popularity for business-critical and e-commerce applications because of its versatility, scalability, and upgradability. In the end, you have to consider which language will deliver a cleaner, more stable application that can evolve and grow with your business.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Learn More

PHP for Beginners - Become a PHP Master - CMS Project

Learn Object Oriented PHP By Building a Complete Website

PHP OOP: Object Oriented Programming for beginners + Project

Laravel PHP Framework Tutorial - Full Course for Beginners (2019)

Symfony PHP Framework - Full Course

What is a Full Stack Developer?

Build RESTful API In Laravel 5.8 Example

Laravel 5.8 Tutorial from Scratch for Beginners

Build a CRUD Operation using PHP & MongoBD

Build a CRUD Web App with Ruby on Rails

Ruby on Rails Tutorial for Beginners

How To Use PostgreSQL with Your Ruby on Rails Application on macOS

Python, Ruby, and Golang: A Command-Line Application Comparison