How Its Made: MongoDB Compass Export to Ruby Language
Tags: ruby, mongodb, bson, beginners
Published: 2022-01-24 19:56:52

Looking for something truly useful for learning MongoDB? Imagine being able to construct a MongoDB query via the [MongoDB Compass](https://www.mongodb.com/products/compass) UI while exploring your data, then exporting that same query to the programming language of your choice.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gz9v0cfgnxyuqhup36k0.png)

In today's "How Its Made", MongoDB Engineer [Neil Shweky](https://github.com/Neilshweky) explains how he recently built out this feature for Ruby. 

Getting this functionality working required that Ruby be added as an output language to our [BSON Transpilers](https://github.com/mongodb-js/compass/tree/main/packages/bson-transpilers) project. As an aside, if you spent a lot of time in university (or just for fun) with compilers, parsers, and other fun functional-programming-related problems, this is a project for you. 

Our BSON transpilers enable users to convert a MongoDB query from one programming language to another via a YAML template file that specifies how to generate code for the specific language in a variety of situations. For example, if the output language is Python and the input code is `'3 in [1,2,3]'` the following template is used to generate equivalent Ruby code:

```
InSyntaxTemplate:
(lhs, op, rhs) => {
  let str = '';
  if (op.includes('!') || op.includes('not')) {
    str = '!';
  }
  return${str}${rhs}.include?(${lhs})
}
```

This template takes in an `lhs` value of `3` and a `rhs` value of `[1,2,3]`. The equivalent Ruby code that is then generated to test for array membership would be:

```ruby
[1, 2, 3].include?(3)
```

The first step in this process was to complete a series of tests which would evaluate a code statement from an input language and output it to Ruby. Then to take those learnings and complete the templates in the ruby template file.


Simple enough, right?

The most difficult part of this work was making decisions on what code is considered _idiomatic to Ruby._ The Ruby language offers so many ways to express the same concepts, however our goal was to choose the ideal way that would make sense to Ruby developers. As an example, assignment of a key/value pair to a [Hash](https://ruby-doc.org/core-3.1.0/Hash.html) of `{ x: 1 }` can be done multiple different ways:

1. `{ x: 1 }`
2. `{ :x => 1 }`
3. `{ :'x' => 1 }`
4. `{ 'x': 1 }`
5. `{ 'x' => 1 }`

Well...

Eagle-eyed Rubyists will note that the keys above vary between being [Symbols](https://ruby-doc.org/core-3.1.0/Symbol.html) and [Strings](https://ruby-doc.org/core-3.1.0/String.html) so it's not technically "5 different ways of assigning _exactly the same thing_", but we chose this example to illustrate the flexibility the Ruby language offers. At the end of the day, we opted to use the last option, because we felt like this would "look right" to most Ruby developers.

Results in the Compass UI:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iuy88xlvl48cb4w4hq4e.png)

For future enhancements, we are thinking about adding Ruby as an input language. This would allow a user to convert queries written in Ruby to any of the other languages we have implemented such as Java, C#, Javascript, Python, with Golang and even Rust.

The next time you're [exporting your query](https://docs.mongodb.com/compass/current/export-query-to-language/) from within MongoDB Compass give Ruby a try and let us know what you think. If you're curious how all this works the [repo for MongoDB Compass](https://github.com/mongodb-js/compass) is available for exploration.

-- Rachelle, Product Lead for Developer Experience

P.S. Neil is also on [twitter](https://twitter.com/neil_shweky) and [devto](https://dev.to/neilshweky)