Description
DatabaseValidations helps you to keep the database consistency with better performance. Right now, it supports only ActiveRecord.
DatabaseValidations alternatives and similar gems
Based on the "Database Tools" category.
Alternatively, view DatabaseValidations alternatives based on common mentions on social networks and blogs.
-
Database Cleaner
Strategies for cleaning databases in Ruby. Can be used to ensure a clean state for testing. -
Large Hadron Migrator
Online MySQL schema migrations -
Seed dump
Rails 4/5 task to dump your data to db/seeds.rb -
Lol DBA
lol_dba is a small package of rake tasks that scan your application models and displays a list of columns that probably should be indexed. Also, it can generate .sql migration scripts. -
Active Record Doctor
Identify database issues before they hit production. -
Foreigner
Adds foreign key helpers to migrations and correctly dumps foreign keys to schema.rb -
Seed Fu
Advanced seed data handling for Rails, combining the best practices of several methods together. -
Squasher
Squasher - squash your old migrations in a single command -
Seedbank
Seedbank gives your seed data a little structure. Create seeds for each environment, share seeds between environments and specify dependencies to load your seeds in order. All nicely integrated with simple rake tasks. -
BatchLoader
:zap: Powerful tool for avoiding N+1 DB or HTTP queries -
DatabaseConsistency
The tool to avoid various issues due to inconsistencies and inefficiencies between a database schema and application models. -
SchemaPlus
SchemaPlus provides a collection of enhancements and extensions to ActiveRecord -
Polo
Polo travels through your database and creates sample snapshots so you can work with real world data in development. -
Upsert
Upsert on MySQL, PostgreSQL, and SQLite3. Transparently creates functions (UDF) for MySQL and PostgreSQL; on SQLite3, uses INSERT OR IGNORE. -
SecondBase
Seamless second database integration for Rails. -
OnlineMigrations
Catch unsafe PostgreSQL migrations in development and run them easier in production (code helpers for table/column renaming, changing column type, adding columns with default, background migrations, etc). -
FastPage
Blazing fast pagination for ActiveRecord with deferred joins ⚡️ -
QueryTrack
Find time-consuming database queries for ActiveRecord-based Rails Apps -
Shiba
Catch bad SQL queries before they cause problems in production -
Redis Dashboard
Sinatra app to monitor Redis servers. -
Ruby Whatsapp SDK
Empower your communication with Whatsapp using our Ruby-based Cloud API and SDK. With our easy-to-use Whatsapp API, you can quickly create custom bots and streamline messaging. Get started today and see the difference in your communication process. -
Ruby PG Extras
Ruby PostgreSQL database performance insights. Locks, index usage, buffer cache hit ratios, vacuum stats and more. -
PgDriveBackup
Simple solution to make encrypted with ccrypt PostgreSQL backups and storing on Google Drive API -
Slack Smart Bot
Create a Slack bot that is smart and so easy to expand, create new bots on demand, run ruby code on chat, create shortcuts... The main scope of this gem is to be used internally in the company so teams can create team channels with their own bot to help them on their daily work, almost everything is suitable to be automated!! slack-smart-bot can create bots on demand, create shortcuts, run ruby code... just on a chat channel. You can access it just from your mobile phone if you want and run those tests you forgot to run, get the results, restart a server... no limits. -
Perfect Shape
Perfect Shape is a collection of geometric algorithms that are mostly useful for GUI manipulation like checking containment of a point in popular geometric shapes such as rectangle, square, arc, circle, polygon, and paths containing lines, quadratic bézier curves, and cubic bezier curves. Also, some general math algorithms like IEEE-754 Remainder. -
ActiveRecord Setops
Union, Intersect, and Difference set operations for ActiveRecord (also, SQL's UnionAll). -
PgDice
Postgres partitioning built on top of https://github.com/ankane/pgslice -
ActiveRecord::DataIntegrity
Check data integrity for your ActiveRecord models -
Rapidity
Simple but fast Redis-backed distributed rate limiter. Allows you to specify time interval and count within to limit distributed operations. -
SlackHook
A Simple Interface to Slack Incoming Webhooks Integrations -
bundler-download
Bundler plugin for auto-downloading specified extra files after gem install
Static code analysis for 29 languages.
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of DatabaseValidations or a related project?
README
DatabaseValidations
DatabaseValidations helps you to keep the database consistency with better performance. Right now, it supports only ActiveRecord.
The more you use the gem, the more performance increase you have. Try it now!
Installation
Add this line to your application's Gemfile:
gem 'database_validations'
And then execute:
bundle
Or install it yourself as:
gem install database_validations
Have a look at [example](example) application for details.
Benchmark ([code](benchmarks/composed_benchmarks.rb))
Imagine, you have User
model defines as
class User < ActiveRecord::Base
validates :email, :full_name, uniqueness: true
belongs_to :company
belongs_to :country
end
and then replace with
class User < ActiveRecord::Base
validates :email, :full_name, db_uniqueness: true
# OR
# validates_db_uniqueness_of :email, :full_name
db_belongs_to :company
db_belongs_to :country
# OR
# belongs_to :company
# belongs_to :country
# validates :company, :country, db_presence: true
end
you will get the following performance improvement:
[](benchmarks/composed.png)
Caveats
db_belongs_to
doesn't work with SQLite due to a poor error message.- In Rails 4, the gem validations work differently than the ActiveRecord ones when
validate: false
option is passed tosave
/save!
. They incorrectly return a validation message instead of raising a proper constraint violation exception. In Rails >= 5 they correctly raise the exceptions they supposed to.
db_belongs_to
Supported databases are PostgreSQL
and MySQL
.
Note: Unfortunately, SQLite
raises a poor error message
by which we can not determine exact foreign key which raised an error.
Usage
class User < ActiveRecord::Base
db_belongs_to :company
end
user = User.create(company_id: nil)
# => false
user.errors.messages
# => {:company=>["must exist"]}
Problem
ActiveRecord's belongs_to
has optional: false
by default. Unfortunately, this
approach does not ensure existence of the related object. For example, we can skip
validations or remove the related object after we save the object. After that, our
database becomes inconsistent because we assume the object has his relation but it
does not.
db_belongs_to
solves the problem using foreign key constraints in the database
also providing backward compatibility with nice validations errors.
Pros and Cons
Advantages:
- Ensures relation existence because it uses foreign keys constraints.
- Checks the existence of proper foreign key constraint at the boot time.
Use
ENV['SKIP_DB_UNIQUENESS_VALIDATOR_INDEX_CHECK'] = 'true'
if you want to skip it in some cases. (For example, when you run migrations.) - It's almost two times faster because it skips unnecessary SQL query. See benchmarks below for details.
Disadvantages:
- Cannot handle multiple database validations at once because database raises only one error per query.
Configuration options
Option name | PostgreSQL | MySQL |
---|---|---|
class_name | + | + |
foreign_key | + | + |
foreign_type | - | - |
primary_key | + | + |
dependent | + | + |
counter_cache | + | + |
polymorphic | - | - |
validate | + | + |
autosave | + | + |
touch | + | + |
inverse_of | + | + |
optional | - | - |
required | - | - |
default | + | + |
Benchmarks ([code](benchmarks/db_belongs_to_benchmark.rb))
[](benchmarks/db_belongs_to.png)
validates_db_uniqueness_of
Supported databases are PostgreSQL
, MySQL
and SQLite
.
Usage
class User < ActiveRecord::Base
validates :email, db_uniqueness: true
# The same as following:
# validates :email, uniqueness: {case_sensitive: true, allow_nil: true, allow_blank: false}
end
original = User.create(email: '[email protected]')
dupe = User.create(email: '[email protected]')
# => false
dupe.errors.messages
# => {:email=>["has already been taken"]}
User.create!(email: '[email protected]')
# => ActiveRecord::RecordInvalid Validation failed: email has already been taken
Complete case_sensitive
replacement example (for PostgreSQL
only):
validates :slug, uniqueness: { case_sensitive: false, scope: :field }
Should be replaced by:
validates :slug, db_uniqueness: {index_name: :unique_index, case_sensitive: false, scope: :field}
Keep in mind: because valid?
method uses default validator you should:
- if your index has many fields, provide proper
scope
option - if your index has lower function, provide
case_sensitive
option - if your index has where condition, provide proper
where
option
Problem
Unfortunately, ActiveRecord's validates_uniqueness_of
approach does not ensure
uniqueness. For example, we can skip validations or create two records in parallel
queries. After that, our database becomes inconsistent because we assume some uniqueness
over the table but it has duplicates.
validates_db_uniqueness_of
solves the problem using unique index constraints
in the database also providing backward compatibility with nice validations errors.
Advantages
- Ensures uniqueness because it uses unique constraints.
- Checks the existence of proper unique index at the boot time.
Use
ENV['SKIP_DB_UNIQUENESS_VALIDATOR_INDEX_CHECK'] = 'true'
if you want to skip it in some cases. (For example, when you run migrations.) - It's two times faster in average because it skips unnecessary SQL query. See benchmarks below for details.
- It has different modes so you can pick up the best for your needs.
Configuration options
Option name | PostgreSQL | MySQL | SQLite |
---|---|---|---|
mode | + | + | + |
scope | + | + | + |
message | + | + | + |
if | + | + | + |
unless | + | + | + |
index_name | + | + | - |
where | + | - | - |
case_sensitive | + | - | - |
allow_nil | - | - | - |
allow_blank | - | - | - |
Modes
There are 3 mode
options:
:optimized
- the default one. In this mode it turns DB constraint exceptions into proper validation messages.:enhanced
- a combination of the standard uniqueness validation and the db uniqueness validation. Runs a query first but also rescues from exception. The preferable mode for user-facing validations.:standard
- in this mode works pretty much the same way asvalidates_uniqueness_of
(except the index existence check).
Benchmark ([code](benchmarks/uniqueness_validator_benchmark.rb))
[](benchmarks/validates_db_uniqueness_of.png)
Testing (RSpec)
Add require database_validations/rspec/matchers'
to your spec
file.
validate_db_uniqueness_of
Example:
class User < ActiveRecord::Base
validates_db_uniqueness_of :field, message: 'duplicate', where: '(some_field IS NULL)', scope: :another_field, index_name: :unique_index
end
describe 'validations' do
subject { User }
it { is_expected.to validate_db_uniqueness_of(:field).with_message('duplicate').with_where('(some_field IS NULL)').scoped_to(:another_field).with_index(:unique_index) }
end
Using with RuboCop
DatabaseValidations provides custom cops for RuboCop to help you consistently apply the improvements.
To use all of them, use rubocop --require database_validations/rubocop/cops
or add to your .rubocop.yml
file:
require:
- database_validations/rubocop/cops
Or you case use some specific cop directly:
require:
- database_validations/rubocop/cop/belongs_to
- database_validations/rubocop/cop/uniqueness_of
Development
You need to have installed and running postgresql
and mysql
.
And for each adapter manually create a database called database_validations_test
accessible by your local user.
Then, run rake spec
to run the tests.
To check the conformance with the style guides, run:
rubocop
To run benchmarks, run:
ruby -I lib benchmarks/composed_benchmarks.rb
To install this gem onto your local machine, run bundle exec rake install
.
To release a new version, update the version number in version.rb
, and then
run bundle exec rake release
, which will create a git tag for the version,
push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the DatabaseValidations project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
Contributors
*Note that all licence references and agreements mentioned in the DatabaseValidations README section above
are relevant to that project's source code only.