Module: DataMapper::Persistence::ClassMethods

Defined in:
lib/data_mapper/persistence.rb

Constant Summary collapse

PROPERTY_OPTIONS =

NOTE: check is only for psql, so maybe the postgres adapter should define its own property options. currently it will produce a warning tho since PROPERTY_OPTIONS is a constant

[
  :public, :protected, :private, :accessor, :reader, :writer,
  :lazy, :default, :nullable, :key, :serial, :column, :size, :length,
  :index, :check
]
MAGIC_PROPERTIES =
{
  :updated_at => lambda { before_save { |x| x.updated_at = Time::now } },
  :updated_on => lambda { before_save { |x| x.updated_on = Date::today } },
  :created_at => lambda { before_create { |x| x.created_at = Time::now } },
  :created_on => lambda { before_create { |x| x.created_on = Date::today } }
}

Instance Method Summary collapse

Instance Method Details

#embed(name, options = {}, &block) ⇒ Object

An embedded value maps the values of an object to fields in the record of the object’s owner. #embed takes a symbol to define the embedded class, options, and an optional block. See examples for use cases.

EXAMPLE:

class CellPhone < DataMapper::Base
  property :number, :string

  embed :owner, :prefix => true do
    property :name, :string
    property :address, :string
  end
end

my_phone = CellPhone.new
my_phone.owner.name = "Nick"
puts my_phone.owner.name

=> Nick

OPTIONS:

* <tt>prefix</tt>: define a column prefix, so instead of mapping :address to an 'address' 
column, it would map to 'owner_address' in the example above. If :prefix => true is 
specified, the prefix will be the name of the symbol given as the first parameter. If the
prefix is a string the specified string will be used for the prefix.
* <tt>lazy</tt>: lazy-load all embedded values at the same time. :lazy => true to enable.
Disabled (false) by default.
* <tt>accessor</tt>: Set method visibility for all embedded properties. Affects both
reader and writer. Allowable values are :public, :protected, :private. Defaults to :public
* <tt>reader</tt>: Like the accessor option but affects only embedded property readers.
* <tt>writer</tt>: Like the accessor option but affects only embedded property writers.
* <tt>protected</tt>: Alias for :reader => :public, :writer => :protected
* <tt>private</tt>: Alias for :reader => :public, :writer => :private


273
274
275
# File 'lib/data_mapper/persistence.rb', line 273

def embed(name, options = {}, &block)
  EmbeddedValue::define(self, name, options, &block)
end

#extended(klass) ⇒ Object



107
108
109
110
111
112
113
114
115
# File 'lib/data_mapper/persistence.rb', line 107

def extended(klass)
  unless klass == DataMapper::Base
    klass.class_eval do
      def persistent?
        true
      end        
    end
  end
end

#foreign_keyObject



103
104
105
# File 'lib/data_mapper/persistence.rb', line 103

def foreign_key
  Inflector.underscore(self.name) + "_id"
end

#index(indexes, unique = false) ⇒ Object

Creates a composite index for an arbitrary number of database columns. Note that it also is possible to specify single indexes directly for each property.

EXAMPLE WITH COMPOSITE INDEX:

class Person < DataMapper::Base
  property :server_id, :integer
  property :name, :string

  index [:server_id, :name]
end

EXAMPLE WITH COMPOSITE UNIQUE INDEX:

class Person < DataMapper::Base
  property :server_id, :integer
  property :name, :string

  index [:server_id, :name], :unique => true
end

SINGLE INDEX EXAMPLES:

  • property :name, :index => true

  • property :name, :index => :unique



303
304
305
306
307
308
309
# File 'lib/data_mapper/persistence.rb', line 303

def index(indexes, unique = false)
  if indexes.kind_of?(Array) # if given an index of multiple columns 
    database.schema[self].add_composite_index(indexes, unique)
  else
    raise ArgumentError.new("You must supply an array for the composite index")
  end
end

#loggerObject



95
96
97
# File 'lib/data_mapper/persistence.rb', line 95

def logger
  database.logger
end

#propertiesObject



277
278
279
# File 'lib/data_mapper/persistence.rb', line 277

def properties
  @properties
end

#property(name, type, options = {}) ⇒ Object

