LoreModel
From Cubawiki
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:
- self.before_create(attribs)
- applying input filters
- self.after_filters(attribs)
- distributing attributes to tables: { :attrib => 'value' } -> { 'public.my_table' => { :attrib => 'value'} }
- self.before_validation(table_attribs)
- validation
- self.before_insert(table_attribs)
- insert operation
- self.before_load(attribs)
- load new instance from DB (thus getting final table values eventually set via default values, triggers etc.)
- 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:
