dm-is-reflective 1.1.0 → 1.2.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.
@@ -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