abstract class Jennifer::Model::Base

Included Modules

Extended Modules

Defined in:

jennifer/model/base.cr

Class Method Summary

Instance Method Summary

Instance methods inherited from module Jennifer::Model::Validation

errors : Errors errors, invalid? invalid?, valid? valid?, validate!(skip = false) : Bool validate!

Instance methods inherited from module Jennifer::Model::Mapping

attribute_metadata(name : String | Symbol) attribute_metadata

Instance methods inherited from module Jennifer::Presentable

attribute(name : String | Symbol, raise_exception : Bool = true) attribute, attribute_metadata(name : String | Symbol) attribute_metadata, class_name : String class_name, errors : Jennifer::Model::Errors errors, human_attribute_name(name : String | Symbol) human_attribute_name

Instance methods inherited from class Jennifer::Model::Resource

append_relation(name : String, hash) append_relation, attribute(name : String | Symbol, raise_exception : Bool = true) attribute, get_relation(name : String) get_relation, inspect(io) : Nil inspect, primary primary, set_inverse_of(name : String, object) set_inverse_of, to_h to_h, to_json(only : Array(String)? = nil, except : Array(String)? = nil)
to_json(only : Array(String)? = nil, except : Array(String)? = nil, &)
to_json(json : JSON::Builder)
to_json(json : JSON::Builder, only : Array(String)? = nil, except : Array(String)? = nil, &)
to_json
, to_str_h to_str_h

Class methods inherited from class Jennifer::Model::Resource

adapter adapter, all all, build(values : Hash(Symbol, Jennifer::DBAny) | NamedTuple)
build(values : Hash(String, Jennifer::DBAny))
build(**values)
build
, c(name : String | Symbol, relation)
c(name : String | Symbol)
c
, context context, read_adapter read_adapter, relation(name) relation, star star, table_name(value : String | Symbol)
table_name : String
table_name
, transaction(&) transaction, where(&)
where(conditions : Hash(Symbol, _))
where
, write_adapter write_adapter

Instance methods inherited from module Jennifer::Model::RelationDefinition

append_relation(name : String, hash) append_relation, get_relation(name : String) get_relation, relation_retrieved(name : String) relation_retrieved, set_inverse_of(name : String, object) set_inverse_of

Instance methods inherited from module Jennifer::Model::Translation

class_name : String class_name, human_attribute_name(attribute : String | Symbol) human_attribute_name, lookup_ancestors(&) lookup_ancestors

Class Method Detail

def self.actual_table_field_count #

Returns actual model table column amount (is grepped from db).

If somewhy you define model with custom table name after the place where adapter is used the first time - manually invoke this method anywhere after table name definition.


[View source]
def self.build(values : Hash | NamedTuple, new_record : Bool) #

Initializes new object based on given arguments.

after_initialize callbacks are invoked. If model mapping allows creating an object without passing any argument - relevant #build method will be generated for such model.


[View source]
def self.build(pull : DB::ResultSet) #

Alias for .new.


[View source]
def self.coercer #

[View source]
def self.create(values : Hash | NamedTuple) #

Creates an object based on given values and saves it to the database, if validation pass.

The resulting object is return whether it was saved to the database or not.

Contact.create({:name => "Jennifer"})
Contact.create({name: "Jennifer"})

[View source]
def self.create #

Creates an object based on an empty hash and saves it to the database, if validation pass.

The resulting object is return whether it was saved to the database or not.

Contact.create

[View source]
def self.create(**values) #

Creates an object based on values and saves it to the database, if validation pass.

The resulting object is return whether it was saved to the database or not.

Contact.create(name: "Jennifer")

[View source]
def self.create!(values : Hash | NamedTuple) #

Creates an object based on values and saves it to the database, if validation pass.

Raises an RecordInvalid error if validation fail, unlike .create.

Contact.create!({:name => "Jennifer"})
Contact.create!({name: "Jennifer"})

