Jennifer.cr Versions Save

Crystal ORM using ActiveRecord pattern with flexible query DSL

v0.8.0

4 years ago

It has been a long time since previous release but expectation is worth it. 0.8.0 release brings a lot of new features such as:

  • extended model mapping
    • new properties to configure sql column name and autoincrementability of primary key
    • opportunity to define mapping in modules and abstract super classes
  • Model.new now respects after_initialize callbacks
  • unify mapping for model and view
  • extended querying functionality
    • make SQL API more natural
    • support of upsert operation
    • add CTE

Also a lot of bugs were fixed and performance enhancements were made.

API documentation is hugely increased so now almost all places are covered.

Changelog

General

  • by default db:migrate task outputs information about executed migrations
  • db:create command doesn't fail if database already exists

QueryBuilder

  • remove redundant Criteria#similar which is loaded with postgres adapter
  • add Query#insert and Query#upsert
  • add ExpressionBuilder#values and Values to reference to VALUES statement in upsert
  • .find_by_sql and .to_a of ModelQuery(T) use T.new instead of T.build
  • add CommonTableExpression to present SQL CTE
  • rename EagerLoading#with to #with_relation
  • #last! and #last assigns old limit value back after request instead of additional #reverse_order call
  • speed up Query allocation by making all query part containers nilable
  • add 2nd argument to Query#union setting union to be UNION ALL
  • now Query#with presents API for registering common table expression
  • add Query#merge
  • Query#where yields expression builder
  • Query's #join, #right_join, #left_join and #lateral_join yield expression builders of a main query and joined context
  • add next SQL functions: count, sum, avg, min, max, coalesce and concat_ws sql functions
  • round function now accepts second optional argument specifying precision
  • Function's #operands_to_sql and #operand_sql now are public
  • Function.define macro accepts comment key to specify function class documentation comment
  • Function.define macro arity argument by default is 0 (instead of -1)
  • add ExpressionBuilder#cast
  • handle an empty array passed to Criteria#in
  • fix missing LIMIT in query generated by #first!
  • fix result type of Executables#exists? query method to Bool (thanks @skloibi)
  • add Executables#explain

Model

  • Base.new now calls after_initialize hooks and supports STI
  • Base.build now is alias for Base.new
  • properties passed to Mapping.mapping now is parsed before main mapping macro is executed
  • #append_{{relation_name}} methods of RelationDefinition now use .new to build a related object
  • Resource::Supportable alias is removed
  • Resource.search_by_sql is removed in favour of Resource.all.find_by_sql
  • fix bug with ignoring of field converter by a STI child
  • fix default constructor for STI child - now it is generated if parent model has only type field without default value
  • allow mapping option column that defines a custom column name that is mapped to this field (thank @skloibi)
  • Base#table_name is moved to Resource
  • Mapping module now can be included by another module with mapping definition
  • STIMapping now doesn't convert result set to hash and use same logic as Mapping
  • add :auto mapping option to specify whether primary key is autoincrementable

Validation

  • change Validations::Uniqueness to consider field mappings when validating properties (thank @skloibi)
  • allow passing multiple fields to .validates_uniqueness to validate combination uniqueness (thank @skloibi)

View

  • introduce Mapping instead of ExperimentalMapping; new mapping heavily reuse Model::Mapping
  • allow specification of property aliases via column option (cf. Model) (thank @skloibi)
  • mapping shares same functionality as Model's

Adapter

  • remove Base::ArgType alias
  • add Base#upsert
  • Postgres::Adapter#data_type_exists? is renamed to #enum_exists?
  • fix bug for dropping foreign key for postgres adapter
  • remove TableBuilderBuilders - now Migration::Base creates commands by its own
  • speed-up tables column count fetch at application start-up
  • Fix result type of #exists? query method to Bool for Base and Postgres adapters (thanks @skloibi)
  • add Base#explain abstract method and implementations for Mysql and Postgres

Config

  • add verbose_migrations to hide or show migration details during db:migrate command invocation

SqlGenerator

  • add .insert_on_duplicate and .values_expression to BaseSQLGenerator as abstract methods and implementations to Postgres and Mysql
  • now BaseSQLGenerator.from_clause accepts 2 arguments (instead of 2..3) accepting table name as 2nd argument
  • add BaseSQLGenerator.with_clause which generates CTE
  • add BaseSQLGenerator.explain

