dm-is-reflective 0.8.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.
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)