Class: Heresy::Model

Inherits:
Object
  • Object
show all
Defined in:
lib/heresy/model.rb

Overview

This class is responsible for storing and retrieving the model data in a schema-free manner.

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes = {}) ⇒ Model

Returns a new instance of Model.



114
115
116
# File 'lib/heresy/model.rb', line 114

def initialize(attributes = {})
  set_attributes attributes
end

Class Attribute Details

.dbObject

Reference to the Sequel DB object



75
76
77
# File 'lib/heresy/model.rb', line 75

def db
  @db = Heresy.db
end

.formatterObject

The formatter is what converts the assembled model hash data into the string that gets saved in the database. The default formatter stores zlib compressed JSON hashes.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/heresy/model.rb', line 87

def formatter
  @formatter ||= \
    if superclass.respond_to?(:formatter)
      superclass.formatter
    else
      :json
    end

  if @formatter.is_a?(Symbol)
    require "heresy/formatting/#{@formatter}"
    @formatter = Heresy::Formatting.const_get(@formatter.to_s.capitalize)
  end

  @formatter
end

.schema(table_name = name.demodulize.underscore.pluralize) {|@schema| ... } ⇒ Object

Accesses the database schema for this model. The basic schema will look something like this:

create_table :entries do |t|
  t.primary_key :id,         :int
  t.column      :uuid,       :binary
  t.column      :updated_at, :timestamp
  t.column      :body,       :blob
end

You can modify any of those from the schema directly.

class Entry < Heresy::Model
  schema :custom_table_name do |s|
    s.id.type = :medium_int
    s.id.options[:size] = 11
    s.body.type = :medium_blob
  end
end

The types are any valid type from the Sequel ruby library. There are a few convenience types, however. (See Heresy::Schema::Column)

All models have the same 4 database fields:

- an auto-incremented ID and updated_at timestamp
- a 32 character hex UUID that gets stored as a 16 character binary string.  This is how items are retrieved.
- a BLOB body character for storing the model's data.

Yields:



34
35
36
37
38
# File 'lib/heresy/model.rb', line 34

def schema(table_name = name.demodulize.underscore.pluralize)
  @schema ||= Heresy::Schema.new(db, table_name.to_sym)
  yield @schema if block_given?
  @schema
end

Instance Attribute Details

#idObject (readonly)

Returns the value of attribute id.



111
112
113
# File 'lib/heresy/model.rb', line 111

def id
  @id
end

#updated_atObject (readonly)

Returns the value of attribute updated_at.



112
113
114
# File 'lib/heresy/model.rb', line 112

def updated_at
  @updated_at
end

Class Method Details

.body_fieldsObject

This is a hash of all specified fields and their type converters. If a type converter is set (see #fields), values are parsed in the field attribute writers, and encoded when saving to the database.



60
61
62
# File 'lib/heresy/model.rb', line 60

def body_fields
  @body_fields ||= {}
end

.datasetObject

Reference to the Sequel dataset for this model’s table.



80
81
82
# File 'lib/heresy/model.rb', line 80

def dataset
  @dataset ||= db[schema.name]
end

.fields {|Schema::Fields.new(self)| ... } ⇒ Object

Yields a Schema::Fields object for specifying fields for this model. These fields get assembled into a hash and stored in the BODY attribute of the schema.

By default, fields are all strings. Other types such as integers and dates can be specified for automatic conversions.

class Entry < Heresy::Model
  fields do |f|
    f.string   :title
    f.integer  :comments_count
    f.datetime :published_at
  end
end

Yields:



54
55
56
# File 'lib/heresy/model.rb', line 54

def fields
  yield Schema::Fields.new(self)
end

.find(uuid) ⇒ Object

Finds a single or an array of entries by UUID.



65
66
67
68
69
70
71
72
# File 'lib/heresy/model.rb', line 65

def find(uuid)
  if uuid.is_a?(Array)
    rows = dataset.filter(:uuid => uuid.map { |u| u.to_a.pack("H*") }).to_a
    rows.map! { |row| retrieve(row) }
  else
    new(:uuid => uuid).reload
  end
end

Instance Method Details

#==(other) ⇒ Object



143
144
145
# File 'lib/heresy/model.rb', line 143

def ==(other)
  other.class == self.class && other.uuid == uuid
end

#inspectObject



147
148
149
# File 'lib/heresy/model.rb', line 147

def inspect
  "<#{self.class.name} (#{uuid}) #{self.class.body_fields.keys.map { |k| "@#{k}=#{send(k).inspect}" } * ', '}>"
end

#new?Boolean

Returns:

  • (Boolean)


134
135
136
# File 'lib/heresy/model.rb', line 134

def new?
  @id.nil?
end

#reloadObject

Reloads a model’s data from the database using the existing UUID.



139
140
141
# File 'lib/heresy/model.rb', line 139

def reload
  retrieve(rowset.select(:id, :body, :updated_at).first)
end

#retrieve(row) ⇒ Object



151
152
153
154
155
156
# File 'lib/heresy/model.rb', line 151

def retrieve(row)
  @id          = row[:id]
  @updated_at  = row[:updated_at]
  set_attributes self.class.formatter.decode(row[:body])
  self
end

#saveObject

Saves the record in the database.



123
124
125
126
127
128
129
130
131
132
# File 'lib/heresy/model.rb', line 123

def save
  if new?
    self.class.dataset << {:uuid => uuid.to_a.pack("H*"), :body => self.class.formatter.encode(assemble_body)}
    reload
  else
    rowset.update({:updated_at => nil})
    reload
  end
  true
end

#uuidObject



118
119
120
# File 'lib/heresy/model.rb', line 118

def uuid
  @uuid ||= UUID.generate(:compact)
end