dm-is-reflective 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,64 +0,0 @@
1
-
2
- module DataMapper
3
- module Is::Reflective
4
- module MysqlAdapter
5
- include DataMapper
6
-
7
- def storages
8
- select('SHOW TABLES')
9
- end
10
-
11
- private
12
- # construct needed table metadata
13
- def reflective_query_storage storage
14
- sql = <<-SQL
15
- SELECT column_name, column_default, is_nullable, data_type,
16
- character_maximum_length, column_key, extra
17
- FROM `information_schema`.`columns`
18
- WHERE `table_schema` = ? AND `table_name` = ?
19
- SQL
20
-
21
- select(Ext::String.compress_lines(sql),
22
- options[:path].sub('/', ''), storage)
23
- end
24
-
25
- def reflective_field_name field
26
- field.column_name
27
- end
28
-
29
- def reflective_primitive field
30
- field.data_type
31
- end
32
-
33
- def reflective_attributes field, attrs = {}
34
- attrs[:serial] = true if field.extra == 'auto_increment'
35
- attrs[:key] = true if field.column_key == 'PRI'
36
-
37
- attrs[:allow_nil] = field.is_nullable == 'YES'
38
- attrs[:default] = field.column_default if
39
- field.column_default
40
-
41
- attrs[:length] = field.character_maximum_length if
42
- field.character_maximum_length
43
-
44
- attrs
45
- end
46
-
47
- def reflective_lookup_primitive primitive
48
- case primitive.upcase
49
- when 'YEAR' ; Integer
50
- when /\w*INT(EGER)?( SIGNED| UNSIGNED)?( ZEROFILL)?/
51
- ; Integer
52
- when /(DOUBLE|FLOAT|DECIMAL)( SIGNED| UNSIGNED)?( ZEROFILL)?/
53
- ; BigDecimal
54
- when /\w*BLOB|\w*BINARY|ENUM|SET|CHAR/; String
55
- when 'TIME' ; Time
56
- when 'DATE' ; Date
57
- when 'DATETIME', 'TIMESTAMP' ; DateTime
58
- when 'BOOL', 'BOOLEAN' ; Property::Boolean
59
- when /\w*TEXT/ ; Property::Text
60
- end || super(primitive)
61
- end
62
- end
63
- end
64
- end
@@ -1,82 +0,0 @@
1
-
2
- module DataMapper
3
- module Is::Reflective
4
- module PostgresAdapter
5
- include DataMapper
6
-
7
- def storages
8
- sql = <<-SQL
9
- SELECT table_name FROM "information_schema"."tables"
10
- WHERE table_schema = current_schema()
11
- SQL
12
-
13
- select(Ext::String.compress_lines(sql))
14
- end
15
-
16
- private
17
- def reflective_query_storage storage
18
- sql = <<-SQL
19
- SELECT column_name FROM "information_schema"."key_column_usage"
20
- WHERE table_schema = current_schema() AND table_name = ?
21
- SQL
22
-
23
- keys = select(Ext::String.compress_lines(sql), storage).to_set
24
-
25
- sql = <<-SQL
26
- SELECT column_name, column_default, is_nullable,
27
- character_maximum_length, udt_name
28
- FROM "information_schema"."columns"
29
- WHERE table_schema = current_schema() AND table_name = ?
30
- SQL
31
-
32
- select(Ext::String.compress_lines(sql), storage).map{ |struct|
33
- struct.instance_eval <<-END_EVAL
34
- def key?
35
- #{keys.member?(struct.column_name)}
36
- end
37
- END_EVAL
38
- struct
39
- }
40
- end
41
-
42
- def reflective_field_name field
43
- field.column_name
44
- end
45
-
46
- def reflective_primitive field
47
- field.udt_name
48
- end
49
-
50
- def reflective_attributes field, attrs = {}
51
- # strip data type
52
- field.column_default.gsub!(/(.*?)::[\w\s]*/, '\1') if field.column_default
53
-
54
- attrs[:serial] = true if field.column_default =~ /nextval\('\w+'\)/
55
- attrs[:key] = true if field.key?
56
- attrs[:allow_nil] = field.is_nullable == 'YES'
57
- # strip string quotation
58
- attrs[:default] = field.column_default.gsub(/^'(.*?)'$/, '\1') if
59
- field.column_default && !attrs[:serial]
60
-
61
- if field.character_maximum_length
62
- attrs[:length] = field.character_maximum_length
63
- elsif field.udt_name.upcase == 'TEXT'
64
- attrs[:length] = Property::Text.length
65
- end
66
-
67
- attrs
68
- end
69
-
70
- def reflective_lookup_primitive primitive
71
- case primitive.upcase
72
- when /^INT\d+$/ ; Integer
73
- when /^FLOAT\d+$/ ; Float
74
- when 'VARCHAR', 'BPCHAR'; String
75
- when 'TIMESTAMP', 'DATE'; DateTime
76
- when 'TEXT' ; Property::Text
77
- when 'BOOL' ; Property::Boolean
78
- end || super(primitive)
79
- end
80
- end
81
- end
82
- end
@@ -1,61 +0,0 @@
1
-
2
- module DataMapper
3
- module Is::Reflective
4
- module SqliteAdapter
5
- include DataMapper
6
-
7
- def storages
8
- sql = <<-SQL
9
- SELECT name
10
- FROM sqlite_master
11
- WHERE type = 'table' AND NOT name = 'sqlite_sequence'
12
- SQL
13
-
14
- select(Ext::String.compress_lines(sql))
15
- end
16
-
17
- private
18
- def reflective_query_storage storage
19
- select('PRAGMA table_info(?)', storage)
20
- end
21
-
22
- def reflective_field_name field
23
- field.name
24
- end
25
-
26
- def reflective_primitive field
27
- field.type.gsub(/\(\d+\)/, '')
28
- end
29
-
30
- def reflective_attributes field, attrs = {}
31
- if field.pk != 0
32
- attrs[:key] = true
33
- attrs[:serial] = true if supports_serial?
34
- end
35
- attrs[:allow_nil] = field.notnull == 0
36
- attrs[:default] = field.dflt_value[1..-2] if field.dflt_value
37
-
38
- if field.type.upcase == 'TEXT'
39
- attrs[:length] = Property::Text.length
40
- else
41
- ergo = field.type.match(/\((\d+)\)/)
42
- size = ergo && ergo[1].to_i
43
- attrs[:length] = size if size
44
- end
45
-
46
- attrs
47
- end
48
-
49
- def reflective_lookup_primitive primitive
50
- case primitive.upcase
51
- when 'INTEGER' ; Integer
52
- when 'REAL', 'NUMERIC'; Float
53
- when 'VARCHAR' ; String
54
- when 'TIMESTAMP' ; DateTime
55
- when 'BOOLEAN' ; Property::Boolean
56
- when 'TEXT' ; Property::Text
57
- end || super(primitive)
58
- end
59
- end
60
- end
61
- end
@@ -1,252 +0,0 @@
1
-
2
- require 'dm-core'
3
- require 'dm-migrations'
4
- require 'dm-is-reflective'
5
-
6
- module Abstract
7
- def self.next_id
8
- @id ||= 0
9
- @id += 1
10
- end
11
-
12
- AttrCommon = {:allow_nil => true}
13
- AttrCommonPK = {:serial => true, :key => true, :allow_nil => false}
14
- AttrText = {:length => 65535}.merge(AttrCommon)
15
-
16
- def user_fields
17
- [[:created_at, DateTime, AttrCommon],
18
- [:id, DataMapper::Property::Serial, AttrCommonPK],
19
- [:login, String, {:length => 70}.merge(AttrCommon)],
20
- [:sig, DataMapper::Property::Text, AttrText]]
21
- end
22
-
23
- def comment_fields
24
- [[:body, DataMapper::Property::Text, AttrText],
25
- [:id, DataMapper::Property::Serial, AttrCommonPK],
26
- [:title, String, {:length => 50, :default => 'default title',
27
- :allow_nil => false}],
28
- [:user_id, Integer, AttrCommon]]
29
- end
30
-
31
- # there's differences between adapters
32
- def super_user_fields
33
- Object.const_set(:MysqlTest, Class.new) unless defined?(MysqlTest) # dummy
34
- case self
35
- when MysqlTest # Mysql couldn't tell it's boolean or tinyint
36
- [[:bool, Integer, AttrCommon],
37
- [:id, DataMapper::Property::Serial, AttrCommonPK]]
38
-
39
- else
40
- [[:bool, DataMapper::Property::Boolean, AttrCommon],
41
- [:id, DataMapper::Property::Serial, AttrCommonPK]]
42
-
43
- end
44
- end
45
-
46
- class User
47
- include DataMapper::Resource
48
- has n, :comments
49
-
50
- property :id, Serial
51
- property :login, String, :length => 70
52
- property :sig, Text
53
- property :created_at, DateTime
54
-
55
- is :reflective
56
- end
57
-
58
- class SuperUser
59
- include DataMapper::Resource
60
- property :id, Serial
61
- property :bool, Boolean
62
-
63
- is :reflective
64
- end
65
-
66
- class Comment
67
- include DataMapper::Resource
68
- belongs_to :user, :required => false
69
-
70
- property :id, Serial
71
- property :title, String, :length => 50, :default => 'default title',
72
- :allow_nil => false
73
- property :body, Text
74
-
75
- is :reflective
76
- end
77
-
78
- Tables = ['abstract_comments', 'abstract_super_users', 'abstract_users']
79
-
80
- def sort_fields fields
81
- fields.sort_by{ |field|
82
- field.first.to_s
83
- }
84
- end
85
-
86
- def create_fake_model
87
- model = Class.new
88
- model.module_eval do
89
- include DataMapper::Resource
90
- property :id, DataMapper::Property::Serial
91
- is :reflective
92
- end
93
- Abstract.const_set("Model#{Abstract.next_id}", model)
94
- [model, self.class.setup_data_mapper]
95
- end
96
-
97
- attr_reader :dm
98
- def setup
99
- @dm = self.class.setup_data_mapper
100
- [User, Comment, SuperUser].each(&:auto_migrate!)
101
- end
102
-
103
- def new_scope
104
- self.class.const_set("Scope#{object_id.object_id}", Module.new)
105
- end
106
-
107
- def test_storages
108
- assert_equal Tables, dm.storages.sort
109
- assert_equal comment_fields, sort_fields(dm.fields('abstract_comments'))
110
- end
111
-
112
- def test_create_comment
113
- Comment.create(:title => 'XD')
114
- assert_equal 'XD', Comment.first.title
115
- end
116
-
117
- def test_create_user
118
- now = Time.now
119
- User.create(:created_at => now)
120
- assert_equal now.asctime, User.first.created_at.asctime
121
-
122
- return now
123
- end
124
-
125
- def test_reflect_all
126
- test_create_comment # for fixtures
127
- model, local_dm = create_fake_model
128
- model.storage_names[:default] = 'abstract_comments'
129
-
130
- assert_equal Tables, local_dm.storages.sort
131
- assert_equal 'abstract_comments', model.storage_name
132
-
133
- model.send :reflect
134
- assert_equal 1, model.all.size
135
- assert_equal comment_fields, sort_fields(model.fields)
136
-
137
- assert_equal 'XD', model.first.title
138
- end
139
-
140
- def test_reflect_and_create
141
- model, local_dm = create_fake_model
142
- model.storage_names[:default] = 'abstract_comments'
143
- model.send :reflect
144
-
145
- model.create(:title => 'orz')
146
- assert_equal 'orz', model.first.title
147
-
148
- model.create
149
- assert_equal 'default title', model.last.title
150
- end
151
-
152
- def test_storages_and_fields
153
- assert_equal user_fields, sort_fields(dm.fields('abstract_users'))
154
- assert_equal( {'abstract_users' => user_fields,
155
- 'abstract_comments' => comment_fields,
156
- 'abstract_super_users' => super_user_fields},
157
- dm.storages_and_fields.inject({}){ |r, i|
158
- key, value = i
159
- r[key] = value.sort_by{ |v| v.first.to_s }
160
- r
161
- } )
162
- end
163
-
164
- def test_reflect_type
165
- model, local_dm = create_fake_model
166
- model.storage_names[:default] = 'abstract_comments'
167
-
168
- model.send :reflect, DataMapper::Property::Serial
169
- assert_equal ['id'], model.properties.map(&:name).map(&:to_s).sort
170
-
171
- model.send :reflect, Integer
172
- assert_equal ['id', 'user_id'], model.properties.map(&:name).map(&:to_s).sort
173
- end
174
-
175
- def test_reflect_multiple
176
- model, local_dm = create_fake_model
177
- model.storage_names[:default] = 'abstract_users'
178
- model.send :reflect, :login, DataMapper::Property::Serial
179
-
180
- assert_equal ['id', 'login'], model.properties.map(&:name).map(&:to_s).sort
181
- end
182
-
183
- def test_reflect_regexp
184
- model, local_dm = create_fake_model
185
- model.storage_names[:default] = 'abstract_comments'
186
- model.send :reflect, /id$/
187
-
188
- assert_equal ['id', 'user_id'], model.properties.map(&:name).map(&:to_s).sort
189
- end
190
-
191
- def test_invalid_argument
192
- assert_raises(ArgumentError){
193
- User.send :reflect, 29
194
- }
195
- end
196
-
197
- def test_allow_empty_string
198
- assert Comment.new(:title => '').save
199
- end
200
-
201
- def test_auto_genclasses
202
- scope = new_scope
203
- assert_equal ["#{scope == Object ? '' : "#{scope}::"}AbstractComment",
204
- "#{scope}::AbstractSuperUser",
205
- "#{scope}::AbstractUser"],
206
- dm.auto_genclass!(:scope => scope).map(&:to_s).sort
207
-
208
- comment = scope.const_get('AbstractComment')
209
-
210
- assert_equal comment_fields, sort_fields(comment.fields)
211
-
212
- test_create_comment
213
-
214
- assert_equal 'XD', comment.first.title
215
- comment.create(:title => 'orz', :body => 'dm-reflect')
216
- assert_equal 'dm-reflect', comment.last.body
217
- end
218
-
219
- def test_auto_genclass
220
- scope = new_scope
221
- assert_equal ["#{scope}::AbstractUser"],
222
- dm.auto_genclass!(:scope => scope,
223
- :storages => 'abstract_users').map(&:to_s)
224
-
225
- user = scope.const_get('AbstractUser')
226
- assert_equal user_fields, sort_fields(user.fields)
227
-
228
- now = test_create_user
229
-
230
- assert_equal now.asctime, user.first.created_at.asctime
231
- user.create(:login => 'godfat')
232
- assert_equal 'godfat', user.last.login
233
- end
234
-
235
- def test_auto_genclass_with_regexp
236
- scope = new_scope
237
- assert_equal ["#{scope}::AbstractSuperUser", "#{scope}::AbstractUser"],
238
- dm.auto_genclass!(:scope => scope,
239
- :storages => /_users$/).map(&:to_s).sort
240
-
241
- user = scope.const_get('AbstractSuperUser')
242
- assert_equal sort_fields(SuperUser.fields), sort_fields(user.fields)
243
- end
244
-
245
- def test_reflect_return_value
246
- model, local_dm = create_fake_model
247
- model.storage_names[:default] = 'abstract_comments'
248
- mapped = model.send :reflect, /.*/
249
-
250
- assert_equal model.properties.map(&:object_id).sort, mapped.map(&:object_id).sort
251
- end
252
- end