[View source]
def self.create! #

Creates an object based on empty hash and saves it to the database, if validation pass.

Raises an RecordInvalid error if validation fail, unlike .create.

Contact.create!

[View source]
def self.create!(**values) #

Creates an object based on values and saves it to the database, if validation pass.

Raises an RecordInvalid error if validation fail, unlike .create.

Contact.create!(name: "Jennifer")

[View source]
def self.delete(ids : Array) #

Deletes records by given ids.


[View source]
def self.delete(*ids) #

Deletes records by given ids.


[View source]
def self.destroy(ids : Array) #

Destroys records by given ids.

All #destroy callbacks will be invoked for each record. All records are loaded in batches.

Contact.destroy(1, 2, 3)
Contact.destroy([1, 2, 3])

[View source]
def self.destroy(*ids) #

Destroys records by given ids.

All #destroy callbacks will be invoked for each record. All records are loaded in batches.

Contact.destroy(1, 2, 3)
Contact.destroy([1, 2, 3])

[View source]
def self.find(id) #

Returns record by given primary field or nil otherwise.

Contact.find(-1) # => nil

[View source]
def self.find!(id) #

Returns record by given primary field or raises Jennifer::RecordNotFound exception otherwise.

Contact.find!(-1) # Jennifer::RecordNotFound

[View source]
def self.foreign_key_name(value : String | Symbol) #

Sets custom model foreign key name.

class User < Jennifer::Model::Base
  foreign_key_name :client_id
end

[View source]
def self.foreign_key_name #

Returns model foreign key name.


[View source]
def self.has_table? #

Returns whether model has a table.

NOTE shouldn't be used outside of tests.


[View source]
def self.import(collection : Array(self)) #

Performs bulk import of given collection.

Any callback is ignored.

User.import([
  User.new({name: "John"}),
  User.new({name: "Fahad"}),
])

[View source]
def self.models #

Returns array of all non-abstract subclasses of Jennifer::Model::Base.

Jennifer::Model::Base.models # => [Contact, Address, User]

[View source]
def self.upsert(collection : Array(self), unique_fields = [] of String) #

Performs bulk import of given collection while ignoring models that would cause a duplicate value of any UNIQUE index on given unique_fields.

Some RDBMS (like MySQL) doesn't require specifying exact constraint to be violated, therefore unique_fields argument by default is [] of String.

Any callback is ignored.

Order.create({:uid => 123})
Order.upsert([
  Order.new({:uid => 123}),
  Order.new({:uid => 321}),
])

[View source]
def self.upsert(collection : Array(self), unique_fields = [] of ::String, &) #

[View source]
def self.with_table_lock(type : String | Symbol, &) #

Performs table lock for current model's table.


[View source]

Instance Method Detail

abstract def arguments_to_insert #

Returns named tuple of all model fields to insert.

NOTE internal method


[View source]
abstract def arguments_to_save #

Returns named tuple of all fields should be saved (because they are changed).

NOTE internal method


[View source]
abstract def changed? : Bool #

Returns whether any field was changed. If field again got first value - true anyway will be returned.

user.name # => John
user.name = "Bill"
user.changed? # => true
user.name = "John"
user.changed? # => true

[View source]
abstract def changes : Hash(String, Jennifer::DBAny) #

Hash of changed columns and their new values.


[View source]
def delete #

Deletes object from the database.

Any callback is invoked. Doesn't start any transaction.


[View source]
abstract def destroy : Bool #

Deletes object from db and calls all related callbacks.

It returns true if the object was successfully deleted.

Contact.first!.destroy # => true

[View source]
def destroy_without_transaction #

Perform destroy without starting a database transaction.


[View source]
def destroyed? : Bool #

Returns whether record isn't destroyed.


[View source]
def lock!(type : String | Bool = true) #

Lock current object in the database.


[View source]
def new_record? : Bool #

