Avram is the ORM Lucky uses for handling connections to your database, and wrapping the SQL mapping in a friendly Crystal class. An Object Relational Mapping or “ORM”, is a simple way to translate SQL queries, and table schema in to an easy to use object.
Avram currently only supports PostgreSQL with no current plans to support any other RDBMS. However, Lucky does not require you to use Avram if your requirements are a bit different.
Originally called “LuckyRecord”, the name change was decided because this ORM is not tied directly to the Lucky framework. You could choose to use it in any number of other Crystal frameworks. When deciding the name, we wanted something easily searchable, and meaningful. Thanks to all the suggestions from the community, we landed on Avram.
Henriette Avram was a computer programmer and systems analyst who developed the MARC format the international data standard for bibliographic and holdings information in libraries.
Every ORM will have a different pattern, and different set of tools included. With Avram, we took a
pattern breaking out where business logic is stored vs. where database queries are handled. This pattern
helps to keep code organized by it’s purpose within your application. This includes Models
, Queries
,
Operations
, Migrations
, and Factories
.
Avram’s models use classes to map each database table to a specific object. The naming convention for
each model is to be the singular word as where the table name is the plural form.
(e.g. User
model, and users
table.).
A model inherits from Avram::Model
; however, Lucky will generate an abstract class called BaseModel
for you to inherit from. This abstraction layer allows you to apply special callbacks, attributes,
or methods to all of your models.
Avram queries are classes that encompass querying the database. Once you have data in your database,
you’ll need a way to pull that data back out, and a Query class is that way! The naming convention
for these objects is to use the referencing model’s name followed by Query
.
(e.g. User
model UserQuery
query).
Query objects inherit from a subclass of the model called BaseQuery
. If you create a User
model,
Lucky will create a User::BaseQuery
class for you, and your UserQuery
object will inherit from that.
(e.g. UserQuery < User::BaseQuery
).
Avram operations are classes used for creating and updating records in the database.
Similar to the Query
object, these classes will inherit from a subclass of your model called
SaveOperation
. If you create a User
model, Lucky will create a User::SaveOperation
class for you.
(e.g. SaveUser < User::SaveOperation
).
The naming convention for operations is to use an action of what this object does like save a user record.
(e.g. User
model, SaveUser
operation).
You can think of migrations like git for your database. These are classes that are scoped with a timestamp to allow you to update your database in versions as well as undo changes that you’ve made previously while keeping track of the order you made them in.
Unlike the other files which live in your app’s src/
folder, these are located in the db/migrations/
folder.
Avram factories are classes that you can use for generating data quick. The most common use cases are when writing tests for your application, and when seeding your database with some default or placeholder data.
Factories inherit from Avram::Factory
and follow the naming convention using the name of the model they
reference followed by “Factory”. (e.g. User
model, UserFactory
factory) You’ll find these located in your app’s
spec/support/factories/
folder.
Even though Lucky uses Avram by default which only supports PostgreSQL, Lucky does not enforce the use of it. There may be cases where your application doesn’t even need a database (e.g. luckyframework.org).
If you want to take advantage of some of what Lucky has to offer, but your requirements need MySQL, SQLServer, or maybe something like RethinkDB / MongoDB, here’s a few tips to integrating those.
shard.yml
filesrc/models
directorysrc/app_database.cr
can be deleted to avoid confusionconfig/database.cr
file with the new adapter’s configuration settings# config/database.cr
class UnusedDB < Avram::Database
end
UnusedDB.configure do |settings|
settings.credentials = Avram::Credentials.void
end
Avram.configure do |settings|
settings.database_to_migrate = UnusedDB
end
# Configure your actual settings here
MyOtherAdapter.configure do |settings|
# Refer to that adapter's configuration guide
settings.url = "my_other_adapter_url"
end
db/migrations/
.If your app doesn’t need a database, you should still set the
AppDatabase
credentials setting toAvram::Credentials.void
. Avram Operations can still be quite useful for things like contact forms, or email subscribe forms. See this website for an example.