LoreModel

From Cubawiki

Jump to: navigation, search

Contents

General

A model provides object oriented abstraction of Types your application uses. A model consists of one or more tables or, more general: Stores.

An Example: Cars and motorcycles both are Vehicles, and both are driven by one or more person. These persons can drive one or more Vehicles.

So the model klasses needed are:

  • Vehicle (abstract base class)
  • Car < Vehicle
  • Bike < Vehicle
  • Driver
  • Vehicle_Driver (maps n Drivers to n Vehicles)

Lore::Model allows operations on models in plain ruby code.


API for model definition: Model class methods

See also documentation for Lore::Table_Accessor

table :table_name [, :schema_name]

Which table this model is mapped to itself.

primary_key :key_name [, :sequence_name]

Declares attribute :key_name as primary key for the model's own table.
State this for each primary key.

is_a Other_Model, :own_foreign_key [, :other_own_foreign_keys]

is_a Other_Model also does the following:

  • Defining aggregates from Other_Model for this model (thus inherits has_a, is_a and aggregates).
  • Defining filters from Other_Model for this model (thus inherits add_input_filter and add_output_filter).


aggregates Other_Model, :own_foreign_key [, :other_own_foreign_keys]

Eager loading for Other_Model. Whenever records are selected for this model, Other_Model will be joined automatically. It is similar to is_a, but it does not affect creation and updates, only selects.

has_a Other_Model, :own_foreign_key [, :other_own_foreign_keys]

has_a_named Other_Model, :name_to_use, :own_foreign_key [, :other_own_foreign_keys]

Like has_a but additionally defines method name to access the foreign entity with.
Example: has_a_named User_Hierarchy_Entry, :user, :entry_id generates method My_Model.user instead My_Model.user_hierarchy_entry_entity

has_many Other_Model, :own_foreign_key [, :other_own_foreign_keys]

has_many_named Other_Model, :own_foreign_key [, :other_own_foreign_keys]

use_label :attribute_name

Which attribute's value to use for labelling instances, e.g. in select boxes or generated views.

set_explicit :attribute_name

When set to explicit, an attribute is only included into update and insert statements if a value for it is given.
Useful when e.g. using NOW() as default value for an attribute.

validates :attribute_name, <constraints>

Possible constraints are:

  • :format => /regexp/ Checks attribute value against given regular expression
  • :length => 10 Checks whether length of attribute value lies within given range
  • :length => [10..20] Checks whether length of attribute value lies within given range
  • :minlength => 10 Checks whether attribute value has at least given length
  • :maxlength => 20 Checks whether attribute value length is below given length


add_input_filter(:attribute_name) { |attrib| ... }

Applies given block to value passed for an attribute. Note that the block has to return the value.

Example:

 
  class My_Model < Lore::Model 
  # ...
    add_input_filter :name { |value| 
      value.downcase!
      value.gsub!(' ', '_')
      value
    }
  # ...
  end

This filter switches values passed for attribute 'name' to downcase and replaces spaces by underscores before writing them into the database:

  obj = My_Model.create(:name => 'But a Test')
  obj.name # -> 'but_a_test'

add_output_filter(:attribute_name) { |attrib| ... }

Applies given block to value of given attribute when read from database. Note that the block has to return the value.

Example:

  add_output_filter :timestamp { |value| 
    value.strftime("%m/%D/%Y")
  }

This filter transforms a database timestamp into a human readable string.

context :db_name

If the underlying table belongs to a database (context) different from the default context (set via Lore::Context.enter :default_context_name), this can be declared with context :other_context.

Model hooks

See also documentation for Lore::Aspect

For example, steps taken in .create are:

  1. self.before_create(attribs)
  2. applying input filters
  3. self.after_filters(attribs)
  4. distributing attributes to tables: { :attrib => 'value' } -> { 'public.my_table' => { :attrib => 'value'} }
  5. self.before_validation(table_attribs)
  6. validation
  7. self.before_insert(table_attribs)
  8. insert operation
  9. self.before_load(attribs)
  10. load new instance from DB (thus getting final table values eventually set via default values, triggers etc.)
  11. self.after_create(created_instance)

Overload following class methods to add hooks for the model itself:

self.before_create(args)

Hook called at the very beginning of Model.create. Arguments passed are those passed to create without modifications. Usage example:

class My_Model < Lore::Model
# ...
  def self.before_create(args)
    puts 'creating instance of My_Model with values: ' << args.inspect
  end
# ...
end

obj = My_Model.create(:name => 'An Example', :position => 3)

-> 'creating instance of My_Model with values: { :name => 'An Example', :position => 3 }

self.after_filters(filtered_args)

Hook called at beginning of Model.create after input filtering. Arguments passed are those passed to create with input filters applyied. Usage example:

class My_Model < Lore::Model
# ...
  add_input_filter :name { |value| value.downcase.gsub(' ','_') }
  add_input_filter :position { |value| value.to_i + 1 }

  def self.after_filters(filtered_args)
    puts 'creating instance of My_Model with values: ' << filtered_args.inspect
  end
# ...
end

obj = My_Model.create(:name => 'An Example', :position => 3)

-> 'creating instance of My_Model with values: { :name => 'an_example', :position => 4 }

self.before_validation(distributed_args)

self.before_insert(validated_args)

self.before_load(completed_validated_args)

self.after_create(model_instance)

Overload following instance methods to add hooks for model instances:

before_delete(model_instance)

after_delete(model_instance)

before_commit(model_instance)

after_commit(model_instance)

Personal tools