dm-is-reflective 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gita/COMMIT_EDITMSG +9 -0
- data/.gita/HEAD +1 -0
- data/.gita/ORIG_HEAD +1 -0
- data/.gita/RENAMED-REF +1 -0
- data/.gita/config +9 -0
- data/.gita/description +1 -0
- data/.gita/gitk.cache +6 -0
- data/.gita/hooks/applypatch-msg +15 -0
- data/.gita/hooks/commit-msg +24 -0
- data/.gita/hooks/post-commit +8 -0
- data/.gita/hooks/post-receive +16 -0
- data/.gita/hooks/post-update +8 -0
- data/.gita/hooks/pre-applypatch +14 -0
- data/.gita/hooks/pre-commit +70 -0
- data/.gita/hooks/pre-rebase +150 -0
- data/.gita/hooks/prepare-commit-msg +36 -0
- data/.gita/hooks/update +107 -0
- data/.gita/index +0 -0
- data/.gita/info/exclude +6 -0
- data/.gita/info/refs +26 -0
- data/.gita/logs/HEAD +40 -0
- data/.gita/logs/refs/heads/dm-mapping +1 -0
- data/.gita/logs/refs/heads/master +40 -0
- data/.gita/logs/refs/heads/return-symbol +0 -0
- data/.gita/logs/refs/remotes/origin/dm-mapping +1 -0
- data/.gita/logs/refs/remotes/origin/master +6 -0
- data/.gita/logs/refs/remotes/origin/return-symbol +0 -0
- data/.gita/objects/5c/91380a1616b7c2d23e14eeb49d9edde58e1f47 +2 -0
- data/.gita/objects/63/71947bcb9c0dd1d3b3d6f449b2d4b4c6c81e63 +0 -0
- data/.gita/objects/73/23ae22118cc54fb0bbb0d6f51cc99191019b96 +0 -0
- data/.gita/objects/81/a0ab6e4dbd148faa0644307b313799027d3344 +2 -0
- data/.gita/objects/b2/9571a21e3bccb60079dfca630dac981f623489 +5 -0
- data/.gita/objects/cb/138acf9efc0f5b3ff91c644cae4dec868442e4 +5 -0
- data/.gita/objects/d5/66699fc7ba5237311cc44648d0cd2abbaa895e +0 -0
- data/.gita/objects/info/packs +2 -0
- data/.gita/objects/pack/pack-c9156ef3406b98f5f12875b13643df7a5f41e42c.idx +0 -0
- data/.gita/objects/pack/pack-c9156ef3406b98f5f12875b13643df7a5f41e42c.pack +0 -0
- data/.gita/packed-refs +27 -0
- data/.gita/refs/heads/master +1 -0
- data/.gita/refs/tags/dm-is-reflective-0.8.0 +1 -0
- data/CHANGES +189 -0
- data/LICENSE +201 -0
- data/NOTICE +30 -0
- data/README +122 -0
- data/Rakefile +45 -0
- data/TODO +7 -0
- data/dm-is-reflective.gemspec +41 -0
- data/lib/dm-is-reflective.rb +10 -0
- data/lib/dm-is-reflective/is/adapters/abstract_adapter.rb +144 -0
- data/lib/dm-is-reflective/is/adapters/mysql_adapter.rb +62 -0
- data/lib/dm-is-reflective/is/adapters/postgres_adapter.rb +84 -0
- data/lib/dm-is-reflective/is/adapters/sqlite3_adapter.rb +61 -0
- data/lib/dm-is-reflective/is/reflective.rb +78 -0
- data/lib/dm-is-reflective/is/version.rb +7 -0
- data/lib/dm-is-reflective/version.rb +7 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +294 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/tasks/zentest.rake +36 -0
- data/test/abstract.rb +250 -0
- data/test/test_dm-is-reflexible.rb +48 -0
- metadata +203 -0
data/NOTICE
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
= notice and thanks
|
2
|
+
|
3
|
+
* dm-is-reflective is a plugin of DataMapper
|
4
|
+
> sudo gem install dm-core
|
5
|
+
http://datamapper.org
|
6
|
+
|
7
|
+
* this project skeleton is built through Mr Bones
|
8
|
+
http://codeforpeople.rubyforge.org/bones/
|
9
|
+
|
10
|
+
* thanks to Rails team with ActiveRecord, it's inspiring.
|
11
|
+
and some SQL snippets are borrowed from it.
|
12
|
+
http://rubyonrails.org
|
13
|
+
|
14
|
+
* Ruby the great language
|
15
|
+
http://www.ruby-lang.org
|
16
|
+
|
17
|
+
* Rubygems the great package management
|
18
|
+
http://rubygems.org
|
19
|
+
|
20
|
+
* Rake the great task automation
|
21
|
+
http://rake.rubyforge.org
|
22
|
+
|
23
|
+
* Facets the great ruby library collection
|
24
|
+
http://facets.rubyforge.org/
|
25
|
+
|
26
|
+
* Rubyforge for distributing ruby gems
|
27
|
+
http://rubyforge.org
|
28
|
+
|
29
|
+
* Github for hosting git
|
30
|
+
http://github.com
|
data/README
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
= dm-is-reflective 0.8.0
|
2
|
+
by Lin Jen-Shin (aka godfat-真常[http://godfat.org])
|
3
|
+
godfat (XD) godfat.org
|
4
|
+
|
5
|
+
== LINKS:
|
6
|
+
|
7
|
+
* rdoc[http://ludy.rubyforge.org/dm-is-reflective]
|
8
|
+
* github-project[http://github.com/godfat/dm-is-reflective]
|
9
|
+
* rubyforge-project[http://rubyforge.org/projects/ludy]
|
10
|
+
|
11
|
+
== DESCRIPTION:
|
12
|
+
|
13
|
+
DataMapper plugin that helps you manipulate an existing database.
|
14
|
+
It creates mappings between existing columns and model's properties.
|
15
|
+
|
16
|
+
== SYNOPSIS:
|
17
|
+
|
18
|
+
require 'dm-is-reflective' # this would require 'dm-core'
|
19
|
+
dm = DataMapper.setup :default, 'sqlite3:db/development.sqlite3'
|
20
|
+
|
21
|
+
class User
|
22
|
+
include DataMapper::Resource
|
23
|
+
is :reflective
|
24
|
+
|
25
|
+
# mapping all, returns an array of properties indicating fields it mapped
|
26
|
+
mapping /.*/ # e.g. => [#<Property:#<Class:0x18f89b8>:id>,
|
27
|
+
# #<Property:#<Class:0x18f89b8>:title>,
|
28
|
+
# #<Property:#<Class:0x18f89b8>:body>,
|
29
|
+
# #<Property:#<Class:0x18f89b8>:user_id>]
|
30
|
+
|
31
|
+
# mapping all (with no argument at all)
|
32
|
+
mapping
|
33
|
+
|
34
|
+
# mapping for field name ended with _at, and started with salt_
|
35
|
+
mapping /_at$/, /^salt_/
|
36
|
+
|
37
|
+
# mapping id and email
|
38
|
+
mapping :id, :email
|
39
|
+
|
40
|
+
# mapping all fields with type String, and id
|
41
|
+
mapping String, :id
|
42
|
+
|
43
|
+
# mapping login, and all fields with type Integer
|
44
|
+
mapping :login, Integer
|
45
|
+
end
|
46
|
+
|
47
|
+
# there's no guarantee of the order in storages array
|
48
|
+
dm.storages
|
49
|
+
# => ['users']
|
50
|
+
|
51
|
+
# there's no guarantee of the order in fields array
|
52
|
+
User.fields
|
53
|
+
# => [[:created_at, DateTime, {:nullable => true}],
|
54
|
+
[:email, String, {:nullable => true, :length => 255,
|
55
|
+
:default => 'nospam@nospam.tw'}],
|
56
|
+
[:id, Serial, {:nullable => false, :serial => true,
|
57
|
+
:key => true}],
|
58
|
+
[:salt_first, String, {:nullable => true, :length => 50}],
|
59
|
+
[:salt_second, String, {:nullable => true, :length => 50}]]
|
60
|
+
|
61
|
+
dm.fields('users').sort_by{ |field| field.first.to_s } ==
|
62
|
+
User.fields.sort_by{ |field| field.first.to_s }
|
63
|
+
# => true
|
64
|
+
|
65
|
+
dm.storages_and_fields
|
66
|
+
# => {'users' => [[:id, Serial, {:nullable => false,
|
67
|
+
:serial => true,
|
68
|
+
:key => true}],
|
69
|
+
[:email, String, {:nullable => true,
|
70
|
+
:default => 'nospam@nospam.tw'}],
|
71
|
+
[:created_at, DateTime, {:nullable => true}],
|
72
|
+
[:salt_first, String, {:nullable => true, :length => 50}],
|
73
|
+
[:salt_second, String, {:nullable => true, :length => 50}]]}
|
74
|
+
|
75
|
+
# there's no guarantee of the order in returned array
|
76
|
+
dm.auto_genclass!
|
77
|
+
# => [DataMapper::Is::Reflective::User,
|
78
|
+
DataMapper::Is::Reflective::SchemaInfo,
|
79
|
+
DataMapper::Is::Reflective::Session]
|
80
|
+
|
81
|
+
# you can change the scope of generated models:
|
82
|
+
dm.auto_genclass! :scope => Object
|
83
|
+
# => [User, SchemaInfo, Session]
|
84
|
+
|
85
|
+
# you can generate classes for tables you specified only:
|
86
|
+
dm.auto_genclass! :scope => Object, :storages => /^phpbb_/
|
87
|
+
# => [PhpbbUser, PhpbbPost, PhpbbConfig]
|
88
|
+
|
89
|
+
# you can generate classes with String too:
|
90
|
+
dm.auto_genclass! :storages => ['users', 'config'], :scope => Object
|
91
|
+
# => [User, Config]
|
92
|
+
|
93
|
+
# you can generate a class only:
|
94
|
+
dm.auto_genclass! :storages => 'users'
|
95
|
+
# => [DataMapper::Is::Reflective::User]
|
96
|
+
|
97
|
+
== REQUIREMENTS:
|
98
|
+
|
99
|
+
* dm-core 0.10.0 or later
|
100
|
+
* at least one do_* adapter
|
101
|
+
|
102
|
+
== INSTALL:
|
103
|
+
|
104
|
+
> sudo gem install dm-is-reflective
|
105
|
+
|
106
|
+
== LICENSE:
|
107
|
+
|
108
|
+
Apache License 2.0
|
109
|
+
|
110
|
+
Copyright (c) 2008, Lin Jen-Shin (aka godfat 真常)
|
111
|
+
|
112
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
113
|
+
you may not use this file except in compliance with the License.
|
114
|
+
You may obtain a copy of the License at
|
115
|
+
|
116
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
117
|
+
|
118
|
+
Unless required by applicable law or agreed to in writing, software
|
119
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
120
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
121
|
+
See the License for the specific language governing permissions and
|
122
|
+
limitations under the License.
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'bones'
|
4
|
+
Bones.setup
|
5
|
+
|
6
|
+
PROJ.name = 'dm-is-reflective'
|
7
|
+
PROJ.authors = 'Lin Jen-Shin (aka godfat 真常)'
|
8
|
+
PROJ.email = 'godfat (XD) godfat.org'
|
9
|
+
PROJ.url = "http://github.com/godfat/#{PROJ.name}"
|
10
|
+
PROJ.rubyforge.name = 'ludy'
|
11
|
+
|
12
|
+
PROJ.gem.dependencies << ['dm-core', '>=0.10.0'] << ['extlib', '>=0.9.13']
|
13
|
+
# PROJ.gem.development_dependencies << ['minitest', '>=1.3.0']
|
14
|
+
# PROJ.gem.executables = ["bin/#{PROJ.name}"]
|
15
|
+
|
16
|
+
PROJ.ruby_opts.delete '-w' # too many warnings in addressable, dm-core, extlib...
|
17
|
+
|
18
|
+
PROJ.description = PROJ.summary = paragraphs_of('README', 'description').join("\n\n")
|
19
|
+
PROJ.changes = paragraphs_of('CHANGES', 0..1).join("\n\n")
|
20
|
+
PROJ.version = File.read("lib/#{PROJ.name}/version.rb").gsub(/.*VERSION = '(.*)'.*/m, '\1')
|
21
|
+
|
22
|
+
PROJ.exclude += ['^tmp', 'tmp$', '^pkg', '^\.gitignore$',
|
23
|
+
'^ann-', '\.sqlite3$', '\.db$']
|
24
|
+
|
25
|
+
PROJ.rdoc.remote_dir = PROJ.name
|
26
|
+
|
27
|
+
PROJ.readme_file = 'README'
|
28
|
+
PROJ.rdoc.main = 'README'
|
29
|
+
PROJ.rdoc.exclude += ['Rakefile', '^tasks', '^test']
|
30
|
+
PROJ.rdoc.include << '\w+'
|
31
|
+
# PROJ.rdoc.opts << '--diagram' if !Rake::WIN32 and `which dot` =~ %r/\/dot/
|
32
|
+
PROJ.rdoc.opts += ['--charset=utf-8', '--inline-source',
|
33
|
+
'--line-numbers', '--promiscuous']
|
34
|
+
|
35
|
+
PROJ.spec.opts << '--color'
|
36
|
+
|
37
|
+
PROJ.ann.file = "ann-#{PROJ.name}-#{PROJ.version}"
|
38
|
+
PROJ.ann.paragraphs.concat %w[LINKS SYNOPSIS REQUIREMENTS INSTALL LICENSE]
|
39
|
+
|
40
|
+
CLEAN.include Dir['**/*.rbc']
|
41
|
+
|
42
|
+
task :default do
|
43
|
+
Rake.application.options.show_task_pattern = /./
|
44
|
+
Rake.application.display_tasks_and_comments
|
45
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{dm-is-reflective}
|
5
|
+
s.version = "0.8.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Lin Jen-Shin (aka godfat \347\234\237\345\270\270)"]
|
9
|
+
s.date = %q{2009-06-21}
|
10
|
+
s.description = %q{ DataMapper plugin that helps you manipulate an existing database.
|
11
|
+
It creates mappings between existing columns and model's properties.}
|
12
|
+
s.email = %q{godfat (XD) godfat.org}
|
13
|
+
s.extra_rdoc_files = ["CHANGES", "LICENSE", "NOTICE", "README", "TODO"]
|
14
|
+
s.files = ["CHANGES", "LICENSE", "NOTICE", "README", "Rakefile", "TODO", "lib/dm-is-reflective.rb", "lib/dm-is-reflective/is/adapters/abstract_adapter.rb", "lib/dm-is-reflective/is/adapters/mysql_adapter.rb", "lib/dm-is-reflective/is/adapters/postgres_adapter.rb", "lib/dm-is-reflective/is/adapters/sqlite3_adapter.rb", "lib/dm-is-reflective/is/reflective.rb", "lib/dm-is-reflective/is/version.rb", "lib/dm-is-reflective/version.rb", "test/abstract.rb", "test/test_dm-is-reflexible.rb"]
|
15
|
+
s.homepage = %q{http://github.com/godfat/dm-is-reflective}
|
16
|
+
s.rdoc_options = ["--charset=utf-8", "--inline-source", "--line-numbers", "--promiscuous", "--main", "README"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{ludy}
|
19
|
+
s.rubygems_version = %q{1.3.4}
|
20
|
+
s.summary = %q{DataMapper plugin that helps you manipulate an existing database. It creates mappings between existing columns and model's properties.}
|
21
|
+
s.test_files = ["test/test_dm-is-reflexible.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 3
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
s.add_runtime_dependency(%q<dm-core>, [">= 0.10.0"])
|
29
|
+
s.add_runtime_dependency(%q<extlib>, [">= 0.9.13"])
|
30
|
+
s.add_development_dependency(%q<bones>, [">= 2.5.1"])
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<dm-core>, [">= 0.10.0"])
|
33
|
+
s.add_dependency(%q<extlib>, [">= 0.9.13"])
|
34
|
+
s.add_dependency(%q<bones>, [">= 2.5.1"])
|
35
|
+
end
|
36
|
+
else
|
37
|
+
s.add_dependency(%q<dm-core>, [">= 0.10.0"])
|
38
|
+
s.add_dependency(%q<extlib>, [">= 0.9.13"])
|
39
|
+
s.add_dependency(%q<bones>, [">= 2.5.1"])
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
|
2
|
+
gem 'dm-core', '>=0.10.0'
|
3
|
+
require 'dm-core'
|
4
|
+
|
5
|
+
require 'dm-is-reflective/is/reflective'
|
6
|
+
DataMapper::Model.append_extensions(DataMapper::Is::Reflective)
|
7
|
+
|
8
|
+
require 'dm-is-reflective/is/adapters/abstract_adapter'
|
9
|
+
DataMapper::Adapters::AbstractAdapter.__send__(:include,
|
10
|
+
DataMapper::Is::Reflective::AbstractAdapter)
|
@@ -0,0 +1,144 @@
|
|
1
|
+
|
2
|
+
module DataMapper
|
3
|
+
module Is::Reflective
|
4
|
+
module AbstractAdapter
|
5
|
+
# returns all tables' name in the repository.
|
6
|
+
# e.g.
|
7
|
+
# ['comments', 'users']
|
8
|
+
def storages
|
9
|
+
reflective_auto_load_adapter_extension
|
10
|
+
storages # call the overrided method
|
11
|
+
end
|
12
|
+
|
13
|
+
# returns all fields, with format [[name, type, attrs]]
|
14
|
+
# e.g.
|
15
|
+
# [[:created_at, DateTime, {:nullable => true}],
|
16
|
+
# [:email, String, {:nullable => true, :size => 255,
|
17
|
+
# :default => 'nospam@nospam.tw'}],
|
18
|
+
# [:id, DataMapper::Types::Serial, {:nullable => false, :serial => true,
|
19
|
+
# :key => true}],
|
20
|
+
# [:salt_first, String, {:nullable => true, :size => 50}],
|
21
|
+
# [:salt_second, String, {:nullable => true, :size => 50}]]
|
22
|
+
def fields storage
|
23
|
+
reflective_query_storage(storage).map{ |field|
|
24
|
+
primitive = reflective_primitive(field)
|
25
|
+
|
26
|
+
type = self.class.type_map.find{ |klass, attrs|
|
27
|
+
next false if [DataMapper::Types::Object, Time].include?(klass)
|
28
|
+
attrs[:primitive] == primitive
|
29
|
+
}
|
30
|
+
type = type ? type.first : reflective_lookup_primitive(primitive)
|
31
|
+
|
32
|
+
attrs = reflective_attributes(field)
|
33
|
+
|
34
|
+
type = if attrs[:serial] && type == Integer
|
35
|
+
DataMapper::Types::Serial
|
36
|
+
|
37
|
+
elsif type == TrueClass
|
38
|
+
DataMapper::Types::Boolean
|
39
|
+
|
40
|
+
else
|
41
|
+
type
|
42
|
+
end
|
43
|
+
|
44
|
+
[reflective_field_name(field).to_sym, type, attrs]
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
# returns a hash with storage names in keys and
|
49
|
+
# corresponded fields in values. e.g.
|
50
|
+
# {'users' => [[:id, Integer, {:nullable => false,
|
51
|
+
# :serial => true,
|
52
|
+
# :key => true}],
|
53
|
+
# [:email, String, {:nullable => true,
|
54
|
+
# :default => 'nospam@nospam.tw'}],
|
55
|
+
# [:created_at, DateTime, {:nullable => true}],
|
56
|
+
# [:salt_first, String, {:nullable => true, :size => 50}],
|
57
|
+
# [:salt_second, String, {:nullable => true, :size => 50}]]}
|
58
|
+
# see Migration#storages and Migration#fields for detail
|
59
|
+
def storages_and_fields
|
60
|
+
storages.inject({}){ |result, storage|
|
61
|
+
result[storage] = fields(storage)
|
62
|
+
result
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
# automaticly generate model class(es) and reflect
|
67
|
+
# all fields with reflect /.*/ for you.
|
68
|
+
# e.g.
|
69
|
+
# dm.auto_genclass!
|
70
|
+
# # => [DataMapper::Is::Reflective::User,
|
71
|
+
# # DataMapper::Is::Reflective::SchemaInfo,
|
72
|
+
# # DataMapper::Is::Reflective::Session]
|
73
|
+
#
|
74
|
+
# you can change the scope of generated models:
|
75
|
+
# e.g.
|
76
|
+
# dm.auto_genclass! :scope => Object
|
77
|
+
# # => [User, SchemaInfo, Session]
|
78
|
+
#
|
79
|
+
# you can generate classes for tables you specified only:
|
80
|
+
# e.g.
|
81
|
+
# dm.auto_genclass! :scope => Object, :storages => /^phpbb_/
|
82
|
+
# # => [PhpbbUser, PhpbbPost, PhpbbConfig]
|
83
|
+
#
|
84
|
+
# you can generate classes with String too:
|
85
|
+
# e.g.
|
86
|
+
# dm.auto_genclass! :storages => ['users', 'config'], :scope => Object
|
87
|
+
# # => [User, Config]
|
88
|
+
#
|
89
|
+
# you can generate a class only:
|
90
|
+
# e.g.
|
91
|
+
# dm.auto_genclass! :storages => 'users'
|
92
|
+
# # => [DataMapper::Is::Reflective::User]
|
93
|
+
def auto_genclass! opts = {}
|
94
|
+
opts[:scope] ||= DataMapper::Is::Reflective
|
95
|
+
opts[:storages] ||= /.*/
|
96
|
+
opts[:storages] = [opts[:storages]].flatten
|
97
|
+
|
98
|
+
storages.map{ |storage|
|
99
|
+
|
100
|
+
mapped = opts[:storages].each{ |target|
|
101
|
+
case target
|
102
|
+
when Regexp;
|
103
|
+
break storage if storage =~ target
|
104
|
+
|
105
|
+
when Symbol, String;
|
106
|
+
break storage if storage == target.to_s
|
107
|
+
|
108
|
+
else
|
109
|
+
raise ArgumentError.new("invalid argument: #{target.inspect}")
|
110
|
+
end
|
111
|
+
}
|
112
|
+
|
113
|
+
reflective_genclass(mapped, opts[:scope]) if mapped.kind_of?(String)
|
114
|
+
}.compact
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
def reflective_query_storage storage
|
119
|
+
reflective_auto_load_adapter_extension
|
120
|
+
reflective_query_storage(storage) # call the overrided method
|
121
|
+
end
|
122
|
+
|
123
|
+
def reflective_genclass storage, scope
|
124
|
+
model = Class.new
|
125
|
+
model.__send__(:include, DataMapper::Resource)
|
126
|
+
model.is(:reflective)
|
127
|
+
model.storage_names[:default] = storage
|
128
|
+
model.__send__(:reflect, /.*/)
|
129
|
+
scope.const_set(Extlib::Inflection.classify(storage), model)
|
130
|
+
end
|
131
|
+
|
132
|
+
def reflective_lookup_primitive primitive
|
133
|
+
raise TypeError.new("#{primitive} not found for #{self.class}")
|
134
|
+
end
|
135
|
+
|
136
|
+
def reflective_auto_load_adapter_extension
|
137
|
+
require "dm-is-reflective/is/adapters/#{options['scheme']}_adapter"
|
138
|
+
class_name = "#{Extlib::Inflection.camelize(options['scheme'])}Adapter"
|
139
|
+
Adapters.const_get(class_name).__send__(:include,
|
140
|
+
Is::Reflective.const_get(class_name))
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
require 'dm-is-reflective/is/adapters/abstract_adapter'
|
3
|
+
|
4
|
+
module DataMapper
|
5
|
+
module Is::Reflective
|
6
|
+
module MysqlAdapter
|
7
|
+
def storages
|
8
|
+
query 'SHOW TABLES'
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
# construct needed table metadata
|
13
|
+
def reflective_query_storage storage
|
14
|
+
sql = <<-SQL.compress_lines
|
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
|
+
query(sql, db_name, storage)
|
22
|
+
end
|
23
|
+
|
24
|
+
def reflective_field_name field
|
25
|
+
field.column_name
|
26
|
+
end
|
27
|
+
|
28
|
+
def reflective_primitive field
|
29
|
+
field.data_type
|
30
|
+
end
|
31
|
+
|
32
|
+
def reflective_attributes field, attrs = {}
|
33
|
+
attrs[:serial] = true if field.extra == 'auto_increment'
|
34
|
+
attrs[:key] = true if field.column_key == 'PRI'
|
35
|
+
|
36
|
+
attrs[:nullable] = field.is_nullable == 'YES'
|
37
|
+
attrs[:default] = field.column_default if
|
38
|
+
field.column_default
|
39
|
+
|
40
|
+
attrs[:length] = field.character_maximum_length if
|
41
|
+
field.character_maximum_length
|
42
|
+
|
43
|
+
attrs
|
44
|
+
end
|
45
|
+
|
46
|
+
def reflective_lookup_primitive primitive
|
47
|
+
p = primitive.upcase
|
48
|
+
|
49
|
+
return Integer if p == 'YEAR'
|
50
|
+
return Integer if p =~ /\w*INT(EGER)?( SIGNED| UNSIGNED)?( ZEROFILL)?/
|
51
|
+
return BigDecimal if p =~ /(DOUBLE|FLOAT|DECIMAL)( SIGNED| UNSIGNED)?( ZEROFILL)?/
|
52
|
+
return String if p =~ /\w*BLOB|\w*BINARY|ENUM|SET|CHAR/
|
53
|
+
return Time if p == 'TIME'
|
54
|
+
return DateTime if p == 'DATETIME'
|
55
|
+
return DataMapper::Types::Boolean if %w[BOOL BOOLEAN].member?(p)
|
56
|
+
return DataMapper::Types::Text if p =~ /\w*TEXT/
|
57
|
+
|
58
|
+
super(primitive)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|