Returns whether record isn't persisted.


[View source]
def persisted? #

Returns true if the record is persisted, i.e. it’s not a new record and it wasn't destroyed, otherwise returns false.


[View source]
def reload #

Reloads the record from the database.

This method finds record by its primary key and modifies the receiver in-place. All relations are refreshed.

user = User.first!
user.name = "John"
user.reload # => #<User id: 1, name: "Will">

[View source]
def save(skip_validation : Bool = false) : Bool #

Saves the object.

If the object is a new record it is created in the database, otherwise the existing record get updated.

By default, #save triggers validations but they can be skipped passing true as the second argument. If any of them fails #save returns false.

There is a series of callbacks associated with #save. If any of the before_* callbacks return false the action is cancelled and false is returned. See Jennifer::Model::Callback for further details.

user.name = "Will"
user.save # => true

[View source]
def save! #

Saves the object.

If the object is a new record it is created in the database, otherwise the existing record get updated.

#save! always triggers validations. If any of them fails Jennifer::RecordInvalid gets raised.

There is a series of callbacks associated with #save!. If any of the before_* callbacks return false the action is cancelled and exception is raised. See Jennifer::Model::Callback for further details.

user.name = "Will"
user.save! # => true

[View source]
def save_without_transaction(skip_validation : Bool = false) : Bool #

Saves all changes to the database without starting a transaction; if any validation fails - returns false.


[View source]
abstract def set_attribute(name : String | Symbol, value : AttrType) #

Sets name field with value

contact.set_attribute(:name, "Ivan")

[View source]
def set_attributes(values : Hash | NamedTuple) #

Sets attributes based on values where keys are attribute names.

post.set_attributes({:title => "New Title", :created_at => Time.local})
post.set_attributes({title: "New Title", created_at: Time.local})
post.set_attributes(title: "New Title", created_at: Time.local)

[View source]
def set_attributes(**values) #

Sets attributes based on values where keys are attribute names.

post.set_attributes({:title => "New Title", :created_at => Time.local})
post.set_attributes({title: "New Title", created_at: Time.local})
post.set_attributes(title: "New Title", created_at: Time.local)

[View source]
def track_timestamps_on_create #

[View source]
def track_timestamps_on_update #

[View source]
def update(values : Hash | NamedTuple) : Bool #

Sets attributes based on given values using #set_attribute and saves it to the database, if validation pass.

Returns whether object is successfully saved.

contact.update({:name => "Jennifer"})
contact.update({name: "Jennifer"})

[View source]
def update(**values) #

Sets attributes based on given values using #set_attribute and saves it to the database, if validation pass.

Returns whether object is successfully saved.

contact.update(name: "Jennifer")

[View source]
def update!(values : Hash | NamedTuple) : Bool #

Sets attributes based on given values and saves it to the database, if validation pass.

Raises an RecordInvalid error if validation fail, unlike #update.

contact.update!({:name => "Jennifer"})
contact.update!({name: "Jennifer"})

[View source]
def update!(**values) : Bool #

Sets attributes based on given values and saves it to the database, if validation pass.

Raises an RecordInvalid error if validation fail, unlike #update.

contact.update!(name: "Jennifer")

[View source]
def update_column(name : String | Symbol, value : Jennifer::DBAny) #

Sets value to field with name name and stores them directly to the database without any validation or callback.

Is a shorthand for #update_columns({ name => value }). Doesn't use attribute writer.


[View source]
abstract def update_columns(values : Hash(String | Symbol, AttrType)) #

Assigns record properties based on key-value pairs of values and stores them directly to the database without running validations and callbacks.

updated_at property is not updated as well.

If at least one attribute get value of wrong type or attribute is missing or is virtual - BaseException is raised.

user.update_columns({:name => "Jennifer"})

[View source]
def with_lock(type : String | Bool = true, &) #

Starts a transaction and locks current object.


[View source]