Rails application with NoSQL Database
A default Rails application is typically built with a relational database, such as PostgreSQL or MySQL, as its default data store. Building a Rails application with a NoSQL database can bring some benefits.
As an opinionated framework, it makes the assumption that there is a “best” way to do things, and it’s designed to encourage that way - and in some cases to discourage alternatives.
This quote is extracted from the Rails documentation, and one could infer that an application diverging from the conventional use of ActiveRecord might not be widely embraced as a viable alternative.
Many Rails applications use non-relational databases in isolated operations, the most famous among them being Redis which offers good performance and high availability.
Database choice is rooted in the structure of Rails itself, it makes querying overall easy and smooth with ActiveRecord as the default ORM. However, we can choose to build a Rails application with a NoSQL database and several key distinctions arise.
NoSQL database options:
NoSQL databases do not serve all purposes due to certain limitations. They often prioritize performance and scalability over strict consistency, making them less suitable for applications that demand absolute data accuracy and adherence to ACID (Atomicity, Consistency, Isolation, Durability) properties, such as financial systems. The absence of strict schemas may lead to potential data integrity issues in applications where a well-defined structure is crucial.
-
MongoDB MongoDB is a NoSQL database program that operates seamlessly across multiple platforms, focusing on high performance, availability, and automatic scalability. It utilizes flexible, JSON-like documents to store data, accommodating diverse fields and data structures. Well-suited for managing extensive volumes of unstructured and semi-structured data, MongoDB stands out for its adaptability.
-
CouchDB Document-oriented database designed for flexible and schema-free data storage. Utilizing a distributed architecture with bi-directional replication, it allows for scalable and fault-tolerant deployments across multiple nodes. With a RESTful API, ACID properties, and support for MapReduce views, CouchDB provides an accessible and robust solution for applications requiring flexible data modeling, decentralized storage, and seamless synchronization in distributed environments.
-
Redis Redis, short for Remote Dictionary Server, serves as an open-source, in-memory data structure store, functioning as a versatile database, cache, and message broker. It boasts support for diverse data structures, including strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, and geospatial indexes equipped with radius queries. With features like high availability, persistence, and automatic partitioning, Redis guarantees swift and dependable performance.
-
Cassandra Apache Cassandra stands out as a massively scalable, distributed, and high-performance NoSQL database management system crafted to efficiently manage extensive data loads across numerous commodity servers. It ensures high availability by eliminating single points of failure. Operating as a wide column store, Apache Cassandra stores data in columns rather than rows, making it exceptionally adept at handling write-intensive workloads and time-series data.
Originally developed at Facebook, Cassandra is now an open-source project under the Apache Software Foundation, and it is used by many large-scale enterprises such as Netflix, Apple, and eBay.
From this list of 4 presented previously, it would be possible to choose MongoDB and CouchDB as options to replace Rails relational databases with ActiveRecord. Redis and Cassandra are key-value store like, so they would not be very good at replacing SQL databases for ActiveRecord.
Due to ease of implementation and extensive documentation, in this blog post we will consider replacement of a relational database with a MongoDB database.
Why would my project use NoSQL instead of default ActiveRecord?
Short answer is: it mainly depends on your project's needs
.
- Schema Flexibility:
- SQL Rails Application: Utilizes a predefined schema that governs the structure of the database. Any change will require a new migration of the database.
- MongoDB Rails Application: Offers schema flexibility, allowing developers to add fields to documents on-the-fly without the need for predefined structures. This flexibility is particularly beneficial when dealing with dynamic or evolving data models.
- Scalability:
- SQL Rails Application: A relational database usually scales vertically (adding more power to a single server), it can also be done horizontally with database sharding and partitioning.
- MongoDB Rails Application: Easily scales horizontally by distributing data across multiple servers, making it easier to handle large amounts of data and increasing performance as the application grows.
- Complex Relationships:
- SQL Rails Application: Handles complex relationships through associations and foreign keys, which can lead to potential performance bottlenecks.
- MongoDB Rails Application: Document-based databases natively supports hierarchical and nested data structures, simplifying the representation of complex relationships without the need for join tables.
- Document-Oriented Storage:
- SQL Rails Application: Organizes data in tables with rows and columns.
- MongoDB Rails Application: Stores data in a document-oriented format, which is particularly advantageous for applications dealing with JSON-like or semi-structured data.
One of the primary factors leading projects to switch between NoSQL and SQL databases, or vice versa, is performance. It’s a key consideration and it can be highly advantageous in different scenarios for both types of databases.
While it’s possible to directly compare two SQL databases with a set of standard SQL benchmarks, achieving the same across non-relational and relational databases is much more difficult and subjective.
There’s some good information about this difference in this MongoDB vs. MySQL Differences blog post by MongoDB.
How to
When building a new Rails application you can skip ActiveRecord using the following command in your terminal:
rails new blog --skip-active-record
This option tells Rails not to include ActiveRecord as the default ORM for database interactions. By excluding ActiveRecord, you can opt for alternative database solutions or choose a NoSQL database.
For not-new Rails application, check your settings, examine config/application.rb
. If it is requiring all components of Rails via require rails/all
, to not use ActiveRecord you will need to change it to require individual frameworks and remove it.
# config/application.rb
# Remove or comment out
#require "rails/all"
# Add the following instead of "rails/all":
require "rails"
# require "active_record/railtie" rescue LoadError
# require "active_storage/engine" rescue LoadError
require "action_controller/railtie" rescue LoadError
require "action_view/railtie" rescue LoadError
require "action_mailer/railtie" rescue LoadError
require "active_job/railtie" rescue LoadError
require "action_cable/engine" rescue LoadError
# require "action_mailbox/engine" rescue LoadError
# require "action_text/engine" rescue LoadError
require "rails/test_unit/railtie" rescue LoadError
ActionText, ActiveStorage and ActionMailbox cannot be used due to their reliance on ActiveRecord.
Once your Rails application is ready to deal with a different database, you might want to use a gem to do something close to what ActiveRecord does for you.
Overviewing MongoID gem
MongoID is the officially supported object-document mapper (ODM) for MongoDB in Ruby. MongoID is a gem specifically developed for MongoDB. Unlike ActiveRecord, MongoID focuses on schema-less, JSON-like documents and supports dynamic queries and flexible data models.
MongoID integrates with Rails pretty smoothly and has some similarities with Rails and ActiveRecord settings. A config/mongoid.yml
file is used to store DB information, at the models layer it uses include Mongoid::Document
as a replacement to an inheritance from the ActiveRecord::Base
object, and as it has a flexible schema it requires the fields to be explicitly defined at the models.
class Post
include Mongoid::Document
field :title, type: String
field :body, type: String
has_many :comments, dependent: :destroy
end
This gem is highly maintained and has a clear and readable way to do queries , and many other things, like ActiveRecord does.
Conclusion
Rails is an opinionated framework, it makes the assumption that there is a “best” way to do things, and it’s designed to encourage that way - and in some cases to discourage alternatives.
Applications that deal with rapidly changing data structures, or have predominantly read-heavy workloads may find solution building something using NoSQL databases. However, the choice between a default Rails application and a NoSQL-based one ultimately depends on the specific needs and characteristics of the project at hand.
Schema flexibility is particularly beneficial in scenarios where the data model evolves frequently or when dealing with varying data structures across different parts of the application. It empowers developers to adapt the database schema on-the-fly, offering greater agility in response to changing application requirements.
Need help with your Rails application? Whether you use a relational or NoSQL database, we can help! Send us a message!