All Versions
Latest Version
Avg Release Cycle
93 days
Latest Release
1302 days ago

Changelog History

  • v0.9 Changes

    November 22, 2020


    I'm pleased to announce the version 0.9 of Crystal Clear ORM !
    ๐Ÿš€ This version is probably the biggest version released since Clear is born.

    โœ… Under the hood, it simplifies a lot of code, push testing to another level with
    a great amount of new specs.

    ๐Ÿ‘ On the feature part, it add full support for serializing to and from json, with mass assignment secure check, big decimal
    ๐Ÿ‘ type, PostgreSQL view management at migration, new callbacks methods, support for postgres interval object and so on...

    ๐Ÿš€ Finally, the code has been tweaked to be compatible with release of Crystal 1.0.

    With that in mind, Clear starts to mature, with only CLI, polymorphic relations and model inheritance still lacking.

    โš  Note of warning: some changes will break your code. However everything can be fixed in matter of minutes (hopefully)

    Special thanks to all contributors of this version:

    @007lva @anykeyh @GabFitzgerald @dukeraphaelng @mamantoha @watzon @yujiri8

    (hopefully I did not forget someone)

    ๐Ÿ’ฅ Breaking changes

    Clear::SQL::ConnectionPool now returns DB::Connection instead of DB::Database (fix #177)

    Clear::Migration::Direction is now an enum instead of a struct.

    where and having clauses use splat and named tuple always. This is breaking change.

    • Before you had to do:

      where("a = ?", [1])

    Now you can do much more easy:

     where("a = ?", 1)

    Same apply for the named parameters version:

    # Instead of where("a = :a", { a: 1 } ) # Do where("a = :a", a: 1)

    ๐Ÿ”‹ Features

    • ๐Ÿ”’ PR #187 Add methods to import from and to json, with mass_assignment security
      (thanks @dukeraphaelng and Caspian Baska for this awesome work!)
    • ๐Ÿ‘ PR #191 Add Big Decimal support (@dukeraphaelng)
    • Collection#add_operation has been renamed to Collection#append_operation
    • โž• Add Clear::SQL.after_commit method

    Register a callback function which will be fired once when SQL COMMIT
    operation is called

    This can be used for example to send email, or perform others tasks
    when you want to be sure the data is secured in the database.

     transaction do@user = User.find(1) @user.subscribe! Clear::SQL.after\_commit{ Email.deliver( } end

    โช In case the transaction fail and eventually rollback, the code won't be called.

    Same method exists now on the model level, using before and after hooks:

    class Userinclude Clear::Model after(:commit){ |mdl|\_now } end

    Note: before(:commit) and after(:commit) are both called after the transaction has been commited.
    Before hook always call before after hook.

    • โž• Add possibility to name and rollback to a specific savepoint:

      Clear::SQL.with_savepoint("a") doClear::SQL.with_savepoint("b") doClear::SQL.rollback("a") # < Exit to "a"endputs "This won't be called"endputs "This will be called"

    • Add Clear.json_serializable_converter(CustomType)

    This macro help setting a converter transparently for any CustomType.
    Your CustomType must be JSON::Serializable, and the database column
    must be of type jsonb, json or text.

    class Colorinclude JSON::Serializable @[JSON::Field]; property r: Int8 @[JSON::Field]; property g: Int8 @[JSON::Field]; property b: Int8 @[JSON::Field]; property a: Int8endClear.json\_serializable\_converter(Color) # Now you can use Color in your models:class MyModelinclude Clear::Model column color : Colorend
    • โž• Add jsonb().contains?(...) method

    This allow usage of Postgres ? operator over jsonb fields:

    # SELECT \* FROM actors WHERE "jsonb\_column"-\>'movies' ? 'Top Gun' LIMIT 1;Actor.query.where{ var("jsonb\_column").jsonb("movies").contains?("Top Gun") }.first!.name # \<\< Tom Cruise
    • Add SelectQuery#reverse_order_by method

    A convenient method to reverse all the order by clauses,
    turning each ASC to DESC direction, and each NULLS FIRST to NULLS LAST

    ๐Ÿ›  Bugfixes

    • Prepare the code to make it compatible with crystal 1.0. Change Void to Nil
    • first and last on collection object does not change the collection anymore (previously would add limit/offset and change order_by clauses)
    • โœ… Dozen of other bugs not tracked here have been fixed, by usage or new test sets.
  • v0.8 Changes

    February 02, 2020

    This version fix a lot of small things:

    • ๐Ÿ›  Fix TimeInDay issues
    • ๐Ÿ›  Fix issue when using DISTINCT with JOIN in models with custom SELECT
      clause defined AFTER the joins.
    • ๐Ÿ›  Fix mistake in spec and add specs
    • โž• Add changelog; update shard
    • โž• Add seed command in the CLI
    • โž• add or_where feature
    • ๐Ÿ›  Fix FTS to remove ambiguous clauses
    • ๐Ÿ›  Fix issue with nilable belongs_to which cannot be saved when set to nil
    • โž• Add RFC3339 support while converting string to time
    • ๐Ÿ›  Fix caching with belongs_to
    • โž• Add colorize parameter to Clear::SQL::Logger module
    • Migration: Add datatype conversion in add_column and alter_column methods
    • โšก๏ธ Migration: Update migration add_column operation to allow contraints, nullable
      0๏ธโƒฃ and default value
    • โšก๏ธ Update to latest version of pg gem
    • Fix ambigous column name in with_xxx method for belongs_to relation
    • โž• Add possibility to have nulls first and nulls last in order_by method
    • ๐Ÿšง WIP on a SQL parser
    • โž• Add the possibility to convert from Array(JSON:Any)
    • ๐Ÿ›  Fix misc typos
  • v0.7.2 Changes

    October 02, 2019


    • This version migrates the code of v0.7.1 to crystal 0.31.1
  • v0.7.1 Changes

    September 24, 2019
    • ๐Ÿ›  Minor bug fixes from 0.7
  • v0.7 Changes

    May 28, 2019


    ๐Ÿ”‹ Features

    • โž• Add Clear::Interval type

    This type is related to the type Clear::Interval of PostgreSQL. It stores month, days and microseconds and can be used
    with Time (Postgres' datetime) by adding or substracting it.


    Usage in Expression engine:

    interval = 1, days: 1)MyModel.query.where{ created\_at - interval \> updated\_at }.each do |model| # ...end

    ๐Ÿšš It might be used as column definition, and added / removed to crystal Time object

    class MyModelinclude Clear::Model column i : Clear::Intervalendputs "Expected time: #{ + MyModel.first!.i}"
    • โž• Add Clear::TimeInDay columns type, which stands for the time object in PostgreSQL.


    Usage as stand alone:

    time = Clear::TimeInDay.parse("12:33")puts time.hour # 12puts time.minutes # # Today at\_s #\_s(false) # don't show seconds =\> 12:33time = time + 2.minutes #12:35

    As with Interval, you might wanna use it as a column (use underlying time type in PostgreSQL):

    class MyModelinclude Clear::Model column i : Clear::TimeInDayend

    ๐Ÿ› Bug fixes

  • v0.6 Changes

    February 25, 2019


    v0.6 should have shipped polymorphic relations, spec rework and improvement in
    ๐Ÿ“š documentation. That's a lot of work (honestly the biggest improvement since v0)
    ๐Ÿ‘ and since already a lot of stuff have been integrated, I think it's better to
    ๐Ÿš€ ship now and prepare it for the next release.

    ๐Ÿ‘€ Since few weeks I'm using Clear in a full-time project, so I can see and correct
    many bugs. Clear should now be more stable in term of compilation and should not
    crash the compiler (which happened in some borderline cases).

    ๐Ÿ”‹ Features

    ๐Ÿ“š Release of a guide and documentation to use Clear:

     json = JSON.parse(%({"first\_name": "John", "last\_name": "Doe", "tags": ["customer", "medical"] }))

    โž• Add of pluck and pluck_col methods to retrieve one or multiple column in a Tuple,
    which are super super fast and convenient!

    โž• Add Clear.with_cli method to allow to use the CLI in your project. Check the documentation !

    โž• Additional comments in the source code

    SelectQuery now inherits from Enumerable(Hash(String, Clear::SQL::Any))

    โž• Add optional block on Enum definition. This allow you to define custom methods for the enum:

    Clear.enum ClientType, "company", "non\_profit", "personnal" dodef pay\_vat? self == Personnalendend

    โž• Add ? support in raw method:

     a = 1 b = 1000 c = 2 where{ raw("generate\_series(?, ?, ?)", a, b, c) }

    [EXPERIMENTAL] Add << operation on collection which comes from has_many and has_many through:

    [EXPERIMENTAL] Add unlink method on collection which comes from has_many through:

    [EXPERIMENTAL] Add possibility to create model from JSON:

    ๐Ÿ’ฅ Breaking changes

    • ๐Ÿšš Migration: use of table.column instead of table.${type} (remove the method missing method); this was causing headache
      in some case where the syntax wasn't exactly followed, as the error output from the compiler was unclear.
    • Renaming of with_serial_pkey to primary_key; refactoring of the macro-code allowing to add other type of keys.
    • Now allow text, int and bigint primary key, with still the uuid, serial and bigserial primary keys available.
    • Renaming of Clear::Model::InvalidModelError to Clear::Model::InvalidError and Clear::Model::ReadOnlyError to
      Clear::Model::ReadOnly to simplify as those classes are already in the Clear::Model namespace
    • ๐Ÿ‘€ Model#set methods has been transfered to Model#reset, and Model#set now change the status of the column to dirty. (see #81)

    ๐Ÿ› Bug fixes

  • v0.5 Changes

    December 24, 2018

    ๐Ÿฑ v0.5: Merry christmas ๐ŸŽ„

    ๐Ÿ”‹ Features

    Connection pool

    ๐Ÿ›  Clear wasn't fiber-proof since it lacks of connection pool system. It's now fixed, the connection pooling is done
    completely transparently without any boilerplate on your application side.

    Each fiber may require a specific connection; then the connection is binded to the fiber. In the case of transaction
    and with_savepoint, the connection is kept until the end of the block happens.
    On the case of normal execution or cursors, we store the connection until the execution is done.

    The connection pool is using Channel so in case of pool shortage, the fiber requesting the connection is put in
    waiting state.

    This is a huge step forward:

    • Clear can be used in framework with spawn-based server and other event machine system.
    • ๐ŸŽ I'll work on performance improvement or other subtilities in some specific cases, where multiple requests can be
      parallelized over different connections.

    ๐Ÿ› Bug fixes

    • ๐Ÿ›  Fix #53
    • โšก๏ธ Update ameba to latest version
    • ๐Ÿ”จ Large refactoring on relations
    • ๐Ÿ›  Many bugfixes
  • v0.4 Changes

    November 12, 2018

    ๐Ÿ”‹ Features

    • #48 Add lateral join feature:

      Model.query.left_join("other_model", lateral: true){ == other_model.model_id }

    • #35 Add methods import over collection, to be able to insert multiple objects with one query:

      user_array ={ |x| "user#{x}") } Model.import(user_array)

    • ๐Ÿ‘ #42 Add support of ON CONFLICT both in Insert and Model#save

      u = 1, first_name: "me")! &.on_conflict("(id)").do_update(&.set("first_name = excluded.first_name").where { == })

      • Note: Method Model#import explained above can use the same syntax to resolve conflict.
        This will helps to use Clear for import, CSV and batch processing.
    • ๐Ÿ‘ #26 Add to_json supports to model. Please note that some core lib and shards pg objects got
      ๐Ÿ‘ extended to allow this support:

      • By default, undefined fields are not exported. To export all columns even thoses which are not fetched in SQL, use full: true. For example:

      User.query.first!.to_json # => {"id":1, "first_name":"Louis", "last_name": "XVI"}"id, first_name").first!.to_json # => {"id":1, "first_name":"Louis"}"id, first_name").first!.to_json(full: true) # => {"id":1, "first_name":"Louis", "last_name": null}

    ๐Ÿ› Bug fixes

    • Escaping table, columns and schema name to allow Clear to works on any SQL restricted names.
      • This is very demanding work as it turns out table and columns naming are used everywhere
        in the ORM. Please give me feedback in case of any issues !
    • ๐Ÿ›  Fix #31, #36, #38, #37
    • ๐Ÿ›  Fix issue with polymorphic table

    ๐Ÿ’ฅ Breaking changes

    • Renaming insert method on InsertQuery to values, making API more elegant.
    • Usage of var in Expression engine has been changed and is now different from raw:

      • var provide simple way to construct [schema].table.field structure,
        with escaped table, field and schema keywords.
      • raw works as usual, printing the raw string fragment to you condition.
      • Therefore:

      where{ var("a.b") == 1 } # Wrong now! => WHERE "a.b" = 1# Must be changed by: where{ var("a", "b") == 1 } # OR where{ raw("a.b") }

    TL;DR, if you currently use var function, please use raw instead from now.

    • ๐Ÿ‘€ Revamping the converter system, allowing to work seemlessly with complexes types like Union and Generic
      • Documentation will follow soon.
  • v0.3.1 Changes

    November 04, 2018

    ๐Ÿ”‹ Features

    • ๐Ÿ‘Œ Improved Model build/create methods, allowing to pass arguments instead of NamedTuple
    • โž• Add supports to Crystal 0.27

    ๐Ÿ› Bug fixes

    • Escaping table, columns and schema name to allow Clear to works on any SQL restricted names.
    • ๐Ÿ›  Fix #31, #36, #37
    • ๐Ÿ›  Fix issue with polymorphic table
  • v0.3 Changes

    August 09, 2018

    ๐Ÿ”‹ Features

    • โž• Add support to pg Enum
    • โž• Add support for UUID primary key, with uuid autogeneration
    • โž• Add support for BCrypt fields, like passwords
    • Finalization of CLI !
    • โž• Add Clear.seed(&block)
      ๐Ÿ‘€ Clear.seed goes in pair with bin/clear migrate seed which will call the seed blocks.
    • โž• Add possibility to use has_many through without having to declare the model doing the relation
      For example, if A belongs to B, B belongs to C, then A has_many C through B. You can
      ๐Ÿ‘€ perform this now without declaring any class for B; see the guide about relations for
      more informations.
    • โž• Add error messages so cool you want your code to crash ๐Ÿ˜‰

    ๐Ÿ› Bug fixes

    • ๐Ÿ›  Fix #23 bug with has_many through: and select
    • โž• Add support for DISTINCT ON feature.
    • Array(String), Array(Int64) columns type are working now works

    ๐Ÿ’ฅ Breaking changes

    • ๐Ÿ‘ป Model#save on read only model do not throw exception anymore but return false (save! still throw error)
    • with_serial_pkey use Int32 (type :serial) and Int64 (type :longserial) pkey instead of UInt32 and UInt64. This would prevent issue with default belongs_to behavior and simplify static number assignation.