Adds property accessors for a field that you’d like to be able to modify. The DataMapper doesn’t use the table schema to infer accessors, you must explicity call #property to add field accessors to your model.

EXAMPLE:

class CellProvider
  property :name, :string
  property :rating, :integer
end

att = CellProvider.new(:name => 'AT&T')
att.rating = 3
puts att.name, att.rating

=> AT&T
=> 3

OPTIONS:

* <tt>lazy</tt>: Lazy load the specified property (:lazy => true). False by default.
* <tt>accessor</tt>: Set method visibility for the property accessors. Affects both 
reader and writer. Allowable values are :public, :protected, :private. Defaults to 
:public
* <tt>reader</tt>: Like the accessor option but affects only the property reader.
* <tt>writer</tt>: Like the accessor option but affects only the property writer.
* <tt>protected</tt>: Alias for :reader => :public, :writer => :protected
* <tt>private</tt>: Alias for :reader => :public, :writer => :private

Raises:

  • (ArgumentError.new)


156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/data_mapper/persistence.rb', line 156

def property(name, type, options = {})

  options.each_pair do |k,v|
    raise ArgumentError.new("#{k.inspect} is not a supported option in DataMapper::Base::PROPERTY_OPTIONS") unless PROPERTY_OPTIONS.include?(k)
  end

  visibility_options = [:public, :protected, :private]
  reader_visibility = options[:reader] || options[:accessor] || :public
  writer_visibility = options[:writer] || options[:accessor] || :public
  writer_visibility = :protected if options[:protected]
  writer_visibility = :private if options[:private]

  raise(ArgumentError.new, "property visibility must be :public, :protected, or :private") unless visibility_options.include?(reader_visibility) && visibility_options.include?(writer_visibility)

  mapping = database.schema[self].add_column(name.to_s.sub(/\?$/, '').to_sym, type, options)

  property_getter(mapping, reader_visibility)
  property_setter(mapping, writer_visibility)

  if MAGIC_PROPERTIES.has_key?(name)
    class_eval(&MAGIC_PROPERTIES[name])
  end

  return name
end

#property_getter(mapping, visibility = :public) ⇒ Object



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/data_mapper/persistence.rb', line 189

def property_getter(mapping, visibility = :public)
  if mapping.lazy?
    class_eval <<-EOS
    #{visibility.to_s}
    def #{mapping.name}
      lazy_load!(#{mapping.name.inspect})
      class << self;
        attr_accessor #{mapping.name.inspect}
      end
      @#{mapping.name}
    end
    EOS
  else
    class_eval("#{visibility.to_s}; def #{mapping.name}; #{mapping.instance_variable_name} end") unless [ :public, :private, :protected ].include?(mapping.name)
  end

  if mapping.type == :boolean
    class_eval("#{visibility.to_s}; def #{mapping.name.to_s.ensure_ends_with('?')}; #{mapping.instance_variable_name} end")
  end

rescue SyntaxError
  raise SyntaxError.new(mapping)
end

#property_setter(mapping, visibility = :public) ⇒ Object



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/data_mapper/persistence.rb', line 213

def property_setter(mapping, visibility = :public)
  if mapping.lazy?
    class_eval <<-EOS
    #{visibility.to_s}
    def #{mapping.name}=(value)
      class << self;
        attr_accessor #{mapping.name.inspect}
      end
      @#{mapping.name} = value
    end
    EOS
  else
    class_eval("#{visibility.to_s}; def #{mapping.name}=(value); #{mapping.instance_variable_name} = value end")
  end
rescue SyntaxError
  raise SyntaxError.new(mapping)
end

#set_table_name(value) ⇒ Object

Allows you to override the table name for a model. EXAMPLE:

class WorkItem
  set_table_name 't_work_item_list'
end


236
237
238
# File 'lib/data_mapper/persistence.rb', line 236

def set_table_name(value)
  database.table(self).name = value
end

#subclassesObject

Track classes that include this module.



91
92
93
# File 'lib/data_mapper/persistence.rb', line 91

def subclasses
  @subclasses || (@subclasses = [])
end

#tableObject



117
118
119
# File 'lib/data_mapper/persistence.rb', line 117

def table
  database.table(self)
end

#transactionObject



99
100
101
# File 'lib/data_mapper/persistence.rb', line 99

def transaction
  yield
end