Module: DataMapper::Reflection

Defined in:
lib/dm-reflection/reflection.rb,
lib/dm-reflection/adapters/mysql.rb,
lib/dm-reflection/adapters/sqlite3.rb,
lib/dm-reflection/adapters/postgres.rb,
lib/dm-reflection/adapters/persevere.rb,
lib/dm-reflection/builders/source_builder.rb

Defined Under Namespace

Modules: Builders, MysqlAdapter, PersevereAdapter, PostgresAdapter, Sqlite3Adapter

Class Method Summary collapse

Class Method Details

.reflect(repository, namespace = Object, overwrite = false) ⇒ DataMapper::Model Array

Main reflection method reflects models out of a repository.

Parameters:

  • repository (Slug)

    is the key to the repository that will be reflected.

  • namespace (Constant) (defaults to: Object)

    is the namespace into which the reflected models will be added

  • overwrite (Boolean) (defaults to: false)

    indicates the reflected models should replace existing models or not.

Returns:

  • (DataMapper::Model Array)

    the reflected models.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/dm-reflection/reflection.rb', line 10

def self.reflect(repository, namespace = Object, overwrite = false)
  adapter = DataMapper.repository(repository).adapter
  separator = adapter.separator
  models  = Hash.new

  adapter.get_storage_names.each do |storage_name|
    namespace_parts = storage_name.split(separator).map do |part|
      ActiveSupport::Inflector.classify(part)
    end

    model_name = namespace_parts.pop

    namespace = if namespace_parts.any?
      Object.make_module(namespace_parts.join('::'))
    else
      Object
    end

    next if namespace.const_defined?(model_name) && !overwrite

    anonymous_model = DataMapper::Model.new do
      class_eval <<-RUBY, __FILE__, __LINE__
        storage_names[#{repository.inspect}]='#{storage_name}'
      RUBY
      unless repository == DataMapper::Repository.default_name
        class_eval <<-RUBY, __FILE__, __LINE__
          def self.default_repository_name
            #{repository.inspect}
          end
        RUBY
      end
    end
    
    full_name = namespace_parts.length > 0 ? [namespace_parts, model_name].join('::') : model_name
    models[full_name] = namespace.const_set(model_name, anonymous_model)
  end

  join_models = Array.new
  
  models.each do |model_name, model|
    adapter.get_properties(model.storage_name).each do |attribute|
      if attribute[:type] == :many_to_many
        attribute.delete(:type)
        attribute.delete(:name)
        relationship = attribute.delete(:relationship)
        parent = models[relationship.delete(:parent)]
        child = models[relationship.delete(:child)]
        cardinality = relationship.delete(:cardinality)
        parent.has(cardinality, relationship[:child_name].to_sym, attribute.merge({:through => DataMapper::Resource, :model => child}))
        child.has(cardinality, relationship[:parent_name].to_sym, attribute.merge({:through => DataMapper::Resource, :model => parent}))
        join_models << model_name
      elsif attribute[:type] == :has_n
        attribute.delete(:type)
        model.has(attribute.delete(:cardinality), attribute.delete(:name).to_sym, attribute)
      elsif attribute[:type] == :belongs_to
        attribute.delete(:type)
        other_side = attribute.delete(:other_side)
        name = attribute.delete(:name)
#            puts "#{model.name}.belongs_to(#{name}, #{attribute.inspect})"
        model.belongs_to(name.to_sym, attribute.dup)
        unless other_side.nil?
          other_name = other_side.delete(:name)
          cardinality = other_side.delete(:cardinality)
          other_side[:model] = ActiveSupport::Inflector.singularize(model)
#              puts "#{models[attribute[:model]]}.has(#{cardinality}, #{other_name}, #{other_side.inspect})"
          models[attribute[:model]].has(cardinality, other_name.to_sym, other_side)
        end
      else
        attribute.delete_if { |k,v| v.nil? }
        model.property(attribute.delete(:name).to_sym, attribute.delete(:type), attribute)
      end
    end
  end
      
  join_models.each do |model|
    models.delete(model)
    DataMapper::Model.descendants.delete(model)
  end

  models.values
end