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.
- checksums.yaml +7 -0
- data/.travis.yml +15 -0
- data/CHANGES.md +8 -0
- data/Gemfile +5 -1
- data/README.md +103 -86
- data/Rakefile +1 -14
- data/bin/dm-is-reflective +4 -0
- data/dm-is-reflective.gemspec +24 -12
- data/lib/dm-is-reflective.rb +4 -5
- data/lib/dm-is-reflective/adapters/data_objects_adapter.rb +136 -0
- data/lib/dm-is-reflective/adapters/mysql_adapter.rb +63 -0
- data/lib/dm-is-reflective/adapters/postgres_adapter.rb +80 -0
- data/lib/dm-is-reflective/adapters/sqlite_adapter.rb +57 -0
- data/lib/dm-is-reflective/{is/reflective.rb → reflective.rb} +18 -7
- data/lib/dm-is-reflective/runner.rb +87 -0
- data/lib/dm-is-reflective/test.rb +279 -0
- data/lib/dm-is-reflective/version.rb +2 -6
- data/task/gemgem.rb +7 -6
- data/test/test_mysql.rb +23 -0
- data/test/test_postgres.rb +23 -0
- data/test/test_sqlite.rb +10 -0
- data/test/test_to_source.rb +55 -0
- metadata +43 -46
- data/lib/dm-is-reflective/is/adapters/data_objects_adapter.rb +0 -138
- data/lib/dm-is-reflective/is/adapters/mysql_adapter.rb +0 -64
- data/lib/dm-is-reflective/is/adapters/postgres_adapter.rb +0 -82
- data/lib/dm-is-reflective/is/adapters/sqlite_adapter.rb +0 -61
- data/test/abstract.rb +0 -252
- data/test/test_dm-is-reflective.rb +0 -53
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a4a92f58af6a1c63b6bb445e06fdc573239ef558
|
4
|
+
data.tar.gz: 4577c3ed73a122c4ddd09e62c8c0e64802e49540
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f271c3864848cfb098e7f7b32887831700617668c001a56f25f0be1a0497d0e488db5f8970ad7e96ee9ab9aecb4fd333b4fa71c70de48afd435929c266751f5c
|
7
|
+
data.tar.gz: a139f550d6b69b36ddb824eec2ca59b4ec157d1289d39cdcc31f268a5d50a7abb90abcb1b48a05f7cdb0784edfb31b28440078adaef7f3b721ccb82d5f7e1944
|
data/.travis.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
before_install:
|
2
|
+
- 'git submodule update --init'
|
3
|
+
- mysql -e 'create database myapp_test;'
|
4
|
+
- psql -c 'create database myapp_test;' -U postgres
|
5
|
+
|
6
|
+
script: 'ruby -r bundler/setup -S rake test'
|
7
|
+
|
8
|
+
env:
|
9
|
+
- 'RBXOPT=-X19'
|
10
|
+
|
11
|
+
rvm:
|
12
|
+
- 1.9.3
|
13
|
+
- 2.0.0
|
14
|
+
- rbx-head
|
15
|
+
- jruby-head
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# CHANGES
|
2
2
|
|
3
|
+
## dm-is-reflective 1.2.0, 2013-05-14
|
4
|
+
|
5
|
+
* We got a bunch of internal renaming.
|
6
|
+
* Added DataMapper::Resource#to_source.
|
7
|
+
* Added an executable which generates sources for you.
|
8
|
+
* Fixed MySQL issues with setting up with a hash rather than URI.
|
9
|
+
* Fixed SQLite issues without loading dm-migrations.
|
10
|
+
|
3
11
|
## dm-is-reflective 1.1.0, 2013-01-11
|
4
12
|
|
5
13
|
* The need for dm-migrations is now removed.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# dm-is-reflective
|
1
|
+
# dm-is-reflective [![Build Status](https://secure.travis-ci.org/godfat/dm-is-reflective.png?branch=master)](http://travis-ci.org/godfat/dm-is-reflective)
|
2
2
|
|
3
3
|
by Lin Jen-Shin ([godfat](http://godfat.org))
|
4
4
|
|
@@ -21,99 +21,116 @@ It creates mappings between existing columns and model's properties.
|
|
21
21
|
## INSTALLATION:
|
22
22
|
|
23
23
|
``` shell
|
24
|
-
|
24
|
+
gem install dm-is-reflective
|
25
25
|
```
|
26
26
|
|
27
27
|
``` ruby
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
gem 'dm-is-reflective',
|
29
|
+
:git => 'git://github.com/godfat/dm-is-reflective.git',
|
30
|
+
:submodules => true
|
31
31
|
```
|
32
32
|
|
33
33
|
## SYNOPSIS:
|
34
34
|
|
35
|
+
### Generating sources from a DATABASE_URI
|
36
|
+
|
37
|
+
We also have an executable to generate sources for you.
|
38
|
+
|
39
|
+
```
|
40
|
+
Usage: dm-is-reflective DATABASE_URI
|
41
|
+
-s, --scope SCOPE SCOPE where the models should go (default: Object)
|
42
|
+
-o, --output DIRECTORY DIRECTORY where the output goes (default: dm-is-reflective)
|
43
|
+
-h, --help Print this message
|
44
|
+
-v, --version Print the version
|
45
|
+
```
|
46
|
+
|
47
|
+
### API
|
48
|
+
|
35
49
|
``` ruby
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
50
|
+
require 'dm-is-reflective' # this would require 'dm-core'
|
51
|
+
dm = DataMapper.setup :default, 'sqlite::memory:'
|
52
|
+
|
53
|
+
class User
|
54
|
+
include DataMapper::Resource
|
55
|
+
is :reflective
|
56
|
+
|
57
|
+
# map all, returning an array of properties indicating fields it mapped
|
58
|
+
reflect /.*/ # e.g. => [#<Property:#<Class:0x18f89b8>:id>,
|
59
|
+
# #<Property:#<Class:0x18f89b8>:title>,
|
60
|
+
# #<Property:#<Class:0x18f89b8>:body>,
|
61
|
+
# #<Property:#<Class:0x18f89b8>:user_id>]
|
62
|
+
|
63
|
+
# map all (with no argument at all)
|
64
|
+
reflect
|
65
|
+
|
66
|
+
# mapping for field name ended with _at, and started with salt_
|
67
|
+
reflect /_at$/, /^salt_/
|
68
|
+
|
69
|
+
# mapping id and email
|
70
|
+
reflect :id, :email
|
71
|
+
|
72
|
+
# mapping all fields with type String, and id
|
73
|
+
reflect String, :id
|
74
|
+
|
75
|
+
# mapping login, and all fields with type Integer
|
76
|
+
reflect :login, Integer
|
77
|
+
end
|
78
|
+
|
79
|
+
# there's no guarantee of the order in storages array
|
80
|
+
dm.storages
|
81
|
+
# => ['users']
|
82
|
+
|
83
|
+
# there's no guarantee of the order in fields array
|
84
|
+
User.fields
|
85
|
+
# => [[:created_at, DateTime, {:required => false}],
|
86
|
+
[:email, String, {:required => false, :length => 255,
|
87
|
+
:default => 'nospam@nospam.tw'}],
|
88
|
+
[:id, Serial, {:required => true, :serial => true,
|
89
|
+
:key => true}],
|
90
|
+
[:salt_first, String, {:required => false, :length => 50}],
|
91
|
+
[:salt_second, String, {:required => false, :length => 50}]]
|
92
|
+
|
93
|
+
dm.fields('users').sort_by{ |field| field.first.to_s } ==
|
94
|
+
User.fields.sort_by{ |field| field.first.to_s }
|
95
|
+
# => true
|
96
|
+
|
97
|
+
dm.storages_and_fields
|
98
|
+
# => {'users' => [[:id, Serial, {:required => true,
|
99
|
+
:serial => true,
|
100
|
+
:key => true}],
|
101
|
+
[:email, String, {:required => false,
|
102
|
+
:default =>
|
103
|
+
'nospam@nospam.tw'}],
|
104
|
+
[:created_at, DateTime, {:required => false}],
|
105
|
+
[:salt_first, String, {:required => false,
|
106
|
+
:length => 50}],
|
107
|
+
[:salt_second, String, {:required => false,
|
108
|
+
:length => 50}]]}
|
109
|
+
|
110
|
+
# there's no guarantee of the order in returned array
|
111
|
+
dm.auto_genclass!
|
112
|
+
# => [DataMapper::Is::Reflective::User,
|
113
|
+
DataMapper::Is::Reflective::SchemaInfo,
|
114
|
+
DataMapper::Is::Reflective::Session]
|
115
|
+
|
116
|
+
# you can change the scope of generated models:
|
117
|
+
dm.auto_genclass! :scope => Object
|
118
|
+
# => [User, SchemaInfo, Session]
|
119
|
+
|
120
|
+
# you can generate classes for tables you specified only:
|
121
|
+
dm.auto_genclass! :scope => Object, :storages => /^phpbb_/
|
122
|
+
# => [PhpbbUser, PhpbbPost, PhpbbConfig]
|
123
|
+
|
124
|
+
# you can generate classes with String too:
|
125
|
+
dm.auto_genclass! :storages => ['users', 'config'], :scope => Object
|
126
|
+
# => [User, Config]
|
127
|
+
|
128
|
+
# you can generate a class only:
|
129
|
+
dm.auto_genclass! :storages => 'users'
|
130
|
+
# => [DataMapper::Is::Reflective::User]
|
131
|
+
|
132
|
+
# you can also generate the source from models:
|
133
|
+
puts User.to_source
|
117
134
|
```
|
118
135
|
|
119
136
|
## CONTRIBUTORS:
|
data/Rakefile
CHANGED
@@ -15,7 +15,7 @@ task 'gem:spec' do
|
|
15
15
|
Gemgem.spec = Gemgem.create do |s|
|
16
16
|
require 'dm-is-reflective/version'
|
17
17
|
s.name = 'dm-is-reflective'
|
18
|
-
s.version =
|
18
|
+
s.version = DmIsReflective::VERSION
|
19
19
|
|
20
20
|
%w[dm-core dm-do-adapter].each{ |g| s.add_runtime_dependency(g) }
|
21
21
|
%w[dm-migrations
|
@@ -26,16 +26,3 @@ task 'gem:spec' do
|
|
26
26
|
|
27
27
|
Gemgem.write
|
28
28
|
end
|
29
|
-
|
30
|
-
desc 'auto_migrate database'
|
31
|
-
task 'auto_migrate' do
|
32
|
-
require 'dm-migrations'
|
33
|
-
require './test/abstract'
|
34
|
-
require './test/test_dm-is-reflective'
|
35
|
-
include Abstract
|
36
|
-
[:SqliteTest, :PostgresTest, :MysqlTest].each do |db|
|
37
|
-
next unless Object.const_defined?(db)
|
38
|
-
Object.const_get(db).setup_data_mapper
|
39
|
-
[User, Comment, SuperUser].each(&:auto_migrate!)
|
40
|
-
end
|
41
|
-
end
|
data/dm-is-reflective.gemspec
CHANGED
@@ -2,43 +2,55 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "dm-is-reflective"
|
5
|
-
s.version = "1.
|
5
|
+
s.version = "1.2.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Lin Jen-Shin (godfat)"]
|
9
|
-
s.date = "2013-
|
9
|
+
s.date = "2013-05-14"
|
10
10
|
s.description = "DataMapper plugin that helps you manipulate an existing database.\nIt creates mappings between existing columns and model's properties."
|
11
11
|
s.email = ["godfat (XD) godfat.org"]
|
12
|
+
s.executables = ["dm-is-reflective"]
|
12
13
|
s.files = [
|
13
14
|
".gitignore",
|
14
15
|
".gitmodules",
|
16
|
+
".travis.yml",
|
15
17
|
"CHANGES.md",
|
16
18
|
"Gemfile",
|
17
19
|
"LICENSE",
|
18
20
|
"README.md",
|
19
21
|
"Rakefile",
|
20
22
|
"TODO.md",
|
23
|
+
"bin/dm-is-reflective",
|
21
24
|
"dm-is-reflective.gemspec",
|
22
25
|
"lib/dm-is-reflective.rb",
|
23
|
-
"lib/dm-is-reflective/
|
24
|
-
"lib/dm-is-reflective/
|
25
|
-
"lib/dm-is-reflective/
|
26
|
-
"lib/dm-is-reflective/
|
27
|
-
"lib/dm-is-reflective/
|
26
|
+
"lib/dm-is-reflective/adapters/data_objects_adapter.rb",
|
27
|
+
"lib/dm-is-reflective/adapters/mysql_adapter.rb",
|
28
|
+
"lib/dm-is-reflective/adapters/postgres_adapter.rb",
|
29
|
+
"lib/dm-is-reflective/adapters/sqlite_adapter.rb",
|
30
|
+
"lib/dm-is-reflective/reflective.rb",
|
31
|
+
"lib/dm-is-reflective/runner.rb",
|
32
|
+
"lib/dm-is-reflective/test.rb",
|
28
33
|
"lib/dm-is-reflective/version.rb",
|
29
34
|
"task/.gitignore",
|
30
35
|
"task/gemgem.rb",
|
31
|
-
"test/abstract.rb",
|
32
36
|
"test/setup_db.sh",
|
33
|
-
"test/
|
37
|
+
"test/test_mysql.rb",
|
38
|
+
"test/test_postgres.rb",
|
39
|
+
"test/test_sqlite.rb",
|
40
|
+
"test/test_to_source.rb"]
|
34
41
|
s.homepage = "https://github.com/godfat/dm-is-reflective"
|
42
|
+
s.licenses = ["Apache License 2.0"]
|
35
43
|
s.require_paths = ["lib"]
|
36
|
-
s.rubygems_version = "
|
44
|
+
s.rubygems_version = "2.0.3"
|
37
45
|
s.summary = "DataMapper plugin that helps you manipulate an existing database."
|
38
|
-
s.test_files = [
|
46
|
+
s.test_files = [
|
47
|
+
"test/test_mysql.rb",
|
48
|
+
"test/test_postgres.rb",
|
49
|
+
"test/test_sqlite.rb",
|
50
|
+
"test/test_to_source.rb"]
|
39
51
|
|
40
52
|
if s.respond_to? :specification_version then
|
41
|
-
s.specification_version =
|
53
|
+
s.specification_version = 4
|
42
54
|
|
43
55
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
44
56
|
s.add_runtime_dependency(%q<dm-core>, [">= 0"])
|
data/lib/dm-is-reflective.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
|
2
|
-
gem 'dm-core', '>=1.0.0'
|
3
2
|
require 'dm-core'
|
4
3
|
require 'dm-do-adapter'
|
5
4
|
|
6
|
-
require 'dm-is-reflective/
|
7
|
-
require 'dm-is-reflective/
|
5
|
+
require 'dm-is-reflective/reflective'
|
6
|
+
require 'dm-is-reflective/adapters/data_objects_adapter'
|
8
7
|
|
9
|
-
DataMapper::Model.append_extensions(
|
8
|
+
DataMapper::Model.append_extensions(DmIsReflective)
|
10
9
|
|
11
10
|
DataMapper::Adapters::DataObjectsAdapter.__send__(:include,
|
12
|
-
|
11
|
+
DmIsReflective::DataObjectsAdapter)
|
@@ -0,0 +1,136 @@
|
|
1
|
+
|
2
|
+
module DmIsReflective::DataObjectsAdapter
|
3
|
+
include DataMapper
|
4
|
+
|
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, {:required => false}],
|
16
|
+
# [:email, String, {:required => false, :size => 255,
|
17
|
+
# :default => 'nospam@nospam.tw'}],
|
18
|
+
# [:id, DataMapper::Property::Serial, {:required => true, :serial => true,
|
19
|
+
# :key => true}],
|
20
|
+
# [:salt_first, String, {:required => false, :size => 50}],
|
21
|
+
# [:salt_second, String, {:required => false, :size => 50}]]
|
22
|
+
def fields storage
|
23
|
+
reflective_query_storage(storage).map{ |field|
|
24
|
+
attr = reflective_attributes(field)
|
25
|
+
type = reflective_lookup_primitive(reflective_primitive(field))
|
26
|
+
pick = if attr[:serial] && type == Integer
|
27
|
+
Property::Serial
|
28
|
+
else
|
29
|
+
type
|
30
|
+
end
|
31
|
+
[reflective_field_name(field).to_sym, pick, attr]
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
# returns a hash with storage names in keys and
|
36
|
+
# corresponded fields in values. e.g.
|
37
|
+
# {'users' => [[:id, Integer, {:required => true,
|
38
|
+
# :serial => true,
|
39
|
+
# :key => true}],
|
40
|
+
# [:email, String, {:required => false,
|
41
|
+
# :default => 'nospam@nospam.tw'}],
|
42
|
+
# [:created_at, DateTime, {:required => false}],
|
43
|
+
# [:salt_first, String, {:required => false, :size => 50}],
|
44
|
+
# [:salt_second, String, {:required => false, :size => 50}]]}
|
45
|
+
# see AbstractAdapter#storages and AbstractAdapter#fields for detail
|
46
|
+
def storages_and_fields
|
47
|
+
storages.inject({}){ |result, storage|
|
48
|
+
result[storage] = fields(storage)
|
49
|
+
result
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
# automaticly generate model class(es) and reflect
|
54
|
+
# all fields with reflect /.*/ for you.
|
55
|
+
# e.g.
|
56
|
+
# dm.auto_genclass!
|
57
|
+
# # => [DataMapper::Is::Reflective::User,
|
58
|
+
# # DataMapper::Is::Reflective::SchemaInfo,
|
59
|
+
# # DataMapper::Is::Reflective::Session]
|
60
|
+
#
|
61
|
+
# you can change the scope of generated models:
|
62
|
+
# e.g.
|
63
|
+
# dm.auto_genclass! :scope => Object
|
64
|
+
# # => [User, SchemaInfo, Session]
|
65
|
+
#
|
66
|
+
# you can generate classes for tables you specified only:
|
67
|
+
# e.g.
|
68
|
+
# dm.auto_genclass! :scope => Object, :storages => /^phpbb_/
|
69
|
+
# # => [PhpbbUser, PhpbbPost, PhpbbConfig]
|
70
|
+
#
|
71
|
+
# you can generate classes with String too:
|
72
|
+
# e.g.
|
73
|
+
# dm.auto_genclass! :storages => ['users', 'config'], :scope => Object
|
74
|
+
# # => [User, Config]
|
75
|
+
#
|
76
|
+
# you can generate a class only:
|
77
|
+
# e.g.
|
78
|
+
# dm.auto_genclass! :storages => 'users'
|
79
|
+
# # => [DataMapper::Is::Reflective::User]
|
80
|
+
def auto_genclass! opts = {}
|
81
|
+
opts[:scope] ||= DmIsReflective
|
82
|
+
opts[:storages] ||= /.*/
|
83
|
+
opts[:storages] = [opts[:storages]].flatten
|
84
|
+
|
85
|
+
storages.map{ |storage|
|
86
|
+
|
87
|
+
mapped = opts[:storages].each{ |target|
|
88
|
+
case target
|
89
|
+
when Regexp;
|
90
|
+
break storage if storage =~ target
|
91
|
+
|
92
|
+
when Symbol, String;
|
93
|
+
break storage if storage == target.to_s
|
94
|
+
|
95
|
+
else
|
96
|
+
raise ArgumentError.new("invalid argument: #{target.inspect}")
|
97
|
+
end
|
98
|
+
}
|
99
|
+
|
100
|
+
reflective_genclass(mapped, opts[:scope]) if mapped.kind_of?(String)
|
101
|
+
}.compact
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
def reflective_query_storage storage
|
106
|
+
reflective_auto_load_adapter_extension
|
107
|
+
reflective_query_storage(storage) # call the overrided method
|
108
|
+
end
|
109
|
+
|
110
|
+
def reflective_genclass storage, scope
|
111
|
+
model = Class.new
|
112
|
+
model.__send__(:include, Resource)
|
113
|
+
model.is(:reflective)
|
114
|
+
model.storage_names[:default] = storage
|
115
|
+
scope.const_set(Inflector.classify(storage), model)
|
116
|
+
model.__send__(:reflect, /.*/)
|
117
|
+
model.finalize if model.respond_to?(:finalize)
|
118
|
+
model
|
119
|
+
end
|
120
|
+
|
121
|
+
def reflective_lookup_primitive primitive
|
122
|
+
raise TypeError.new("#{primitive} not found for #{self.class}")
|
123
|
+
end
|
124
|
+
|
125
|
+
def reflective_auto_load_adapter_extension
|
126
|
+
# TODO: can we fix this shit in dm-mysql-adapter?
|
127
|
+
name = options[:adapter] || options['adapter']
|
128
|
+
# TODO: can we fix this adapter name in dm-sqlite-adapter?
|
129
|
+
adapter = name.sub(/\Asqlite3\Z/, 'sqlite')
|
130
|
+
|
131
|
+
require "dm-is-reflective/adapters/#{adapter}_adapter"
|
132
|
+
class_name = "#{Inflector.camelize(adapter)}Adapter"
|
133
|
+
Adapters.const_get(class_name).__send__(:include,
|
134
|
+
DmIsReflective.const_get(class_name))
|
135
|
+
end
|
136
|
+
end
|