Migration

  • add Base#tinyint (not all adapter support it)
  • change next Base instance method signature:
    • #foreign_key_exists?(from_table, to_table = nil, column = nil, name : String? = nil)
    • #add_index(table_name : String | Symbol, field : Symbol, type : Symbol? = nil, name : String? = nil, length : Int32? = nil, order : Symbol? = nil) (same for TableBuilder::CreateTable#index and TableBuilder::ChangeTable#add_index)
    • #drop_index(table : String | Symbol, fields : Array(Symbol) = [] of Symbol, name : String? = nil) (same for TableBuilder::ChangeTable#drop_index)
    • #drop_foreign_key(to_table : String | Symbol, column = nil, name = nil) (same for TableBuilder::ChangeTable#drop_foreign_key)
  • add TableBuilder::CreateTable#column as alias to TableBuilder::CreateTable#field
  • new signature of TableBuilder::CreateTable#reference - #reference(name, type : Symbol = :integer, options : Hash(Symbol, AAllowedTypes) = DB_OPTIONS.new)

Record

  • for missing fields BaseException exception is raised instead of KeyError

v0.7.1

5 years ago

Changelog

QueryBuilder

  • #pluck, #update, #db_results, #results. #each_result_set and #find_in_batchesof Query respects #none (returns empty result if it has being called)
  • remove deprecated QueryObject constructor accepting array of options and #params

