Micrate is recommended. It is used and supported by core crystal members.
Usage
First create a Repo. The Repo maps to the datastore and the database adapter and is used to run queries. You can even create multiple repos if you need to access multiple databases.
For those coming from Active Record: Repo provides a level of abstraction between database logic (Repo) and business logic (Model).
Let's create a repo for Postgres:
moduleRepoextendCrecto::Repo config do|conf| conf.adapter =Crecto::Adapters::Postgres# or Crecto::Adapters::Mysql or Crecto::Adapters::SQLite3 conf.database ="database_name" conf.hostname ="localhost" conf.username ="user" conf.password ="password" conf.port =5432# you can also set initial_pool_size, max_pool_size, max_idle_pool_size,# checkout_timeout, retry_attempts, and retry_delayendend
Define table name, fields, validations, and constraints in your model. By default, Crecto assumes your table has the following columns defined id, created_at, updated_at. These are in addition to whatever columns you decide to add.
Defining a new class using Crecto::Model:
classUser<Crecto::Model schema "users"do field :age,Int32# or use `PkeyValue` alias: `field :age, PkeyValue` field :name,String field :is_admin,Bool, default: false field :temporary_info,Float64, virtual: true field :email,String has_many :posts,Post, dependent: :destroyend validate_required [:name, :age] validate_format :name,/^[a-zA-Z]*$/ unique_constraint :emailend
If your schema doesn't require the default fields (id, created_at, updated_at), you can omit them.
classUserTags<Crecto::Model set_created_at_field nil# or you can set the name of your created_at field set_updated_at_field nil# ditto# primary_key: false tells the schema there's no `id` field schema "user_tags", primary_key: falsedo belongs_to :user,User belongs_to :tag,Tagendend
For a schema with an ID that is custom (UUID, Random String, etc...)
classComment<Crecto::Model schema "comments"do field :id,String, primary_key: true field :content,Stringendend
You can check out the spec/spec_helper.cr for more examples.
multi.insert(insert_user)multi.delete(post)multi.delete_all(Comment)multi.update(update_user)multi.update_all(User,Query.where(name: "stan"), {name: "stan the man"})multi.insert(new_user)
Insert the multi using a transaction
Repo.transaction(multi)
Check for errors
If there are any errors in any of the transactions, the database will rollback as if none of the transactions happened
multi.errors.any?
Non-nillable attributes
If you wish to access attributes of a model without having to check for nil, in the case that you are using a NOT NULLdatabase constraint you can use the non-nillable attribute accessors. CAUTION: Mis-use of this could lead to Nil reference runtime errors.
classUserArray<Crecto::Model schema "users_array"do field :string_array,Array(String) field :int_array,Array(Int32) field :float_array,Array(Float64) field :bool_array,Array(Bool)endenduser =UserArray.newuser.string_array = ["one","two","three"]Repo.insert(user)query =Query.where("? = ANY(string_array)","one")users =Repo.all(UserArray, query)
Database Logging
By default nothing is logged. To enable pass any type of IO to the logger. For STDOUT use:
Crecto::DbLogger.set_handler(STDOUT)
Write to a file:
f =File.open("database.log","w")f.sync =trueCrecto::DbLogger.set_handler(f)