module DataMapa::ClassMethods

Public Instance Methods

active_record_class(klass) click to toggle source

Declarative methods

# File lib/datamapa.rb, line 13
def active_record_class(klass)
  @ar_class = klass
end
aggregates(components) click to toggle source
# File lib/datamapa.rb, line 33
def aggregates(components)
  @aggregates = components
end
composed_of(parts) click to toggle source
# File lib/datamapa.rb, line 37
def composed_of(parts)
  @composed_of = parts
end
composes(parent) click to toggle source
# File lib/datamapa.rb, line 41
def composes(parent)
  @composes = parent
end
create!(model, extras={}) click to toggle source
# File lib/datamapa.rb, line 72
def create!(model, extras={})
  begin
    attributes = attribute_hash(model, extras)

    ar = @ar_class.create!(attributes)
    model.send(:id=, ar.id)

    @composed_of.each do |parts, mapper|
      mapper.create_parts!(model.send(parts), model.id)
    end if @composed_of
    model
  rescue ActiveRecord::StatementInvalid => e
    raise DataMapa::PersistenceError, e.message
  end
end
creates_model_with(&block) click to toggle source
# File lib/datamapa.rb, line 17
def creates_model_with(&block)
  @create_model_proc = block
end
delete!(id) click to toggle source
# File lib/datamapa.rb, line 111
def delete!(id)
  @composed_of.each do |part, mapper|
    mapper.delete_children_of(id)
  end if @composed_of

  count = @ar_class.delete(id)
end
exists?(model) click to toggle source
# File lib/datamapa.rb, line 56
def exists?(model)
  if model.id.nil?
    load_id_with_semantic_key(model) unless @semantic_key.nil?
    !model.id.nil?
  else
    @ar_class.exists?(model.id)
  end
end
find!(id) click to toggle source

Public methods

# File lib/datamapa.rb, line 47
def find!(id)
  begin
    ar = @ar_class.find(id)
    model_for(ar)
  rescue ActiveRecord::RecordNotFound
    raise DataMapa::RecordNotFoundError
  end
end
model_for(ar) click to toggle source
# File lib/datamapa.rb, line 119
def model_for(ar)
  model = @create_model_proc.call(ar)
  r2o(ar, model)
  model.id = ar.id
  model
end
ref_attr(attributes) click to toggle source
# File lib/datamapa.rb, line 29
def ref_attr(attributes)
  @ref_attr = attributes
end
save!(model, extras={}) click to toggle source
# File lib/datamapa.rb, line 102
def save!(model, extras={})
  load_id_with_semantic_key(model) unless @semantic_key.nil?
  if model.id.nil?
    create!(model)
  else
    update(model)
  end
end
semantic_key(key) click to toggle source
# File lib/datamapa.rb, line 21
def semantic_key(key)
  @semantic_key = key
end
simple_attr(attributes) click to toggle source
# File lib/datamapa.rb, line 25
def simple_attr(attributes)
  @simple_attr = attributes
end
update(model, extras={}) click to toggle source
# File lib/datamapa.rb, line 88
def update(model, extras={})
  begin
    attributes = attribute_hash(model, extras)

    @ar_class.update(model.id, attributes)

    @composed_of.each do |parts, mapper|
      mapper.update_parts!(model.send(parts), model.id)
    end if @composed_of
  rescue ActiveRecord::StatementInvalid => e
    raise DataMapa::PersistenceError, e.message
  end
end
where(clause) click to toggle source
# File lib/datamapa.rb, line 65
def where(clause)
  records = @ar_class.where(clause) 
  records.map do |ar|
    model_for(ar)
  end
end

Protected Instance Methods

create_parts!(parts, parent_id) click to toggle source
# File lib/datamapa.rb, line 128
def create_parts!(parts, parent_id)
  parts.each_with_index do |item, i|
    create!(item, "#{@composes}_id".to_sym => parent_id, :index => i)
  end
end
delete_children_of(id) click to toggle source
# File lib/datamapa.rb, line 147
def delete_children_of(id)
  @ar_class.delete_all(["#{@composes}_id = ?", id])
end
update_parts!(parts, parent_id) click to toggle source
# File lib/datamapa.rb, line 134
def update_parts!(parts, parent_id)
  existing_ids = parts.map(&:id).reject { |id| id.nil? }
  @ar_class.where(composes_column => parent_id).where.not(id: existing_ids).delete_all

  parts.each_with_index do |item, i|
    if item.id.nil?
      create!(item, composes_column => parent_id, :index => i)
    else
      update(item, composes_column => parent_id, :index => i)
    end
  end
end

Private Instance Methods

attribute_hash(model, extras) click to toggle source
# File lib/datamapa.rb, line 153
def attribute_hash(model, extras)
  attributes = {}

  @simple_attr.each do |attr|
    attributes[:"#{attr.to_s.chomp('?')}"] = model.send(attr)
  end if @simple_attr

  @ref_attr.each_key do |attr|
    ref = model.send(attr)
    attributes[:"#{attr.to_s.chomp('?')}_id"] = ref.id unless ref.nil?
  end if @ref_attr

  extras.each_pair { |key, value| attributes[:"#{key}"] = value }

  attributes
end
composes_column() click to toggle source
# File lib/datamapa.rb, line 179
def composes_column
  "#{@composes}_id".to_sym
end
load_id_with_semantic_key(model) click to toggle source
# File lib/datamapa.rb, line 170
def load_id_with_semantic_key(model)
  clause = @semantic_key.inject({}) do |memo, attr|
    memo[attr] = model.send(attr)
    memo
  end
  ar = @ar_class.find_by(clause)
  model.id = ar.id unless ar.nil?
end
model_name() click to toggle source
# File lib/datamapa.rb, line 217
def model_name
  name.chomp('Mapper').downcase
end
r2o(ar, model) click to toggle source
# File lib/datamapa.rb, line 183
def r2o(ar, model)
  r2o_simple(ar, model)
  r2o_ref(ar, model)
  r2o_collection(ar, model, @composed_of) if @composed_of
  model
end
r2o_collection(ar, model, attributes) click to toggle source
# File lib/datamapa.rb, line 210
def r2o_collection(ar, model, attributes)
  attributes.each do |attr, mapper|
    model_items = mapper.where(where_clause_for_references_to(ar.id))
    model.send("#{attr}=", model_items)
  end
end
r2o_ref(ar, object) click to toggle source
# File lib/datamapa.rb, line 197
def r2o_ref(ar, object)
  @ref_attr.each do |attr, mapper|
    model = mapper.find!(ar.send("#{attr}_id"))

    setter = "#{attr}="
    object.send(setter, model)
  end if @ref_attr
end
r2o_simple(relational, object) click to toggle source
# File lib/datamapa.rb, line 190
def r2o_simple(relational, object)
  @simple_attr.each do |attr|
    setter = "#{attr.to_s.chomp('?')}="
    object.send(setter, relational.send(attr))
  end if @simple_attr
end
where_clause_for_references_to(id) click to toggle source
# File lib/datamapa.rb, line 206
def where_clause_for_references_to(id)
  {"#{model_name}_id".to_sym => id}
end