Skip to content

Instantly share code, notes, and snippets.

@maiha
Last active April 1, 2018 10:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maiha/284f59220cd3c1b588ddf84c1b115367 to your computer and use it in GitHub Desktop.
Save maiha/284f59220cd3c1b588ddf84c1b115367 to your computer and use it in GitHub Desktop.

active_record.cr - Active Record pattern implementation

  • ⚠️ activity last commit is 1 year ago
  • MySQL driver : libmysql(C API)
  • agnostic FREE
  • define fields simple
  • table name supports camel class name
  • model level query lacks first, count
  • low level adapter hard to access
  • relations
  • ⚠️ multibytes can't set charset in default (needs monkey patch)
  • pluck not supported yet
  • gateway pattern not supported yet
  • timestamps not supported yet
  • field access #foo returns Union(T, T::Null) with null object pattern
  • required field access #foo
  • nilable field access not supported yet
  • ⚠️ inspect class doesn't show column names
  • ⚠️ inspect record ugly
  • prepared statements uses : with hash, and returns Array(Array())

field access

  • Model#foo returns Union(T, T::Null) where T::Null is a null pattern object

usage

class User < ActiveRecord::Model
  adapter mysql
  primary id : Int
  field name : String
  field age  : Int
end

u = User.get(1)

u.name        # => "maiha"
u.name.class  # => String
u.name.upcase # => "MAIHA"
u.age         # => Null(struct)
u.age.class   # => Int::Null
u.age + 1     # => 1
u.age || -1   # => Null(struct)

p u
# #<User:0xaeeb60
#  @fields=
#   #<ActiveRecord::Model::Fields:0xaeeb40
#    @typed_fields=
#     {"Int" =>
#       #<ActiveRecord::Model::Fields::Generic(Int16 | Int32 | Int64 | Int8 | Int::Null | UInt16 | UInt32 | UInt64 | UInt8):0xaeeb20
#        @fields={"id" => 1_i64}>,
# ...

core - Pure, transparent and efficient ORM

crecto - Database wrapper, based on Ecto

granite-orm - ORM for Postgres, Mysql, Sqlite

  • activity HIGH
  • MySQL driver : crystal-mysql
  • agnostic controlled by Amber project
  • define fields simple
  • ⚠️ table name doesn't care camel class name (UserGroupusergroups)
  • adapter doesn't connect lazily (ENV["DATABASE_URL"] must be resolved in not runtime but class definitions)
  • model level query CRUD and count
  • relations
  • multibytes
  • pluck not supported yet
  • gateway pattern not supported yet
  • ⚠️ timestamps just a syntax sugar (names and types are fixed)
  • ⚠️ field access #foo returns T?
  • required field access #foo!
  • nilable field access #foo
  • ⚠️ inspect class doesn't show column names
  • inspect record pretty (but multiline)
  • prepared statements uses ? with array, and returns Array(MySql::ResultSet)
    • ❌ It's hard to operate MySql::ResultSet for arbitrary fields

usage

class User < Granite::ORM::Base
  adapter mysql
  field name : String
  field age  : Int32
end

u = User.create(name: "maiha")
# => "INSERT INTO `users` (`name`, `age`) VALUES (?, ?): ["maiha", nil]"
u.name.upcase # undefined method 'upcase' for Nil (compile-time type is (String | Nil))
u.name!.upcase # => "MAIHA"
u.name!.upcase # => "MAIHA"
u.age       # => nil
u.age || -1 # => -1
u.age!      # raises "User#age cannot be nil" (Exception)

jennifer.cr - Active Record pattern implementation

record - Type safe querying, saving and updating

topaz - A simple and useful db wrapper

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment