dm-reflection 0.10.2 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +0 -1
- data/VERSION +1 -1
- data/dm-reflection.gemspec +2 -2
- data/lib/dm-reflection/adapters/mysql.rb +47 -8
- data/lib/dm-reflection/adapters/persevere.rb +33 -24
- data/lib/dm-reflection/adapters/postgres.rb +4 -0
- data/lib/dm-reflection/adapters/sqlite3.rb +4 -0
- data/lib/dm-reflection/reflection.rb +25 -8
- data/spec/persevere_reflection_spec.rb +0 -10
- metadata +4 -4
data/.gitignore
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.11.0
|
data/dm-reflection.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{dm-reflection}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.11.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Martin Gamsjaeger (snusnu), Yogo Team"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-06-09}
|
13
13
|
s.description = %q{Generates datamapper models from existing database schemas and export them to files}
|
14
14
|
s.email = %q{irjudson [a] gmail [d] com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -44,6 +44,10 @@ module DataMapper
|
|
44
44
|
}[$1] || raise("unknown type: #{db_type}")
|
45
45
|
end
|
46
46
|
|
47
|
+
def separator
|
48
|
+
'--'
|
49
|
+
end
|
50
|
+
|
47
51
|
##
|
48
52
|
# Get the list of table names
|
49
53
|
#
|
@@ -54,6 +58,23 @@ module DataMapper
|
|
54
58
|
select("SHOW FULL TABLES FROM #{options[:path][1..-1]} WHERE Table_type = 'BASE TABLE'").map { |item| item.first }
|
55
59
|
end
|
56
60
|
|
61
|
+
##
|
62
|
+
# This method breaks the join table into the two other table names
|
63
|
+
#
|
64
|
+
# @param [String] Name join table name
|
65
|
+
# @return [String,String] The two other table names joined.
|
66
|
+
#
|
67
|
+
def join_table_name(name, name_list=nil)
|
68
|
+
name_list = get_storage_names.sort if name_list.nil?
|
69
|
+
left = name_list[name_list.index(name)-1]
|
70
|
+
right = name[left.length+1..-1]
|
71
|
+
if name_list.include?(right)
|
72
|
+
return left,right
|
73
|
+
else
|
74
|
+
return nil,nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
57
78
|
##
|
58
79
|
# Get the column specifications for a specific table
|
59
80
|
#
|
@@ -65,8 +86,15 @@ module DataMapper
|
|
65
86
|
#
|
66
87
|
def get_properties(table)
|
67
88
|
# TODO: use SHOW INDEXES to find out unique and non-unique indexes
|
89
|
+
join_table = false
|
90
|
+
columns = select("SHOW COLUMNS FROM #{table} IN #{options[:path][1..-1]};")
|
68
91
|
|
69
|
-
|
92
|
+
if columns.length == 2 && columns[0].field.downcase[-3,3] == "_id" && columns[1].field.downcase[-3,3] == "_id"
|
93
|
+
left_table_name,right_table_name = join_table_name(table)
|
94
|
+
join_table = true
|
95
|
+
end
|
96
|
+
|
97
|
+
columns.map do |column|
|
70
98
|
type = get_type(column.type)
|
71
99
|
auto_increment = column.extra == 'auto_increment'
|
72
100
|
|
@@ -84,24 +112,35 @@ module DataMapper
|
|
84
112
|
:key => column.key == 'PRI',
|
85
113
|
}
|
86
114
|
|
87
|
-
|
115
|
+
# TODO: use the naming convention to compare the name vs the column name
|
116
|
+
unless attribute[:name] == column.field
|
117
|
+
attribute[:field] = column.field
|
118
|
+
end
|
119
|
+
|
120
|
+
if join_table
|
121
|
+
attribute[:type] = DataMapper::Associations::Relationship
|
122
|
+
attribute[:relationship] = {
|
123
|
+
# M:M requires we wire things a bit differently and remove the join model
|
124
|
+
:many_to_many => true,
|
125
|
+
:parent => Extlib::Inflection.classify(left_table_name),
|
126
|
+
:child => Extlib::Inflection.classify(right_table_name),
|
127
|
+
# When we can detect more from the database we can optimize this
|
128
|
+
:cardinality => Infinity,
|
129
|
+
:bidirectional => true }
|
130
|
+
return [attribute]
|
131
|
+
elsif type == Integer && field_name[-3,3] == "_id"
|
88
132
|
# This is a foriegn key. So this model belongs_to the other (_id) one.
|
89
133
|
# Add a special set of values and flag this as a relationship so the reflection code
|
90
134
|
# can rebuild the relationship when it's building the model.
|
91
135
|
attribute[:type] = DataMapper::Associations::Relationship
|
92
136
|
attribute[:relationship] = {
|
137
|
+
:many_to_many => false,
|
93
138
|
:parent => Extlib::Inflection.classify(field_name[0..-4]),
|
94
139
|
:child => Extlib::Inflection.classify(table),
|
95
140
|
# When we can detect more from the database we can optimize this
|
96
141
|
:cardinality => Infinity,
|
97
142
|
:bidirectional => true }
|
98
143
|
end
|
99
|
-
|
100
|
-
# TODO: use the naming convention to compare the name vs the column name
|
101
|
-
unless attribute[:name] == column.field
|
102
|
-
attribute[:field] = column.field
|
103
|
-
end
|
104
|
-
|
105
144
|
attribute
|
106
145
|
end
|
107
146
|
end
|
@@ -15,12 +15,14 @@ module DataMapper
|
|
15
15
|
#
|
16
16
|
chainable do
|
17
17
|
def get_type(db_type)
|
18
|
+
|
19
|
+
return :has_one_relation if db_type.has_key?("$ref")
|
20
|
+
|
18
21
|
type = db_type['type']
|
19
22
|
format = db_type['format']
|
20
23
|
|
21
24
|
case type
|
22
|
-
when
|
23
|
-
when 'array' then DataMapper::Types::JsonReferenceCollection
|
25
|
+
when 'array' then :has_many_relation
|
24
26
|
when 'serial' then DataMapper::Types::Serial
|
25
27
|
when 'integer' then Integer
|
26
28
|
# when 'number' then BigDecimal
|
@@ -36,6 +38,11 @@ module DataMapper
|
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
41
|
+
|
42
|
+
def separator
|
43
|
+
'/'
|
44
|
+
end
|
45
|
+
|
39
46
|
##
|
40
47
|
# Get the list of schema names
|
41
48
|
#
|
@@ -43,7 +50,7 @@ module DataMapper
|
|
43
50
|
#
|
44
51
|
def get_storage_names
|
45
52
|
@schemas = self.get_schema
|
46
|
-
@schemas.map { |schema| schema['id']
|
53
|
+
@schemas.map { |schema| schema['id'] }
|
47
54
|
end
|
48
55
|
|
49
56
|
##
|
@@ -57,32 +64,34 @@ module DataMapper
|
|
57
64
|
#
|
58
65
|
chainable do
|
59
66
|
def get_properties(table)
|
60
|
-
|
61
|
-
schema = self.get_schema(table
|
67
|
+
attributes = Array.new
|
68
|
+
schema = self.get_schema(table)[0]
|
62
69
|
schema['properties'].each_pair do |key, value|
|
63
70
|
type = get_type(value)
|
64
|
-
property = {:name => key, :type => type }
|
65
|
-
property.merge!({ :required => !value.delete('optional'),
|
66
|
-
:key => value.has_key?('index') && value.delete('index') }) unless property[:type] == DataMapper::Types::Serial
|
67
|
-
|
68
|
-
if type.kind_of?(DataMapper::Types::JsonReference)
|
69
|
-
property.merge!( {:reference => derive_relationship_model(value[:type]["$ref"])} )
|
70
|
-
end
|
71
71
|
|
72
|
-
|
73
|
-
property.merge!( {:reference => derive_relationship_model(value[:items]["$ref"])} )
|
74
|
-
end
|
72
|
+
attribute = { :name => key }
|
75
73
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
74
|
+
if type == :has_one_relation
|
75
|
+
# Has one
|
76
|
+
# Retrieve the other side to determine the cardinality
|
77
|
+
other_table = [table.split('/')[0..-2], value['$ref']].join("/")
|
78
|
+
other_schema = self.get_schema(other_table)[0]
|
79
|
+
|
80
|
+
elsif type == :has_many_relation
|
81
|
+
# Has many
|
82
|
+
# Retrieve the other side to determine the cardinality
|
83
|
+
other_table = [table.split('/')[0..-2], value['items']['$ref']].join("/")
|
84
|
+
other_schema = self.get_schema(other_table)[0]
|
85
|
+
|
86
|
+
else
|
87
|
+
attribute.merge!({ :type => type, :required => !value.delete('optional'), :key => value.has_key?('index') && value.delete('index') }) unless attribute[:type] == DataMapper::Types::Serial
|
88
|
+
['type', 'format', 'unique', 'index', 'items'].each { |key| value.delete(key) }
|
89
|
+
value.keys.each { |key| value[key.to_sym] = value[key]; value.delete(key) }
|
90
|
+
attribute.merge!(value)
|
91
|
+
attributes << attribute
|
92
|
+
end
|
84
93
|
end
|
85
|
-
return
|
94
|
+
return attributes
|
86
95
|
end
|
87
96
|
end
|
88
97
|
|
@@ -9,11 +9,11 @@ module DataMapper
|
|
9
9
|
#
|
10
10
|
def self.reflect(repository, namespace = Object, overwrite = false)
|
11
11
|
adapter = DataMapper.repository(repository).adapter
|
12
|
-
|
12
|
+
separator = adapter.separator
|
13
13
|
models = Hash.new
|
14
14
|
|
15
15
|
adapter.get_storage_names.each do |storage_name|
|
16
|
-
namespace_parts = storage_name.split(
|
16
|
+
namespace_parts = storage_name.split(separator).map do |part|
|
17
17
|
Extlib::Inflection.classify(part)
|
18
18
|
end
|
19
19
|
|
@@ -43,14 +43,26 @@ module DataMapper
|
|
43
43
|
models[model_name] = namespace.const_set(model_name, anonymous_model)
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
join_models = Array.new
|
47
|
+
|
48
|
+
models.each do |model_name, model|
|
47
49
|
adapter.get_properties(model.storage_name).each do |attribute|
|
48
50
|
if attribute[:type] == DataMapper::Associations::Relationship
|
49
51
|
parent = models[attribute[:relationship][:parent]]
|
50
52
|
child = models[attribute[:relationship][:child]]
|
51
|
-
|
52
|
-
|
53
|
-
|
53
|
+
if parent.nil? or child.nil?
|
54
|
+
puts "Reflection Relationship: P: #{parent.inspect} C: #{child.inspect} A: #{attribute[:relationship].inspect}"
|
55
|
+
end
|
56
|
+
if attribute[:relationship][:many_to_many]
|
57
|
+
parent.has(attribute[:relationship][:cardinality], child.name.tableize.pluralize.downcase.to_sym, :through => DataMapper::Resource, :model => child)
|
58
|
+
child.has(attribute[:relationship][:cardinality], parent.name.tableize.pluralize.downcase.to_sym, :through => DataMapper::Resource, :model => parent)
|
59
|
+
# Remove join model
|
60
|
+
join_models << model_name
|
61
|
+
else
|
62
|
+
child.belongs_to(parent.name.tableize.downcase.to_sym, :model => parent)
|
63
|
+
if attribute[:relationship][:bidirectional]
|
64
|
+
parent.has(attribute[:relationship][:cardinality], child.name.tableize.pluralize.downcase.to_sym, :model => child)
|
65
|
+
end
|
54
66
|
end
|
55
67
|
else
|
56
68
|
attribute.delete_if { |k,v| v.nil? }
|
@@ -58,8 +70,13 @@ module DataMapper
|
|
58
70
|
end
|
59
71
|
end
|
60
72
|
end
|
61
|
-
|
62
|
-
|
73
|
+
|
74
|
+
join_models.each do |model|
|
75
|
+
models.delete(model)
|
76
|
+
DataMapper::Model.descendants.delete(model)
|
77
|
+
end
|
78
|
+
|
79
|
+
models.values
|
63
80
|
end
|
64
81
|
end # module Reflection
|
65
82
|
|
@@ -28,8 +28,6 @@ if ENV['ADAPTER'] == 'persevere'
|
|
28
28
|
property :body, Text, :length => 65535, :lazy => true
|
29
29
|
property :updated_at, DateTime
|
30
30
|
property :score, Integer
|
31
|
-
property :blog_post, DataMapper::Types::JsonReference, :reference => :Post
|
32
|
-
|
33
31
|
|
34
32
|
end
|
35
33
|
RUBY
|
@@ -49,8 +47,6 @@ if ENV['ADAPTER'] == 'persevere'
|
|
49
47
|
}
|
50
48
|
|
51
49
|
@models.each_key { |model| Extlib::Inflection.constantize(model.to_s).auto_migrate! }
|
52
|
-
Post.send(:property, :comments, DataMapper::Types::JsonReferenceCollection, :reference => :PostComment)
|
53
|
-
Post.auto_upgrade!
|
54
50
|
@models.each_key { |model| remove_model_from_memory( Extlib::Inflection.constantize(model.to_s) ) }
|
55
51
|
end
|
56
52
|
|
@@ -75,12 +71,6 @@ if ENV['ADAPTER'] == 'persevere'
|
|
75
71
|
result = @adapter.get_properties("post")
|
76
72
|
result.should be_kind_of(Array)
|
77
73
|
end
|
78
|
-
|
79
|
-
it "should reflect out JsonReference types" do
|
80
|
-
DataMapper::Reflection.reflect(:default)
|
81
|
-
PostComment.properties[:blog_post].type.should eql DataMapper::Types::JsonReference
|
82
|
-
Post.properties[:comments].type.should eql DataMapper::Types::JsonReferenceCollection
|
83
|
-
end
|
84
74
|
|
85
75
|
end
|
86
76
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 11
|
8
|
+
- 0
|
9
|
+
version: 0.11.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Martin Gamsjaeger (snusnu), Yogo Team
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-06-09 00:00:00 -06:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|