dmapper 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +10 -0
- data/README.rdoc +153 -0
- data/bin/dmap +172 -0
- data/lib/dmap.rb +60 -0
- data/lib/dmap/core.rb +53 -0
- data/lib/dmap/new.rb +39 -0
- data/lib/dmap/properties.rb +36 -0
- data/lib/dmap/properties/boolean.rb +14 -0
- data/lib/dmap/properties/core.rb +35 -0
- data/lib/dmap/properties/date.rb +29 -0
- data/lib/dmap/properties/decimal.rb +17 -0
- data/lib/dmap/properties/integer.rb +15 -0
- data/lib/dmap/properties/misc.rb +25 -0
- data/lib/dmap/properties/serial.rb +10 -0
- data/lib/dmap/properties/string.rb +22 -0
- data/lib/dmap/validations/absence.rb +15 -0
- data/lib/dmap/validations/confirmation.rb +25 -0
- data/lib/dmap/validations/core.rb +95 -0
- data/lib/dmap/validations/format.rb +15 -0
- data/lib/dmap/validations/length.rb +13 -0
- data/lib/dmap/validations/method.rb +14 -0
- data/lib/dmap/validations/presence.rb +16 -0
- data/lib/dmap/validations/primitive.rb +16 -0
- data/lib/dmap/validations/uniqueness.rb +14 -0
- data/lib/dmap/validations/within.rb +15 -0
- metadata +105 -0
data/COPYING
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
Copyright (c) 2011, Daniel Durante
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
7
|
+
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
8
|
+
* Neither the name of Sinatra Fedora nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
9
|
+
|
10
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
= DMap
|
2
|
+
|
3
|
+
DMap is a generator for creating models with {DataMapper}[http://datamapper.org]. It's currently under a lot of development but I, as well as others, use it when for production use. As of right now majority of the validations work as expected and property types.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
gem install dmapper
|
7
|
+
|
8
|
+
== Usage
|
9
|
+
|
10
|
+
As of right now the only command available is <tt>new</tt>. Here's a basic example of DMap to explain the structure...
|
11
|
+
|
12
|
+
dmap new user id str:name str:email:required,unique str:password:required
|
13
|
+
|
14
|
+
The first, after <tt>dmap new</tt>, is the [table]. You can create multiple tables at a time by adding a comma (,). Every argument (<tt>space</tt>) is a separate [field]. Fields are divided into three sections by a colon (<tt>:</tt>). The first part is the field's [type]. The second part is the field's name, and the last part marks additional options for that field (explained later).
|
15
|
+
|
16
|
+
== Examples
|
17
|
+
|
18
|
+
Using DMap is incredibly easy once you learn the basic structure of it all. Here's a quick example...
|
19
|
+
|
20
|
+
dmap new user id str:username str:email text:signature
|
21
|
+
|
22
|
+
Which creates (user.rb file in the folder that you're currently in)...
|
23
|
+
|
24
|
+
class User
|
25
|
+
include DataMapper::Resource
|
26
|
+
|
27
|
+
property :signature
|
28
|
+
property :username
|
29
|
+
property :id
|
30
|
+
property :email
|
31
|
+
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
Let's get a little more "complex"
|
36
|
+
|
37
|
+
dmap new user id str:username str:email,required str:name:required,unique str:password datetime:date_created:default=Time.now text:signature
|
38
|
+
|
39
|
+
Which produces...
|
40
|
+
|
41
|
+
class User
|
42
|
+
include DataMapper::Resource
|
43
|
+
|
44
|
+
property :name, String, :required => true, :unique => true
|
45
|
+
property :required, String
|
46
|
+
property :signature, Text
|
47
|
+
property :username, String
|
48
|
+
property :id, Serial
|
49
|
+
property :password, String
|
50
|
+
property :date_created, DateTime, :default => Time.now
|
51
|
+
property :email, String
|
52
|
+
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
I know, still not that impressive, let's try something a tad more difficult...
|
57
|
+
|
58
|
+
dmap new user,user_copy id str:first_name,last_name datetime:name1:default=true,length=1..5,presence_of=title-publish20..50,length_of=1,absent,confirm=field,format=email_address,primitive,unique,accessor=private str:Name1
|
59
|
+
|
60
|
+
Which creates (along with a copy model "UserCopy" of the same exact thing)
|
61
|
+
|
62
|
+
class User
|
63
|
+
include DataMapper::Resource
|
64
|
+
|
65
|
+
property :id, Serial
|
66
|
+
property :name1, DateTime, :default => true, :accessor => private, :unique => true, :length => 1..5
|
67
|
+
property :last_name, String
|
68
|
+
property :Name1, String
|
69
|
+
property :first_name, String
|
70
|
+
|
71
|
+
validates_format_of :name1, :as => :email_address
|
72
|
+
validates_confirmation :name1, :confirm => :field
|
73
|
+
validates_absence_of :name1
|
74
|
+
validates_length_of :name1, :equals => 1
|
75
|
+
validates_presence_of :name1, :within => 20..50, :when => [:title, :publish]
|
76
|
+
validates_primitive_type_of :name1
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
== Types
|
81
|
+
|
82
|
+
Here is a list of all the types available from DataMapper, which ones we support, and custom aliases.
|
83
|
+
|
84
|
+
<table>
|
85
|
+
[DataMapper Property Type]</td><td>[DMap Command]</td><td>[Aliases]
|
86
|
+
<tt>Boolean</tt>::<tt>Boolean</tt>::<tt>Bool</tt>
|
87
|
+
<tt>String</tt>::<tt>String</tt>::<tt>Str, S</tt>
|
88
|
+
<tt>Text</tt>::<tt>Text</tt>::<tt>Txt</tt>
|
89
|
+
<tt>Float</tt>::<tt>Float</tt>::<tt>F</tt>
|
90
|
+
<tt>Integer</tt>::<tt>Integer</tt>::<tt>Int, I</tt>
|
91
|
+
<tt>Decimal</tt>::<tt>Decimal</tt>::<tt>Dec</tt>
|
92
|
+
<tt>DateTime</tt>::<tt>DateTime</tt>::<tt>DT</tt>
|
93
|
+
<tt>Date</tt>::<tt>Date</tt>::<tt>D</tt>
|
94
|
+
<tt>Time</tt>::<tt>Time</tt>::<tt>T</tt>
|
95
|
+
<tt>Object</tt>::<tt>Object</tt>::<tt>Obj</tt>
|
96
|
+
<tt>Discriminator</tt>::<tt>Discriminator</tt>::<tt>Disc</tt>
|
97
|
+
<tt>Binary</tt>::<tt>Binary</tt>::<tt>Blob, B</tt>
|
98
|
+
</table>
|
99
|
+
|
100
|
+
More coming soon!
|
101
|
+
|
102
|
+
== Property Validators
|
103
|
+
|
104
|
+
This part belongs in the third section of the command for example:
|
105
|
+
|
106
|
+
dmap new user id str:name:[required,accessor=private]
|
107
|
+
|
108
|
+
Each validator is separated by a comma (<tt>,</tt>) and can have a value placed within it by an equal sign (<tt>=</tt>). The property name will look like...
|
109
|
+
|
110
|
+
property :name, String, :required => true, :accessor => :private
|
111
|
+
|
112
|
+
|
113
|
+
=== Property Validator List
|
114
|
+
|
115
|
+
[DataMapper's List]:: [DMap Command]
|
116
|
+
<tt>required</tt>:: <tt>required</tt>
|
117
|
+
<tt>default</tt>:: <tt>default</tt>
|
118
|
+
<tt>key</tt>:: <tt>key</tt>
|
119
|
+
<tt>lazy</tt>:: <tt>lazy</tt> - Only accepts "false" for now
|
120
|
+
<tt>accessor</tt>:: <tt>accessor</tt>
|
121
|
+
<tt>writer</tt>:: <tt>writer</tt>
|
122
|
+
<tt>reader</tt>:: <tt>reader</tt>
|
123
|
+
|
124
|
+
That's all the ones I know for now, let me know if there are more!
|
125
|
+
|
126
|
+
== Validations
|
127
|
+
|
128
|
+
A list of all of the validates_*_of commands and which DMap currently supports
|
129
|
+
|
130
|
+
[DataMapper's List]:: [DMap Command] [Notes]
|
131
|
+
<tt>validates_absence_of</tt>:: <tt>absence, absent</tt>
|
132
|
+
<tt>validates_acceptance_of</tt>:: <tt>acceptance, accept</tt>:: Does not accept :allow_nil options yet
|
133
|
+
<tt>validates_with_block</tt>:: </td><td>Unsupported at this time
|
134
|
+
<tt>validates_confirmation_of</tt>:: <tt>confirmation, confirm</tt>
|
135
|
+
<tt>validates_format_of</tt>:: <tt>format</tt>
|
136
|
+
<tt>validates_length_of</tt>:: <tt>length_of</tt>
|
137
|
+
<tt>validates_with_method</tt>:: <tt>withmethod, method</tt>
|
138
|
+
<tt>validates_numericality_of</tt>:: <tt>Unsupported</tt>
|
139
|
+
<tt>validates_primitive_type_of</tt>:: <tt>primitive</tt>
|
140
|
+
<tt>validates_presence_of</tt>:: <tt>presence, present</tt>
|
141
|
+
<tt>validates_uniqueness_of</tt>:: <tt>uniqueness</tt>
|
142
|
+
<tt>validates_within</tt>:: <tt>within</tt>
|
143
|
+
|
144
|
+
== To Do
|
145
|
+
|
146
|
+
* Add a verbose option
|
147
|
+
* Add a way to add/edit/remove columns from pre-existing tables
|
148
|
+
* Backup option before overwriting
|
149
|
+
* All of the misc. property types
|
150
|
+
* Better validation checkers
|
151
|
+
* Associations! (this will be done first)
|
152
|
+
* Template system similar to {Sinatra::Fedora's}[https://github.com/durango/sinatra_fedora] hatrack option
|
153
|
+
* Better documentation!
|
data/bin/dmap
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'erb'
|
6
|
+
|
7
|
+
$: << File.join(File.dirname(__FILE__), '../lib/')
|
8
|
+
require 'dmap'
|
9
|
+
|
10
|
+
opt_parser = OptionParser.new do |opt|
|
11
|
+
opt.banner = "Usage: dmap COMMAND [OPTIONS]"
|
12
|
+
opt.separator ""
|
13
|
+
opt.separator "Commands"
|
14
|
+
opt.separator " new <model name> [options]: Creates a new model"
|
15
|
+
opt.separator " e.g. dmap new User serial:id str:name:length=1..5,unique str:email text:signature"
|
16
|
+
opt.separator ""
|
17
|
+
end
|
18
|
+
|
19
|
+
opt_parser.parse!
|
20
|
+
|
21
|
+
if ARGV[0].nil?
|
22
|
+
puts opt_parser
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
|
26
|
+
unless DMap::Commands.exists?(ARGV[0])
|
27
|
+
puts ARGV[0] + " is not a valid command."
|
28
|
+
puts opt_parser
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
|
32
|
+
# safe guard table names
|
33
|
+
table_names = ARGV[1].match /^\[*([a-zA-Z0-9,_]+)\]*$/
|
34
|
+
if table_names.nil?
|
35
|
+
puts "Invalid table name, only characters A-Z, 0-9, and _ are allowed."
|
36
|
+
puts opt_parser
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
|
40
|
+
# Store all of the tables for this action
|
41
|
+
table_names[1].split(',').each do |table|
|
42
|
+
# camelcase model name
|
43
|
+
model_name = table.capitalize
|
44
|
+
model_name.gsub!(/(_(.))/) { |a| a.sub('_','').upcase }
|
45
|
+
table.downcase!
|
46
|
+
|
47
|
+
DMap::Tables.add model_name, model_name.underscore
|
48
|
+
if File.file? "./#{table}.rb"
|
49
|
+
puts "A model with the name of #{table} already exists."
|
50
|
+
exit 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
ARGV[2..-1].each do |command|
|
55
|
+
# TODO: Add a shortcut module/class
|
56
|
+
command = "serial:id" if command == "id"
|
57
|
+
|
58
|
+
keys = command.split(':')
|
59
|
+
unless DMap::Fields.list.include?(keys[0]) or DMap::Properties.valid?(keys[0].camelcase)
|
60
|
+
puts keys[0] + " is not a valid property or field"
|
61
|
+
puts opt_parser
|
62
|
+
exit 1
|
63
|
+
end
|
64
|
+
|
65
|
+
# Check if the "command" is a key first (keys always overrule)
|
66
|
+
if DMap::Fields.list.include?(keys[0])
|
67
|
+
keys.unshift(DMap::Fields.list[keys[0]])
|
68
|
+
else
|
69
|
+
# Can't create two fields with the same name
|
70
|
+
if DMap::Fields.list.include?(keys[1])
|
71
|
+
puts keys[1] + " is already a declared field. You cannot declare a field twice."
|
72
|
+
puts opt_parser
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
|
76
|
+
# We really only need to do this when we're declaring a field with a type
|
77
|
+
# Gets proper property name (e.g. "Dt" becomes "DateTime")
|
78
|
+
property_class = DMap::Properties.const_get(keys[0].camelcase)
|
79
|
+
begin
|
80
|
+
keys[0] = property_class.superclass.parent_name
|
81
|
+
rescue
|
82
|
+
keys[0] = keys[0].camelcase
|
83
|
+
end
|
84
|
+
|
85
|
+
# Allow to declare multiple fields at once
|
86
|
+
keys[1].split(',').each do |key|
|
87
|
+
DMap::Fields.add key, keys[0]
|
88
|
+
DMap::Tables.list.each do |table|
|
89
|
+
DMap::Properties.add table, key, keys[0], 'type'
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Add validations
|
95
|
+
unless keys[2].nil?
|
96
|
+
keys[2].split(',').each do |cmds|
|
97
|
+
validation = cmds.split('=')
|
98
|
+
|
99
|
+
# Let's check if it's a validates_*_of first
|
100
|
+
begin
|
101
|
+
if DMap::Validations.const_defined? validation[0].camelcase
|
102
|
+
# See if we're just an alias command...
|
103
|
+
original_class = DMap::Validations.const_get(validation[0].camelcase)
|
104
|
+
begin
|
105
|
+
original_name = original_class.superclass.parent_name
|
106
|
+
rescue
|
107
|
+
original_name = validation[0].camelcase
|
108
|
+
end
|
109
|
+
original_name = original_name.underscore.downcase
|
110
|
+
|
111
|
+
# Compile all of the otptions for the validation
|
112
|
+
struct = DMap::Validations.const_get(original_name.camelcase).validate validation[1]
|
113
|
+
|
114
|
+
# Finally, add the validations!
|
115
|
+
struct.each do |key, value|
|
116
|
+
DMap::Validations.add keys[1], original_name, key, value unless value.nil? || key == :cmd
|
117
|
+
end
|
118
|
+
next
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Does the validation exist
|
123
|
+
property = DMap::Properties.const_get keys[0].capitalize
|
124
|
+
unless property.respond_to? validation[0] or DMap::Validations.respond_to? validation[0]
|
125
|
+
puts "Invalid validation command " + validation[0] + " in type " + property.to_s
|
126
|
+
puts opt_parser
|
127
|
+
exit 1
|
128
|
+
end
|
129
|
+
|
130
|
+
# Use class specific validation or generic if one doesn't exist
|
131
|
+
use_method = property.method validation[0] if property.respond_to? validation[0]
|
132
|
+
use_method = DMap::Validations.method validation[0] unless use_method
|
133
|
+
|
134
|
+
# Check to see if the validation returns true based on our input
|
135
|
+
unless use_method.call(validation[1]) == true
|
136
|
+
puts "Invalid value for validation " + validation[0] + " in type " + property.to_s
|
137
|
+
puts opt_parser
|
138
|
+
exit 1
|
139
|
+
end
|
140
|
+
|
141
|
+
# Add the "core" validations (on properties)
|
142
|
+
DMap::Tables.list.each do |table|
|
143
|
+
validation[1] = true if validation[1].nil?
|
144
|
+
DMap::Properties.add table, keys[1], validation[1], validation[0]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Good for debugging
|
151
|
+
#p DMap::Fields.list
|
152
|
+
#p DMap::Tables.list
|
153
|
+
#p DMap::Properties.list
|
154
|
+
#p DMap::Validations.list
|
155
|
+
#p DMap::Associations.list TODO
|
156
|
+
|
157
|
+
case ARGV[0]
|
158
|
+
when "new"
|
159
|
+
DMap::Tables.list.each do |table|
|
160
|
+
properties = DMap::Properties.list[table]
|
161
|
+
validations = DMap::Validations.list
|
162
|
+
p "Compiling model " + table[0]
|
163
|
+
obj = $new_block.result(binding)
|
164
|
+
|
165
|
+
handler = File.new(table[1] + ".rb", "w")
|
166
|
+
handler.write(obj)
|
167
|
+
handler.close
|
168
|
+
p table[0] + " saved successfully"
|
169
|
+
end
|
170
|
+
else
|
171
|
+
puts opt_parser
|
172
|
+
end
|
data/lib/dmap.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
=begin
|
2
|
+
dmap.rb - Foundation of dmap
|
3
|
+
*
|
4
|
+
* Copyright (c) 2011, Daniel Durante <officedebo at gmail dot com>
|
5
|
+
* All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following conditions are met:
|
9
|
+
*
|
10
|
+
* * Redistributions of source code must retain the above copyright notice,
|
11
|
+
* this list of conditions and the following disclaimer.
|
12
|
+
* * Redistributions in binary form must reproduce the above copyright
|
13
|
+
* notice, this list of conditions and the following disclaimer in the
|
14
|
+
* documentation and/or other materials provided with the distribution.
|
15
|
+
* * Neither the name of Redis nor the names of its contributors may be used
|
16
|
+
* to endorse or promote products derived from this software without
|
17
|
+
* specific prior written permission.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
=end
|
31
|
+
|
32
|
+
libdir = File.dirname(__FILE__)
|
33
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
34
|
+
|
35
|
+
# Core
|
36
|
+
require 'dmap/core'
|
37
|
+
|
38
|
+
# Properties
|
39
|
+
require 'dmap/properties/core'
|
40
|
+
require 'dmap/properties/boolean'
|
41
|
+
require 'dmap/properties/date' # DateTime, Date and Time
|
42
|
+
require 'dmap/properties/decimal' # Float and Decimal
|
43
|
+
require 'dmap/properties/integer'
|
44
|
+
require 'dmap/properties/misc' # Object, Discriminator, Blob
|
45
|
+
require 'dmap/properties/serial'
|
46
|
+
require 'dmap/properties/string' # String and Text
|
47
|
+
|
48
|
+
# Validations
|
49
|
+
require 'dmap/validations/core'
|
50
|
+
require 'dmap/validations/absence'
|
51
|
+
require 'dmap/validations/confirmation' # Confirmation and Acceptance
|
52
|
+
require 'dmap/validations/format'
|
53
|
+
require 'dmap/validations/length'
|
54
|
+
require 'dmap/validations/method'
|
55
|
+
require 'dmap/validations/presence'
|
56
|
+
require 'dmap/validations/primitive'
|
57
|
+
require 'dmap/validations/within'
|
58
|
+
|
59
|
+
# Template for building new model
|
60
|
+
require 'dmap/new'
|
data/lib/dmap/core.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# We'll be needing to convert to CamelCase and under_score quite a bit
|
2
|
+
class String
|
3
|
+
def camelcase
|
4
|
+
self.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
5
|
+
end
|
6
|
+
|
7
|
+
def underscore
|
8
|
+
self.gsub(/::/, '/').
|
9
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
10
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
11
|
+
tr("-", "_").
|
12
|
+
downcase
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
#DMap Core functions + Table and Fields
|
17
|
+
module DMap
|
18
|
+
# List available commands here
|
19
|
+
class Commands
|
20
|
+
def self.exists?(command)
|
21
|
+
list = %w[ new ].include? command
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Fields
|
26
|
+
attr_accessor :list
|
27
|
+
|
28
|
+
def self.list
|
29
|
+
@list ||= Hash[]
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.add(field, property=nil)
|
33
|
+
list.store field, property unless property.nil?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Tables
|
38
|
+
attr_accessor :list
|
39
|
+
|
40
|
+
def inheritance(value=nil)
|
41
|
+
list.push value unless value.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.list
|
45
|
+
@list ||= Hash[]
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.add(key, value=nil)
|
49
|
+
list[key] = {} if list[key].nil?
|
50
|
+
list.store key, value unless value.nil?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/dmap/new.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
$new_block = ERB.new <<-EOF
|
2
|
+
class <%= table[0] %>
|
3
|
+
include DataMapper::Resource
|
4
|
+
<%
|
5
|
+
$str = ''
|
6
|
+
properties.each do |k, val|
|
7
|
+
$str += ' property :' + k
|
8
|
+
$str += ', ' + val["type"] unless val["type"].nil?
|
9
|
+
val.each do |key, v|
|
10
|
+
next if key == "type"
|
11
|
+
v = ":" + v if v == "protected" || v == "private" || v == "public"
|
12
|
+
$str += ', :' + key + ' => ' + v.to_s
|
13
|
+
end
|
14
|
+
$str += "\n"
|
15
|
+
end
|
16
|
+
|
17
|
+
$str += "\n"
|
18
|
+
|
19
|
+
validations.each do |field, value|
|
20
|
+
value.each do |key, v|
|
21
|
+
$str += " validates_" + key + " :" + field + ", "
|
22
|
+
v.each do |k, cmd|
|
23
|
+
next if k == :null
|
24
|
+
cmd = ":" + field if cmd == :self
|
25
|
+
cmd = '"' + cmd + '"' if cmd.is_a?(String)
|
26
|
+
k = ":" + k.to_s if k.is_a?(Symbol)
|
27
|
+
cmd = ":" + cmd.to_s if cmd.is_a?(Symbol)
|
28
|
+
cmd = "[" + cmd.map {|x| ":" + x}.join(', ') + "]" if cmd.is_a?(Array)
|
29
|
+
|
30
|
+
$str += k.to_s + " => " + cmd.to_s + ", "
|
31
|
+
end
|
32
|
+
$str.slice!(-2)
|
33
|
+
$str += "\n"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
%>
|
37
|
+
<%= $str %>
|
38
|
+
end
|
39
|
+
EOF
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module DMap
|
2
|
+
module Properties
|
3
|
+
attr_accessor :list
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def required(value)
|
7
|
+
value.is_a?(Boolean)
|
8
|
+
end
|
9
|
+
|
10
|
+
def valid?(klass)
|
11
|
+
begin
|
12
|
+
# Don't need if I need to do the sub() thing anymore...
|
13
|
+
self.const_get(klass.capitalize.sub('Datetime', 'DateTime')).is_a?(Class)
|
14
|
+
rescue
|
15
|
+
false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def list
|
20
|
+
@list ||= Hash[]
|
21
|
+
end
|
22
|
+
|
23
|
+
def add(table, property=nil, value=nil, bucket=nil)
|
24
|
+
list[table] = {} if list[table].nil?
|
25
|
+
unless property.nil?
|
26
|
+
list[table][property] = {} if list[table][property].nil?
|
27
|
+
if bucket.nil?
|
28
|
+
list[table].store property, value unless value.nil?
|
29
|
+
else
|
30
|
+
list[table][property][bucket] = value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module DMap
|
2
|
+
module Properties
|
3
|
+
attr_accessor :list
|
4
|
+
class << self
|
5
|
+
# default methods
|
6
|
+
def required(value)
|
7
|
+
value.is_a?(Boolean)
|
8
|
+
end
|
9
|
+
|
10
|
+
def valid?(klass)
|
11
|
+
begin
|
12
|
+
self.const_get(klass.capitalize).is_a?(Class)
|
13
|
+
rescue
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def list
|
19
|
+
@list ||= Hash[]
|
20
|
+
end
|
21
|
+
|
22
|
+
def add(table, property=nil, value=nil, bucket=nil)
|
23
|
+
list[table] = {} if list[table].nil?
|
24
|
+
unless property.nil?
|
25
|
+
list[table][property] = {} if list[table][property].nil?
|
26
|
+
if bucket.nil?
|
27
|
+
list[table].store property, value unless value.nil?
|
28
|
+
else
|
29
|
+
list[table][property][bucket] = value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module DMap
|
2
|
+
module Properties
|
3
|
+
class Date
|
4
|
+
def self.parent_name
|
5
|
+
"Date"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
class D < Date; end
|
9
|
+
|
10
|
+
class DateTime
|
11
|
+
def self.default(value=nil)
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.parent_name
|
16
|
+
"DateTime"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
class Datetime < DateTime; end
|
20
|
+
class Dt < DateTime; end
|
21
|
+
|
22
|
+
class Time
|
23
|
+
def self.parent_name
|
24
|
+
"Time"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
class T < Time; end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module DMap
|
2
|
+
module Properties
|
3
|
+
class Integer
|
4
|
+
def length(value)
|
5
|
+
false unless (value.is_a(Fixnum) || value.is_a(Integer))
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.parent_name
|
9
|
+
"Integer"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class Int < Integer; end
|
13
|
+
class I < Integer; end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module DMap
|
2
|
+
module Properties
|
3
|
+
class Object
|
4
|
+
def self.parent_name
|
5
|
+
"Object"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
class Obj < Object; end
|
9
|
+
|
10
|
+
class Discriminator
|
11
|
+
def self.parent_name
|
12
|
+
"Discriminator"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
class Disc < Discriminator; end
|
16
|
+
|
17
|
+
class Binary
|
18
|
+
def self.parent_name
|
19
|
+
"Binary"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
class Blob < Binary; end
|
23
|
+
class B < Binary; end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module DMap
|
2
|
+
module Properties
|
3
|
+
class String
|
4
|
+
def self.default(value)
|
5
|
+
true
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.parent_name
|
9
|
+
"String"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class Str < String; end
|
13
|
+
class S < String; end
|
14
|
+
|
15
|
+
class Text
|
16
|
+
def self.parent_name
|
17
|
+
"Text"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
class Txt < Text; end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module DMap
|
2
|
+
module Validations
|
3
|
+
class Confirmation
|
4
|
+
def self.parent_name
|
5
|
+
"Confirmation"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.validate(command=nil)
|
9
|
+
{:confirm => command.to_sym}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class Confirm < Confirmation; end
|
13
|
+
|
14
|
+
class Acceptance
|
15
|
+
def self.parent_name
|
16
|
+
"Acceptance"
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.validate(command=nil)
|
20
|
+
{:accept => command.to_s}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
class Accept < Acceptance; end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module DMap
|
2
|
+
# Default validations if Property::Type doesn't have it
|
3
|
+
module Validations
|
4
|
+
attr_accessor :list
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def list
|
8
|
+
@list ||= Hash[]
|
9
|
+
end
|
10
|
+
|
11
|
+
def default(value=nil)
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def length(value=nil)
|
16
|
+
true if value.match /^\d+$/ or value.match /^\d+\.\.\d+$/
|
17
|
+
end
|
18
|
+
|
19
|
+
def unique(value=nil)
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def key(value=nil)
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def required(value=nil)
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
def lazy(value=nil)
|
32
|
+
false # Not true since lazy is loaded by default
|
33
|
+
end
|
34
|
+
|
35
|
+
def accessor(value=nil)
|
36
|
+
return true if value == "protected" or value == "private" or value == "public"
|
37
|
+
end
|
38
|
+
|
39
|
+
def writer(value=nil)
|
40
|
+
return true if value == "protected" or value == "private" or value == "public"
|
41
|
+
end
|
42
|
+
|
43
|
+
def reader(value=nil)
|
44
|
+
return true if value == "protected" or value == "private" or value == "public"
|
45
|
+
end
|
46
|
+
|
47
|
+
# validates_*_of
|
48
|
+
def add(field, validation, bucket, value)
|
49
|
+
list[field] = {} if list[field].nil?
|
50
|
+
list[field][validation] = {} if list[field][validation].nil?
|
51
|
+
list[field][validation][bucket] = {} if list[field][validation][bucket].nil?
|
52
|
+
list[field][validation].store bucket, value unless value.nil?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module Core
|
57
|
+
module When
|
58
|
+
def self.run(validation)
|
59
|
+
{:when => validation.split('-')}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
module Fields
|
64
|
+
def self.run(validation)
|
65
|
+
{:fields => validation.split('-')}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
module Numbers
|
70
|
+
def self.run(validation)
|
71
|
+
# Let's get the minimum/maximum numbers e.g. 20min50max
|
72
|
+
minimum = validation[/(\d+)min/, 1] # fetch min
|
73
|
+
unless minimum.nil? # take it out
|
74
|
+
validation.sub!(/\d+min/i, '')
|
75
|
+
end
|
76
|
+
|
77
|
+
maximum = validation[/(\d+)max/, 1]
|
78
|
+
unless maximum.nil? # take it out
|
79
|
+
validation.sub!(/\d+max/i, '')
|
80
|
+
end
|
81
|
+
|
82
|
+
# Now for the min..max e.g. 20..50
|
83
|
+
within = validation[/(\d+\.\.\d+)/, 1] unless minimum or maximum
|
84
|
+
validation.sub!(/\d+\.\.\d+/, '')
|
85
|
+
|
86
|
+
# Just equals? e.g. length_of=5
|
87
|
+
equals = validation[/^(\d+)$/, 1] unless minimum or maximum
|
88
|
+
validation.sub!(/^\d+$/, '')
|
89
|
+
|
90
|
+
{:cmd => validation, :min => minimum, :max => maximum, :within => within, :equals => equals}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module DMap
|
2
|
+
module Validations
|
3
|
+
class FormatOf
|
4
|
+
def self.parent_name
|
5
|
+
"FormatOf"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.validate(command=nil)
|
9
|
+
command = command.to_sym if command.match(/^[A-Za-z]/)
|
10
|
+
{:as => command}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
class Format < FormatOf; end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module DMap
|
2
|
+
module Validations
|
3
|
+
class PresenceOf
|
4
|
+
def self.parent_name
|
5
|
+
"PresenceOf"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.validate(command=nil)
|
9
|
+
ret = DMap::Validations::Core::Numbers.run command
|
10
|
+
ret1 = DMap::Validations::Core::When.run ret[:cmd]
|
11
|
+
ret.merge!(ret1)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
class Present < PresenceOf; end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module DMap
|
2
|
+
module Validations
|
3
|
+
class PrimitiveTypeOf
|
4
|
+
def self.parent_name
|
5
|
+
"PrimitiveTypeOf"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.validate(command=nil)
|
9
|
+
{:null => true}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class PrimitiveType < PrimitiveTypeOf; end
|
13
|
+
class PrimitiveOf < PrimitiveTypeOf; end
|
14
|
+
class Primitive < PrimitiveTypeOf; end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module DMap
|
2
|
+
module Validations
|
3
|
+
class Within
|
4
|
+
def self.parent_name
|
5
|
+
"Within"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.validate(command=nil)
|
9
|
+
ret = DMap::Validations::Core::Numbers.run command
|
10
|
+
ret1 = DMap::Validations::Core::Fields.run command
|
11
|
+
ret.merge!(ret1)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dmapper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 9
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: "0.1"
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Daniel Durante
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-07-02 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: data_mapper
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description: Create models easily for DataMapper using the command line.
|
35
|
+
email: officedebo@gmail.com
|
36
|
+
executables:
|
37
|
+
- dmap
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files: []
|
41
|
+
|
42
|
+
files:
|
43
|
+
- bin/dmap
|
44
|
+
- lib/dmap/core.rb
|
45
|
+
- lib/dmap/new.rb
|
46
|
+
- lib/dmap/properties/boolean.rb
|
47
|
+
- lib/dmap/properties/core.rb
|
48
|
+
- lib/dmap/properties/date.rb
|
49
|
+
- lib/dmap/properties/decimal.rb
|
50
|
+
- lib/dmap/properties/integer.rb
|
51
|
+
- lib/dmap/properties/misc.rb
|
52
|
+
- lib/dmap/properties/serial.rb
|
53
|
+
- lib/dmap/properties/string.rb
|
54
|
+
- lib/dmap/properties.rb
|
55
|
+
- lib/dmap/validations/absence.rb
|
56
|
+
- lib/dmap/validations/confirmation.rb
|
57
|
+
- lib/dmap/validations/core.rb
|
58
|
+
- lib/dmap/validations/format.rb
|
59
|
+
- lib/dmap/validations/length.rb
|
60
|
+
- lib/dmap/validations/method.rb
|
61
|
+
- lib/dmap/validations/presence.rb
|
62
|
+
- lib/dmap/validations/primitive.rb
|
63
|
+
- lib/dmap/validations/uniqueness.rb
|
64
|
+
- lib/dmap/validations/within.rb
|
65
|
+
- lib/dmap.rb
|
66
|
+
- COPYING
|
67
|
+
- README.rdoc
|
68
|
+
has_rdoc: true
|
69
|
+
homepage: https://github.com/durango/dmap
|
70
|
+
licenses:
|
71
|
+
- MIT
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
hash: 3
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
version: "0"
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 23
|
92
|
+
segments:
|
93
|
+
- 1
|
94
|
+
- 3
|
95
|
+
- 6
|
96
|
+
version: 1.3.6
|
97
|
+
requirements: []
|
98
|
+
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 1.6.2
|
101
|
+
signing_key:
|
102
|
+
specification_version: 3
|
103
|
+
summary: Generators for DataMapper
|
104
|
+
test_files: []
|
105
|
+
|