Model

  • fix mapping issue when all Generics are assumed as unions (#208)

Validation

  • allow passing multiple fields to .validates_uniqueness to validate combination uniqueness

Adapter

  • Mysql::SchemaProcessor now respects false as column default value
  • Postgres::SchemaProcessor now respects false as column default value

Config

  • introduce new configuration pool_size which sets max_idle_pool_size = max_pool_size = initial_pool_size to the given value; getter #pool_size returns #max_pool_size
  • postgres is no more default adapter

Migration

  • TableBuilder::Base::AllowedTypes alias includes Float64 and JSON::Any

v0.7.0

5 years ago

Overview

This release was hard and pretty long. As a result we've got a set of very important features (like polymorphic relations and complex query update mechanism). Also as a side effect bunch of side-shards were appeared to fill gaps in missing functionality (like form parsing).

Also you can find 3 sample application describing possible way of integrating web frameworks/libraries with Jennifer:

Changelog

General

  • bump sam to "~> 0.3.0"
  • add sam command generate:model to generate model and related migration
  • move all logic regarding file generating to Jennifer::Generators space
  • add db:seed task as a placeholder seeding task
  • db:setup now invokes db:seed after db:migrate

QueryBuilder

  • add #and, #or and #xor shortcut methods to ExpressionBuilder
  • Criteria#in now accepts SQLNode as well
  • add Statement module with base abstract functionality needed for query string generating
  • ExpressionBuilder#g and #group now has no argument type restriction
  • Grouping#condition now can be of Statement type
  • Query includes Statement
  • Query#to_sql now is #as_sql, #select_args - #sql_args
  • Condition includes Statement
  • Executables#update accepts block expecting Hash(Symbol, Statement) to be returned
  • Executables#modify is removed in favor of new #update method accepting block
  • now LogicOperator is inherited from SQLNode
  • #delete and exists? of Executables do nothing when #do_nothing? is true
  • add Query#do_nothing?
  • add Query.null which returns Query.new.none
  • Join accepts Grouping for ON condition

Model

  • remove Base.build_params, Base.parameter_converter methods
  • remove ParameterConverter class
  • fix skipping generating default constructor byMapping.mapping when at least one field has default value and all others are nilable
  • stringified_type option is removed from the COLUMNS_METADATA
  • STIMapping#arguments_to_save & STIMapping#arguments_to_insert now respect field converter
  • Translation model now is includeable module
  • all class methods of Translation are moved to Translation::ClassMethods which is automatically extended by target class using included macro
  • #lookup_ancestors and #human_attribute_name methods of Translation are added
  • Errors#base now is type of Translation instead of Base
  • add Base#persisted?
  • now attribute-specific rendering for Resource#inspect is generated by .mapping
  • add polymorphic relation support for has_one, has_many and belongs_to relations
  • add :nodoc: for almost all generated relation methods (except #association)
  • add missing relation names for criterion in Relation::Base methods
  • add Relation::IPolymorphicBelongsTo, Relation::PolymorphicHasMany and Relation::PolymorphicHasOne
  • @new_record, @destroyed, @errors, changeset and relation attributes now is ignored by JSON::Serializable
  • add skip_validation argument to Authentication.with_authentication macro to specify whether validation should be added
  • add generating predicate method #{{attribute}}? for boolean attribute
  • allow Jennifer::Model::Base#attribute= to accept not only defined type but also Jennifer::DBAny
  • rename Base#update_attributes to Base#set_attributes

Validation

  • all validation macros now accept :if key; the value may be both Symbol name of a method to be called or expression
  • replace validation logic generated during a macro call with new validators usage: Validations::Absence, Validations::Acceptance, Validations::Confirmation, Validations::Exclusion, Validations::Format, Validations::Inclusion, Validations::Length, Validations::Numericality, Validations::Presence, Validations::Uniqueness
  • remove Jennifer::Validator in favour of Jennifer::Valdiations::Validator
  • all validators by default implement singleton pattern
  • all validation macros are moved to Jennifer::Validations::Macros

View

  • now attribute-specific rendering for Resource#inspect is generated by .mapping
  • add generating predicate method #{{attribute}}? for boolean attribute

Adapter

  • fix output stream for postgres schema dump
  • remove legacy postgres insert
  • add Adapter#foreign_key_exists?
  • add Mysql::SchameProcessor
  • now Base#schema_processor is abstract
  • add Postgres::SchemaProcessor#rename_table
  • SchemaProcessor now is abstract class
  • all builder methods are moved from SchemaProcessor class to TableBuilderBuilders module
  • fix syntax in SchemaProcessor#drop_foreign_key
  • all _query arguments in Base methods are renamed to query
  • Base.extract_arguments is removed
  • .delete, .exists and .count of BaseSQLGenerator now returns string
  • Postgres.bulk_insert is removed
  • Transaction#with_connection ensure to release connection
  • all sqlite3 related code are removed

Config

  • fix migration_failure_handler_method property from being global
  • add new property model_files_path representing model directory (is used in a scope of model generating)
  • fix ignoring skip_dumping_schema_sql config

SqlGenerator

  • .select_clause now doesn't invoke .from_clause under the hood
  • .lock_clause adds whitespaces around lock statement automatically

Migration

  • remove Runner.generate and Runner::MIGRATION_DATE_FORMAT
  • TableBuilder::CreateTable#reference triggers #foreign_key and accepts polymorphic bool argument presenting whether additional type column should be added; for polymorphic reference foreign key isn't added

Exceptions

  • 'RecordNotFound' from QueryBuilder::Query#first! and QueryBuilder::Query#last! includes detailed parsed query

v0.6.2

5 years ago

This is an intermediate release before the breaking 0.7.0.

Changelog

General

  • add :nodoc: to all internal constants and generated methods (implementing standard ORM methods) from the macros

QueryBuilder

  • Query isn't extended by Ifrit
  • add OrderItem to describe order direction
  • add Criteria#order, Criteria#asc and Criteria#desc to create OrderItem
  • add Condition#eql? to compare with other condition or SQLNode (returns false)
  • add Criteria#eql?, Grouping#eql?, LogicOperator#eql?
  • add Query#order and Query#reorder with accepting OrderItem
  • now Query#order with block to expect a OrderItem
  • remove CriteriaContainer
  • QueryObject now is an abstract class
  • changed wording for the ArgumentError in #max, #min, #sum, #avg methods of Aggregation to "Cannot be used with grouping"
  • change Query#from(_from : String | Query) signature to Query#from(from : String | Query)

Model

  • #save and #update will return true when is called on an object with no changed fields (all before callbacks are invoked)
  • next Base methods become abstract: .primary_auto_incrementable?, .build_params, #destroy, #arguments_to_save, #arguments_to_insert
  • Base#_extract_attributes and Base#_sti_extract_attributes become private
  • all callback invocation methods become protected
  • next Resource methods become abstract: .primary, .field_count, .field_names, .columns_tuple, #to_h, #to_str_h
  • Resource isn't extended by Ifrit
  • regenerate .build_params for STI models
  • Scoping.scope(Symbol,QueryObject) now checks in runtime whether T of Jennifer::QueryBuilder::ModelQuery(T) responds to method named after the scope

View

  • Base#_after_initialize_callback becomes protected
  • Base#_extract_attributes becomes private

Adapter

  • fix custom port not used when accessing the Postgres database

Migration

  • TableBuilder::Base isn't extended by Ifrit
  • rename TableBuilder::ChangeTable#new_table_rename getter to #new_table_name
  • fix misuse of local variable in TableBuilder::ChangeTable#rename_table
  • TableBuilder::ChangeTable#change_column has next changes:
    • old_name argument renamed to name
    • new_name argument is replaced with option in options arguemnt hash
    • raise ArgumentError if both type and options[:sql_type] are nil
  • TableBuilder::ChangeTable#change_column raises ArgumentError if both type and options[:sql_type] are nil
  • TableBuilder::CreateTable#field data_type argument renamed to type
  • TableBuilder::CreateTable#timestamps creates fields with null: false by default
  • TableBuilder::CreateTable#add_index is removed in favour of #index
  • .pending_versions, .assert_outdated_pending_migrations and .default_adapter methods of Runnerbecome private
  • Runner.config is removed

v0.6.1

5 years ago

Changelog

General

  • adds Time::Span to supported types

QueryBuilder

  • allows listing any SQLNode instance in SELECT clause (like raw sql or functions)
  • removes redundant SQLNode#sql_args_count
  • adds SQLNode#filterable? function which presents if node has filterable sql parameter
  • refactors Condition#sql_arg
  • adds Function base abstract class for defining custom sql functions
  • adds lower, upper, current_timestamp, current_date, current_time, now, concat, abs, ceil, floor, round
  • adds Join#filterable? and Query#filterable?
  • raise AmbiguousSQL when % symbol is found in the raw SQL (except %s)

Model

  • replaces mapping option numeric_converter with new converter
  • adds NumericToFloat64Converter and JSONConverter
  • now #to_h and #to_str_h use field getter methods
  • remove puts from JSONConverter#from_db

Adapter

  • propagate native DB::Error instead of wrapping it into BadQuery
  • manually release a connection when an exception occurs under the transaction

Config

  • set default max_pool_size to 1 and warn about danger of setting different max_pool_size, max_idle_pool_size and initial_pool_size

Migration

  • adds Migration::TableBuilder::CreateForeignKey & Migration::TableBuilder::DropForeignKey
  • adds Migration::Base#add_foreign_key & Migration::Base#drop_foreign_key
  • adds Migration::TableBuilder::ChangeTable#add_foreign_key & Migration::TableBuilder::ChangeTable#drop_foreign_key

Exceptions

  • add AmbiguousSQL - is raised when forbidden % symbol is used in the raw SQL

v0.6.0

5 years ago

This release brings a lot of features that are useful for the web-based applications. Enjoy :smile: :balloon: :tada:

Changelog

General

  • adds support of crystal 0.25.0
  • removes time_zone dependency
  • removes requiring "inflector/string"
  • adds cloning to Time::Location & Time::Location::Zone
  • removes Ifrit.typed_hash and Ifrit.typed_array usage
  • presents "mapping types" which allows reusing common type definition
  • now Primary32 and Primary64 are mapping types (not aliases of Int32 and Int64)
  • removes accord dependency

QueryBuilder

  • allows nested eager loading in ModelQuery(T)#eager_load and ModelQuery(T)#include
  • all query eager loading methods are extracted to separate module QueryBuilder::EagerLoading which is included in QueryBuilder::IModelQuery

Model

  • introduces model virtual attributes
  • adds Mapping.build_params and ParameterConverter class for converting Hash(String, String) parameters to acceptable by model
  • allows to specify table prefix
  • all relations are stored in Base::RELATIONS
  • fixes building of sti objects using parent class
  • adds Jennifer::Model::Authentication module with authentication logic
  • fixes compile time issue with IRelation when app has no belongs-to relation defined
  • fixes bug with reading Int64 primary key
  • adds #inspect
  • adds numeric_converter mapping option for numeric postgres field
  • introduces new Jennifer::Model::Errors class replacing Accord::ErrorList which mimics analogic rails one a lot;
  • moves Translation::human_error method functionality to introduced Errors instance level
  • now next Resource static methods are abstract: actual_table_field_count, primary_field_name, build, all, superclass
  • Resource#inspect returns simplified version (only class name and object id)
  • Resource.all now is a macro method
  • fixes Model::Transaltion.lookup_ancestors from breaking at compilation time
  • now all built-in validations use attribute getter methods instead of variables

View

  • removes ExperimentalMapping#attributes_hash, ExperimentalMapping.strict_mapping?

Config

  • local_time_zone now is a Time::Location
  • local time zone is loaded using Time::Location.local as default value

SqlGenerator

  • replaces \n with whitespace character as query part separator

Migration

  • now migration version is taken from file name timestamp
  • Jennifer::Migration::Base.migrations returns a hash of version number => migration class instead of array of classes

v0.5.1

5 years ago

This is a temporary release before the 0.6.0.

All changes could be found in CHANGELOG.md file.

v0.5.0

6 years ago

At the age of 1 :tada:

This is an anniversary release - 1 year ago the very first commit has been made. A lot of work have been done and a lot of will be but for now this it is the most powerful ORM for crystal - with flexible query dsl, mapping declaration, callbacks, validation, internationalization, migrating mechanism, materialized and non materialized view

Changes

  • all adapter-related logic have been decoupled - all adapters could be required at the same place (one step forward to multi-adapter application support)
  • added internationalization support - now human model name, attribute name and error message are translated using i18n shard
  • added support of time_zone - any time object is converted from local time to UTC during storing it to the db and vise versa
  • added new validation macros
  • made one step from Accord - introduced new validator class and implemented own validation methods
  • added new callbacks - update, commit and rollback

More complite list of changes could be found in CHANGELOG.md file. Also documentation .md files has got new information - check it out.

Have an awesome coding and happy Valentine's day :heart:

v0.4.3

6 years ago
  • All macro methods were rewritten to new 0.24.1 crystal syntax

Adapter

  • removed Jennifer::Adapter::TICKS_PER_MICROSECOND
  • fixes Jennifer::Adapter::Mysql#table_column_count bug

Model

  • add Primary32 and Primary64 shortcuts for primary key mapping (view mapping respects this as well)
  • add ::create! & ::create with splatted named tuple arguments
  • now relation retrieveness is updated for any superclass relations as well
  • a relation will be retrieved from db for only persisted record
  • move Jennifer::Mode::build method to %mapping macro
  • allow retrieving and building sti records using base class
  • fix #reload method for sti record
  • optimize building sti record from hash

QueryBuilder

  • fix Criteria#not
  • add Criteria#ilike

View

  • introduce View::Materialized superclass for materialized views
  • add COLUMNS_METADATA constant
  • add ::columns_tuple which retrns COLUMNS_METADATA
  • remove ::children_classes
  • make after_initialize callback respect inheritance
  • add ::adapter

Exceptions

  • add AbstractMethod exception which represents expectation of overriding current method by parents (is usefull when method can't be real abstract one)
  • add UnknownSTIType

v0.4.2

6 years ago

SqlGenerator

  • rename #trancate to #truncate

Migration

  • rename TableBuilder::DropInde to TableBuilder::DropIndex

  • remove printing out redundand execution information during db drop and create

  • remove Migration::Base::TABLE_NAME constant

  • allow to pass QueryBuilder::Query as source to the CreateMaterializedView (postgres only)

Model

  • move Base#build method witout arguments to Mapping module under the %mapping

  • added validates_presence_of validation macros

  • fixed callback invokation from parent classes

  • add allow_blank key to validates_inclusion, validates_exclusion, validates_format

  • add ValidationMessages module which includes methods generating validation error messages

  • add Primary32 and Primary64 shortcuts for Int32 and Int64 primary field declarations for model and view

  • allow use nil usions instead of null: true named tuple option

QueryBuilder

  • #count method is moved from Executables module to the Aggregations one

  • changed method signature of #find_in_batches

  • add #find_each - works same way as #find_in_batches but yields each record instead of array

  • add #ordered? method to Ordering module

  • switch Criteria#hash to use object_id as seed

  • add Query#eql?

  • add Query#clone and all related methods

  • add Query#except - creates clone except given clauses

  • make IModelQuery class as new superclass of ModelQuery(T); move all methods no depending on T to the new class