dm-is-reflective 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/.gita/COMMIT_EDITMSG +9 -0
  2. data/.gita/HEAD +1 -0
  3. data/.gita/ORIG_HEAD +1 -0
  4. data/.gita/RENAMED-REF +1 -0
  5. data/.gita/config +9 -0
  6. data/.gita/description +1 -0
  7. data/.gita/gitk.cache +6 -0
  8. data/.gita/hooks/applypatch-msg +15 -0
  9. data/.gita/hooks/commit-msg +24 -0
  10. data/.gita/hooks/post-commit +8 -0
  11. data/.gita/hooks/post-receive +16 -0
  12. data/.gita/hooks/post-update +8 -0
  13. data/.gita/hooks/pre-applypatch +14 -0
  14. data/.gita/hooks/pre-commit +70 -0
  15. data/.gita/hooks/pre-rebase +150 -0
  16. data/.gita/hooks/prepare-commit-msg +36 -0
  17. data/.gita/hooks/update +107 -0
  18. data/.gita/index +0 -0
  19. data/.gita/info/exclude +6 -0
  20. data/.gita/info/refs +26 -0
  21. data/.gita/logs/HEAD +40 -0
  22. data/.gita/logs/refs/heads/dm-mapping +1 -0
  23. data/.gita/logs/refs/heads/master +40 -0
  24. data/.gita/logs/refs/heads/return-symbol +0 -0
  25. data/.gita/logs/refs/remotes/origin/dm-mapping +1 -0
  26. data/.gita/logs/refs/remotes/origin/master +6 -0
  27. data/.gita/logs/refs/remotes/origin/return-symbol +0 -0
  28. data/.gita/objects/5c/91380a1616b7c2d23e14eeb49d9edde58e1f47 +2 -0
  29. data/.gita/objects/63/71947bcb9c0dd1d3b3d6f449b2d4b4c6c81e63 +0 -0
  30. data/.gita/objects/73/23ae22118cc54fb0bbb0d6f51cc99191019b96 +0 -0
  31. data/.gita/objects/81/a0ab6e4dbd148faa0644307b313799027d3344 +2 -0
  32. data/.gita/objects/b2/9571a21e3bccb60079dfca630dac981f623489 +5 -0
  33. data/.gita/objects/cb/138acf9efc0f5b3ff91c644cae4dec868442e4 +5 -0
  34. data/.gita/objects/d5/66699fc7ba5237311cc44648d0cd2abbaa895e +0 -0
  35. data/.gita/objects/info/packs +2 -0
  36. data/.gita/objects/pack/pack-c9156ef3406b98f5f12875b13643df7a5f41e42c.idx +0 -0
  37. data/.gita/objects/pack/pack-c9156ef3406b98f5f12875b13643df7a5f41e42c.pack +0 -0
  38. data/.gita/packed-refs +27 -0
  39. data/.gita/refs/heads/master +1 -0
  40. data/.gita/refs/tags/dm-is-reflective-0.8.0 +1 -0
  41. data/CHANGES +189 -0
  42. data/LICENSE +201 -0
  43. data/NOTICE +30 -0
  44. data/README +122 -0
  45. data/Rakefile +45 -0
  46. data/TODO +7 -0
  47. data/dm-is-reflective.gemspec +41 -0
  48. data/lib/dm-is-reflective.rb +10 -0
  49. data/lib/dm-is-reflective/is/adapters/abstract_adapter.rb +144 -0
  50. data/lib/dm-is-reflective/is/adapters/mysql_adapter.rb +62 -0
  51. data/lib/dm-is-reflective/is/adapters/postgres_adapter.rb +84 -0
  52. data/lib/dm-is-reflective/is/adapters/sqlite3_adapter.rb +61 -0
  53. data/lib/dm-is-reflective/is/reflective.rb +78 -0
  54. data/lib/dm-is-reflective/is/version.rb +7 -0
  55. data/lib/dm-is-reflective/version.rb +7 -0
  56. data/tasks/ann.rake +80 -0
  57. data/tasks/bones.rake +20 -0
  58. data/tasks/gem.rake +201 -0
  59. data/tasks/git.rake +40 -0
  60. data/tasks/notes.rake +27 -0
  61. data/tasks/post_load.rake +34 -0
  62. data/tasks/rdoc.rake +51 -0
  63. data/tasks/rubyforge.rake +55 -0
  64. data/tasks/setup.rb +294 -0
  65. data/tasks/spec.rake +54 -0
  66. data/tasks/svn.rake +47 -0
  67. data/tasks/test.rake +40 -0
  68. data/tasks/zentest.rake +36 -0
  69. data/test/abstract.rb +250 -0
  70. data/test/test_dm-is-reflexible.rb +48 -0
  71. metadata +203 -0
data/tasks/spec.rake ADDED
@@ -0,0 +1,54 @@
1
+
2
+ if HAVE_SPEC_RAKE_SPECTASK and not PROJ.spec.files.to_a.empty?
3
+ require 'spec/rake/verify_rcov'
4
+
5
+ namespace :spec do
6
+
7
+ desc 'Run all specs with basic output'
8
+ Spec::Rake::SpecTask.new(:run) do |t|
9
+ t.ruby_opts = PROJ.ruby_opts
10
+ t.spec_opts = PROJ.spec.opts
11
+ t.spec_files = PROJ.spec.files
12
+ t.libs += PROJ.libs
13
+ end
14
+
15
+ desc 'Run all specs with text output'
16
+ Spec::Rake::SpecTask.new(:specdoc) do |t|
17
+ t.ruby_opts = PROJ.ruby_opts
18
+ t.spec_opts = PROJ.spec.opts + ['--format', 'specdoc']
19
+ t.spec_files = PROJ.spec.files
20
+ t.libs += PROJ.libs
21
+ end
22
+
23
+ if HAVE_RCOV
24
+ desc 'Run all specs with RCov'
25
+ Spec::Rake::SpecTask.new(:rcov) do |t|
26
+ t.ruby_opts = PROJ.ruby_opts
27
+ t.spec_opts = PROJ.spec.opts
28
+ t.spec_files = PROJ.spec.files
29
+ t.libs += PROJ.libs
30
+ t.rcov = true
31
+ t.rcov_dir = PROJ.rcov.dir
32
+ t.rcov_opts = PROJ.rcov.opts + ['--exclude', 'spec']
33
+ end
34
+
35
+ RCov::VerifyTask.new(:verify) do |t|
36
+ t.threshold = PROJ.rcov.threshold
37
+ t.index_html = File.join(PROJ.rcov.dir, 'index.html')
38
+ t.require_exact_threshold = PROJ.rcov.threshold_exact
39
+ end
40
+
41
+ task :verify => :rcov
42
+ remove_desc_for_task %w(spec:clobber_rcov)
43
+ end
44
+
45
+ end # namespace :spec
46
+
47
+ desc 'Alias to spec:run'
48
+ task :spec => 'spec:run'
49
+
50
+ task :clobber => 'spec:clobber_rcov' if HAVE_RCOV
51
+
52
+ end # if HAVE_SPEC_RAKE_SPECTASK
53
+
54
+ # EOF
data/tasks/svn.rake ADDED
@@ -0,0 +1,47 @@
1
+
2
+ if HAVE_SVN
3
+
4
+ unless PROJ.svn.root
5
+ info = %x/svn info ./
6
+ m = %r/^Repository Root:\s+(.*)$/.match(info)
7
+ PROJ.svn.root = (m.nil? ? '' : m[1])
8
+ end
9
+ PROJ.svn.root = File.join(PROJ.svn.root, PROJ.svn.path) unless PROJ.svn.path.empty?
10
+
11
+ namespace :svn do
12
+
13
+ # A prerequisites task that all other tasks depend upon
14
+ task :prereqs
15
+
16
+ desc 'Show tags from the SVN repository'
17
+ task :show_tags => 'svn:prereqs' do |t|
18
+ tags = %x/svn list #{File.join(PROJ.svn.root, PROJ.svn.tags)}/
19
+ tags.gsub!(%r/\/$/, '')
20
+ tags = tags.split("\n").sort {|a,b| b <=> a}
21
+ puts tags
22
+ end
23
+
24
+ desc 'Create a new tag in the SVN repository'
25
+ task :create_tag => 'svn:prereqs' do |t|
26
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
27
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
28
+
29
+ svn = PROJ.svn
30
+ trunk = File.join(svn.root, svn.trunk)
31
+ tag = "%s-%s" % [PROJ.name, PROJ.version]
32
+ tag = File.join(svn.root, svn.tags, tag)
33
+ msg = "Creating tag for #{PROJ.name} version #{PROJ.version}"
34
+
35
+ puts "Creating SVN tag '#{tag}'"
36
+ unless system "svn cp -m '#{msg}' #{trunk} #{tag}"
37
+ abort "Tag creation failed"
38
+ end
39
+ end
40
+
41
+ end # namespace :svn
42
+
43
+ task 'gem:release' => 'svn:create_tag'
44
+
45
+ end # if PROJ.svn.path
46
+
47
+ # EOF
data/tasks/test.rake ADDED
@@ -0,0 +1,40 @@
1
+
2
+ if test(?e, PROJ.test.file) or not PROJ.test.files.to_a.empty?
3
+ require 'rake/testtask'
4
+
5
+ namespace :test do
6
+
7
+ Rake::TestTask.new(:run) do |t|
8
+ t.libs = PROJ.libs
9
+ t.test_files = if test(?f, PROJ.test.file) then [PROJ.test.file]
10
+ else PROJ.test.files end
11
+ t.ruby_opts += PROJ.ruby_opts
12
+ t.ruby_opts += PROJ.test.opts
13
+ end
14
+
15
+ if HAVE_RCOV
16
+ desc 'Run rcov on the unit tests'
17
+ task :rcov => :clobber_rcov do
18
+ opts = PROJ.rcov.opts.dup << '-o' << PROJ.rcov.dir
19
+ opts = opts.join(' ')
20
+ files = if test(?f, PROJ.test.file) then [PROJ.test.file]
21
+ else PROJ.test.files end
22
+ files = files.join(' ')
23
+ sh "#{RCOV} #{files} #{opts}"
24
+ end
25
+
26
+ task :clobber_rcov do
27
+ rm_r 'coverage' rescue nil
28
+ end
29
+ end
30
+
31
+ end # namespace :test
32
+
33
+ desc 'Alias to test:run'
34
+ task :test => 'test:run'
35
+
36
+ task :clobber => 'test:clobber_rcov' if HAVE_RCOV
37
+
38
+ end
39
+
40
+ # EOF
@@ -0,0 +1,36 @@
1
+ if HAVE_ZENTEST
2
+
3
+ # --------------------------------------------------------------------------
4
+ if test(?e, PROJ.test.file) or not PROJ.test.files.to_a.empty?
5
+ require 'autotest'
6
+
7
+ namespace :test do
8
+ task :autotest do
9
+ Autotest.run
10
+ end
11
+ end
12
+
13
+ desc "Run the autotest loop"
14
+ task :autotest => 'test:autotest'
15
+
16
+ end # if test
17
+
18
+ # --------------------------------------------------------------------------
19
+ if HAVE_SPEC_RAKE_SPECTASK and not PROJ.spec.files.to_a.empty?
20
+ require 'autotest/rspec'
21
+
22
+ namespace :spec do
23
+ task :autotest do
24
+ load '.autotest' if test(?f, '.autotest')
25
+ Autotest::Rspec.run
26
+ end
27
+ end
28
+
29
+ desc "Run the autotest loop"
30
+ task :autotest => 'spec:autotest'
31
+
32
+ end # if rspec
33
+
34
+ end # if HAVE_ZENTEST
35
+
36
+ # EOF
data/test/abstract.rb ADDED
@@ -0,0 +1,250 @@
1
+
2
+ require 'rubygems'
3
+ require 'dm-core'
4
+ require 'dm-is-reflective'
5
+
6
+ module Abstract
7
+ def setup_data_mapper
8
+ raise 'please provide a clean database because it is a destructive test!!'
9
+ end
10
+
11
+ AttrCommon = {:nullable => true}
12
+ AttrCommonPK = {:serial => true, :key => true, :nullable => false}
13
+ AttrText = {:length => 65535}.merge(AttrCommon)
14
+
15
+ def user_fields
16
+ [[:created_at, DateTime, AttrCommon],
17
+ [:id, DataMapper::Types::Serial, AttrCommonPK],
18
+ [:login, String, {:length => 70}.merge(AttrCommon)],
19
+ [:sig, DataMapper::Types::Text, AttrText]]
20
+ end
21
+
22
+ def comment_fields
23
+ [[:body, DataMapper::Types::Text, AttrText],
24
+ [:id, DataMapper::Types::Serial, AttrCommonPK],
25
+ [:title, String, {:length => 50, :default => 'default title'}.
26
+ merge(AttrCommon)],
27
+ [:user_id, Integer, AttrCommon]]
28
+ end
29
+
30
+ # there's differences between adapters
31
+ def super_user_fields
32
+ case self
33
+ when MysqlTest # Mysql couldn't tell it's boolean or tinyint
34
+ [[:bool, Integer, AttrCommon],
35
+ [:id, DataMapper::Types::Serial, AttrCommonPK]]
36
+
37
+ else
38
+ [[:bool, DataMapper::Types::Boolean, AttrCommon],
39
+ [:id, DataMapper::Types::Serial, AttrCommonPK]]
40
+
41
+ end
42
+ end
43
+
44
+ class User
45
+ include DataMapper::Resource
46
+ has n, :comments
47
+
48
+ property :id, Serial
49
+ property :login, String, :length => 70
50
+ property :sig, Text
51
+ property :created_at, DateTime
52
+
53
+ is :reflective
54
+ end
55
+
56
+ class SuperUser
57
+ include DataMapper::Resource
58
+ property :id, Serial
59
+ property :bool, Boolean
60
+
61
+ is :reflective
62
+ end
63
+
64
+ class Comment
65
+ include DataMapper::Resource
66
+ belongs_to :user, :nullable => true
67
+
68
+ property :id, Serial
69
+ property :title, String, :length => 50, :default => 'default title'
70
+ property :body, Text
71
+
72
+ is :reflective
73
+ end
74
+
75
+ class Model; end
76
+
77
+ Tables = ['abstract_comments', 'abstract_super_users', 'abstract_users']
78
+
79
+ def sort_fields fields
80
+ fields.sort_by{ |field|
81
+ field.first.to_s
82
+ }
83
+ end
84
+
85
+ def create_fake_model
86
+ model = Model.dup.send(:include, DataMapper::Resource)
87
+ model.is :reflective
88
+ [ model, setup_data_mapper ]
89
+ end
90
+
91
+ attr_reader :dm
92
+ def setup
93
+ @dm = setup_data_mapper
94
+ # this is significant faster than DataMapper.auto_migrate!
95
+ User.auto_migrate!
96
+ Comment.auto_migrate!
97
+ SuperUser.auto_migrate!
98
+ end
99
+
100
+ def new_scope
101
+ self.class.const_set("Scope#{object_id.object_id}", Module.new)
102
+ end
103
+
104
+ def test_storages
105
+ assert_equal Tables, dm.storages.sort
106
+ assert_equal comment_fields, sort_fields(dm.fields('abstract_comments'))
107
+ end
108
+
109
+ def test_create_comment
110
+ Comment.create(:title => 'XD')
111
+ assert_equal 1, Comment.first.id
112
+ assert_equal 'XD', Comment.first.title
113
+ end
114
+
115
+ def test_create_user
116
+ now = Time.now
117
+ User.create(:created_at => now)
118
+ assert_equal 1, User.first.id
119
+ assert_equal now.asctime, User.first.created_at.asctime
120
+
121
+ return now
122
+ end
123
+
124
+ def test_reflect_all
125
+ test_create_comment # for fixtures
126
+ model, local_dm = create_fake_model
127
+ model.storage_names[:default] = 'abstract_comments'
128
+
129
+ assert_equal Tables, local_dm.storages.sort
130
+ assert_equal 'abstract_comments', model.storage_name
131
+
132
+ model.send :reflect
133
+ assert_equal 1, model.all.size
134
+ assert_equal comment_fields, sort_fields(model.fields)
135
+
136
+ assert_equal 'XD', model.first.title
137
+ assert_equal 1, model.first.id
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
+ assert_equal 1, model.first.id
148
+
149
+ model.create
150
+ assert_equal 'default title', model.get(2).title
151
+ end
152
+
153
+ def test_storages_and_fields
154
+ assert_equal user_fields, sort_fields(dm.fields('abstract_users'))
155
+ assert_equal( {'abstract_users' => user_fields,
156
+ 'abstract_comments' => comment_fields,
157
+ 'abstract_super_users' => super_user_fields},
158
+ dm.storages_and_fields.inject({}){ |r, i|
159
+ key, value = i
160
+ r[key] = value.sort_by{ |v| v.first.to_s }
161
+ r
162
+ } )
163
+ end
164
+
165
+ def test_reflect_type
166
+ model, local_dm = create_fake_model
167
+ model.storage_names[:default] = 'abstract_comments'
168
+
169
+ model.send :reflect, DataMapper::Types::Serial
170
+ assert_equal ['id'], model.properties.map(&:name).map(&:to_s).sort
171
+
172
+ model.send :reflect, Integer
173
+ assert_equal ['id', 'user_id'], model.properties.map(&:name).map(&:to_s).sort
174
+ end
175
+
176
+ def test_reflect_multiple
177
+ model, local_dm = create_fake_model
178
+ model.storage_names[:default] = 'abstract_users'
179
+ model.send :reflect, :login, DataMapper::Types::Serial
180
+
181
+ assert_equal ['id', 'login'], model.properties.map(&:name).map(&:to_s).sort
182
+ end
183
+
184
+ def test_reflect_regexp
185
+ model, local_dm = create_fake_model
186
+ model.storage_names[:default] = 'abstract_comments'
187
+ model.send :reflect, /id$/
188
+
189
+ assert_equal ['id', 'user_id'], model.properties.map(&:name).map(&:to_s).sort
190
+ end
191
+
192
+ def test_invalid_argument
193
+ assert_raises(ArgumentError){
194
+ User.send :reflect, 29
195
+ }
196
+ end
197
+
198
+ def test_auto_genclasses
199
+ scope = new_scope
200
+ assert_equal ["#{scope == Object ? '' : "#{scope}::"}AbstractComment",
201
+ "#{scope}::AbstractSuperUser",
202
+ "#{scope}::AbstractUser"],
203
+ dm.auto_genclass!(:scope => scope).map(&:to_s).sort
204
+
205
+ comment = scope.const_get('AbstractComment')
206
+
207
+ assert_equal comment_fields, sort_fields(comment.fields)
208
+
209
+ test_create_comment
210
+
211
+ assert_equal 'XD', comment.first.title
212
+ comment.create(:title => 'orz', :body => 'dm-reflect')
213
+ assert_equal 'dm-reflect', comment.get(2).body
214
+ end
215
+
216
+ def test_auto_genclass
217
+ scope = new_scope
218
+ assert_equal ["#{scope}::AbstractUser"],
219
+ dm.auto_genclass!(:scope => scope,
220
+ :storages => 'abstract_users').map(&:to_s)
221
+
222
+ user = scope.const_get('AbstractUser')
223
+ assert_equal user_fields, sort_fields(user.fields)
224
+
225
+ now = test_create_user
226
+
227
+ assert_equal now.asctime, user.first.created_at.asctime
228
+ user.create(:login => 'godfat')
229
+ assert_equal 'godfat', user.get(2).login
230
+ end
231
+
232
+ def test_auto_genclass_with_regexp
233
+ scope = new_scope
234
+ assert_equal ["#{scope}::AbstractSuperUser", "#{scope}::AbstractUser"],
235
+ dm.auto_genclass!(:scope => scope,
236
+ :storages => /_users$/).map(&:to_s).sort
237
+
238
+ user = scope.const_get('AbstractSuperUser')
239
+ assert_equal sort_fields(SuperUser.fields), sort_fields(user.fields)
240
+ end
241
+
242
+ def test_reflect_return_value
243
+ model, local_dm = create_fake_model
244
+ model.storage_names[:default] = 'abstract_comments'
245
+ mapped = model.send :reflect, /.*/
246
+
247
+ assert_equal model.properties.map(&:object_id).sort, mapped.map(&:object_id).sort
248
+ end
249
+
250
+ end
@@ -0,0 +1,48 @@
1
+
2
+ require 'test/abstract'
3
+
4
+ TestCase = begin
5
+ require 'minitest/unit'
6
+ MiniTest::Unit.autorun
7
+ MiniTest::Unit::TestCase
8
+ rescue LoadError
9
+ require 'test/unit'
10
+ Test::Unit::TestCase
11
+ end
12
+
13
+ %w[sqlite3 mysql postgres].each{ |adapter|
14
+ begin
15
+ require "dm-core/adapters/#{adapter}_adapter"
16
+ rescue LoadError
17
+ puts "skip #{adapter} test since it's not installed"
18
+ end
19
+ }
20
+
21
+ # cost 1 second to run
22
+ class Sqlite3Test < TestCase
23
+ include Abstract
24
+
25
+ def setup_data_mapper
26
+ DataMapper.setup(:default, 'sqlite3::memory:')
27
+ end
28
+ end if defined?(DataObjects::Sqlite3)
29
+
30
+
31
+ # cost 2 seconds to run
32
+ class MysqlTest < TestCase
33
+ include Abstract
34
+
35
+ def setup_data_mapper
36
+ DataMapper.setup(:default, 'mysql://dm-mapping:godfat@localhost/dm-mapping')
37
+ end
38
+ end if defined?(DataObjects::Mysql)
39
+
40
+
41
+ # cost 3 seconds to run
42
+ class PostgresTest < TestCase
43
+ include Abstract
44
+
45
+ def setup_data_mapper
46
+ DataMapper.setup(:default, 'postgres://dm-mapping:godfat@localhost/dm-mapping')
47
+ end
48
+ end if defined?(DataObjects::Postgres)