dmapper 0.1 → 0.2

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.
@@ -0,0 +1,16 @@
1
+ 0.2 July 4th, 2011
2
+
3
+ * Properties now maintain correct order
4
+ * Added tiny 'helpers' (e.g. Time.now becomes proc => { Time.now })
5
+ * Switched the order of operations (from type:field:options to field:type:options)
6
+ * Lazy accepts true/false/fields
7
+ * Added a verbose option -v
8
+ * Added a testing option -t
9
+ * Added a backup option -b
10
+ * Added a silent/suppress option -s
11
+ * Much better validation handlers (still needs quite a bit of work)
12
+ * Added association support!
13
+
14
+ 0.1 - July 3rd, 2011
15
+
16
+ * Initial Release
@@ -1,6 +1,8 @@
1
1
  = DMap
2
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.
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 for production use. DataMapper gems are not even required for this gem/tool.
4
+
5
+ "DMap a shorter way for saying, and using, DataMapper"
4
6
 
5
7
  == Installation
6
8
  gem install dmapper
@@ -9,53 +11,60 @@ DMap is a generator for creating models with {DataMapper}[http://datamapper.org]
9
11
 
10
12
  As of right now the only command available is <tt>new</tt>. Here's a basic example of DMap to explain the structure...
11
13
 
12
- dmap new user id str:name str:email:required,unique str:password:required
14
+ dmap new user id name:string email:str:required,unique str:password:required
13
15
 
14
16
  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
17
 
18
+ == Options
19
+
20
+ <b><tt>-b, --backup</tt></b>:: Backs up the current model files (renames them to *.rb.bk)
21
+ <b><tt>-h, --help</tt></b>:: Displays help message
22
+ <b><tt>-s, --silent</tt></b>:: If you entered incorrect values for a validation just suppress it and continue on.
23
+ <b><tt>-t, --test</tt></b>:: Displays what DMap would have made into a file onto the screen.
24
+ <b><tt>-v, --verbose</tt></b>:: Will print out the model(s) after changes have been made
25
+
16
26
  == Examples
17
27
 
18
28
  Using DMap is incredibly easy once you learn the basic structure of it all. Here's a quick example...
19
29
 
20
- dmap new user id str:username str:email text:signature
30
+ dmap new user id username:str email:str signature:text
21
31
 
22
32
  Which creates (user.rb file in the folder that you're currently in)...
23
33
 
24
34
  class User
25
35
  include DataMapper::Resource
26
36
 
27
- property :signature
28
- property :username
29
- property :id
30
- property :email
37
+ property :id, Serial
38
+ property :username, String
39
+ property :email, String
40
+ property :signature, Text
31
41
 
32
42
 
33
43
  end
34
44
 
35
45
  Let's get a little more "complex"
36
46
 
37
- dmap new user id str:username str:email,required str:name:required,unique str:password datetime:date_created:default=Time.now text:signature
47
+ dmap new user id username:str email:str:required name:str:required,unique password:str date_crtd:datetime:default=DateTime.now signature:text
38
48
 
39
49
  Which produces...
40
50
 
41
51
  class User
42
52
  include DataMapper::Resource
43
53
 
44
- property :name, String, :required => true, :unique => true
45
- property :required, String
46
- property :signature, Text
47
- property :username, String
48
54
  property :id, Serial
55
+ property :username, String
56
+ property :email, String, :required => true
57
+ property :name, String, :required => true, :unique => true
49
58
  property :password, String
50
- property :date_created, DateTime, :default => Time.now
51
- property :email, String
59
+ property :date_crtd, DateTime, :default => proc => { DateTime.now }
60
+ property :signature, Text
52
61
 
53
62
 
54
63
  end
55
64
 
56
65
  I know, still not that impressive, let's try something a tad more difficult...
57
66
 
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
67
+ dmap new user,user_copy id first_name,last_name:str name1:datetime:default=true,length=1..5,presence_of=title-publish20..50,length_of=1,absent,confirm=field,format=email_address,primitive,unique,accessor=private Name1:str
59
68
 
60
69
  Which creates (along with a copy model "UserCopy" of the same exact thing)
61
70
 
@@ -63,10 +72,10 @@ Which creates (along with a copy model "UserCopy" of the same exact thing)
63
72
  include DataMapper::Resource
64
73
 
65
74
  property :id, Serial
66
- property :name1, DateTime, :default => true, :accessor => private, :unique => true, :length => 1..5
75
+ property :first_name, String
67
76
  property :last_name, String
77
+ property :name1, DateTime, :default => true, :length => 1..5, :unique => true, :accessor => :private
68
78
  property :Name1, String
69
- property :first_name, String
70
79
 
71
80
  validates_format_of :name1, :as => :email_address
72
81
  validates_confirmation :name1, :confirm => :field
@@ -81,21 +90,19 @@ Which creates (along with a copy model "UserCopy" of the same exact thing)
81
90
 
82
91
  Here is a list of all the types available from DataMapper, which ones we support, and custom aliases.
83
92
 
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>
93
+ <b>DataMapper Property Type</b>:: <b>DMap Command/Aliases</b>
94
+ <tt>Boolean</tt>:: <tt>boolean</tt>, <tt>bool</tt>
95
+ <tt>String</tt>:: <tt>string</tt>, <tt>str, s</tt>
96
+ <tt>Text</tt>:: <tt>text</tt>, <tt>txt</tt>
97
+ <tt>Float</tt>:: <tt>float</tt>, <tt>f</tt>
98
+ <tt>Integer</tt>:: <tt>integer</tt>, <tt>int, i</tt>
99
+ <tt>Decimal</tt>:: <tt>decimal</tt>, <tt>dec</tt>
100
+ <tt>DateTime</tt>:: <tt>datetime</tt>, <tt>dt</tt>
101
+ <tt>Date</tt>:: <tt>date</tt>, <tt>d</tt>
102
+ <tt>Time</tt>:: <tt>time</tt>, <tt>t</tt>
103
+ <tt>Object</tt>:: <tt>object</tt>, <tt>obj</tt>
104
+ <tt>Discriminator</tt>:: <tt>discriminator</tt>, <tt>disc</tt>
105
+ <tt>Binary</tt>:: <tt>binary</tt>, <tt>blob, b</tt>
99
106
 
100
107
  More coming soon!
101
108
 
@@ -103,7 +110,7 @@ More coming soon!
103
110
 
104
111
  This part belongs in the third section of the command for example:
105
112
 
106
- dmap new user id str:name:[required,accessor=private]
113
+ dmap new user id name:str:<b>required,accessor=private</b>
107
114
 
108
115
  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
116
 
@@ -112,11 +119,11 @@ Each validator is separated by a comma (<tt>,</tt>) and can have a value placed
112
119
 
113
120
  === Property Validator List
114
121
 
115
- [DataMapper's List]:: [DMap Command]
122
+ <b>DataMapper's List</b>:: <b>DMap Command</b>
116
123
  <tt>required</tt>:: <tt>required</tt>
117
124
  <tt>default</tt>:: <tt>default</tt>
118
125
  <tt>key</tt>:: <tt>key</tt>
119
- <tt>lazy</tt>:: <tt>lazy</tt> - Only accepts "false" for now
126
+ <tt>lazy</tt>:: <tt>lazy</tt>
120
127
  <tt>accessor</tt>:: <tt>accessor</tt>
121
128
  <tt>writer</tt>:: <tt>writer</tt>
122
129
  <tt>reader</tt>:: <tt>reader</tt>
@@ -127,27 +134,39 @@ That's all the ones I know for now, let me know if there are more!
127
134
 
128
135
  A list of all of the validates_*_of commands and which DMap currently supports
129
136
 
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
137
+ Note: DMap currently does not support :allow_nil parameters. This will change in the future.
138
+
139
+ <b>DataMapper's List</b>:: <b>DMap Command</b>
140
+ <tt>validates_absence_of</tt>:: <tt>absence, absent</tt>
141
+ <tt>validates_acceptance_of</tt>:: <tt>acceptance, accept</tt>
142
+ <tt>validates_with_block</tt>:: Unsupported at this time
134
143
  <tt>validates_confirmation_of</tt>:: <tt>confirmation, confirm</tt>
135
144
  <tt>validates_format_of</tt>:: <tt>format</tt>
136
145
  <tt>validates_length_of</tt>:: <tt>length_of</tt>
137
146
  <tt>validates_with_method</tt>:: <tt>withmethod, method</tt>
138
- <tt>validates_numericality_of</tt>:: <tt>Unsupported</tt>
147
+ <tt>validates_numericality_of</tt>:: Unsupported
139
148
  <tt>validates_primitive_type_of</tt>:: <tt>primitive</tt>
140
149
  <tt>validates_presence_of</tt>:: <tt>presence, present</tt>
141
150
  <tt>validates_uniqueness_of</tt>:: <tt>uniqueness</tt>
142
151
  <tt>validates_within</tt>:: <tt>within</tt>
143
152
 
153
+ == Associations
154
+
155
+ <b>DataMapper Command</b>:: <b>DMap Command</b>
156
+ <tt>has 1</tt>:: <tt>has1, hasone</tt>
157
+ <tt>has n</tt>:: <tt>hasn</tt>
158
+ <tt>belongs_to</tt>:: <tt>belongs_to, belongs</tt>
159
+ <tt>has_and_belongs_to_many</tt>:: <tt>hasmany</tt>
160
+
161
+ Note: use hasn when wanting to use :through => :model and hasmany for wanting to :through => Resource
162
+
163
+ Also, conditions are <b>not</b> supported through this generator (suggestions on this could be implemented would be helpful).
164
+
144
165
  == To Do
145
166
 
146
- * Add a verbose option
147
167
  * Add a way to add/edit/remove columns from pre-existing tables
148
- * Backup option before overwriting
149
168
  * All of the misc. property types
150
- * Better validation checkers
151
- * Associations! (this will be done first)
152
169
  * Template system similar to {Sinatra::Fedora's}[https://github.com/durango/sinatra_fedora] hatrack option
153
- * Better documentation!
170
+ * Better documentation!
171
+ * Migrations! (This will most likely be started after DM core team has finished the Veritas system).
172
+ * Conditions with associations?
data/bin/dmap CHANGED
@@ -14,6 +14,28 @@ opt_parser = OptionParser.new do |opt|
14
14
  opt.separator " new <model name> [options]: Creates a new model"
15
15
  opt.separator " e.g. dmap new User serial:id str:name:length=1..5,unique str:email text:signature"
16
16
  opt.separator ""
17
+
18
+ opt.on('-h', '--help', 'Displays this screen') do
19
+ puts opt
20
+ exit 1
21
+ end
22
+
23
+ opt.on('-v', '--verbose', 'Will print out the model(s) after changes have been made') do
24
+ DMap::Commands.options['verbose'] = true
25
+ end
26
+
27
+ opt.on('-b', '--backup', 'Backs up the old model from "model.rb" into "model.rb.bk"') do
28
+ DMap::Commands.options['backup'] = true
29
+ end
30
+
31
+ opt.on('-t', '--test', 'Displays what DMap would have made into a file onto the screen.') do
32
+ DMap::Commands.options['test'] = true
33
+ DMap::Commands.options['verbose'] = true
34
+ end
35
+
36
+ opt.on('-s', '--silent', 'If you entered incorrect values for a validation just suppress it and continue on.') do
37
+ DMap::Commands.options['silent'] = true
38
+ end
17
39
  end
18
40
 
19
41
  opt_parser.parse!
@@ -23,14 +45,14 @@ if ARGV[0].nil?
23
45
  exit 1
24
46
  end
25
47
 
26
- unless DMap::Commands.exists?(ARGV[0])
48
+ unless DMap::Commands.exists? ARGV[0]
27
49
  puts ARGV[0] + " is not a valid command."
28
50
  puts opt_parser
29
51
  exit 1
30
52
  end
31
53
 
32
54
  # safe guard table names
33
- table_names = ARGV[1].match /^\[*([a-zA-Z0-9,_]+)\]*$/
55
+ table_names = ARGV[1].to_s.match /^\[*([a-zA-Z0-9,_]+)\]*$/
34
56
  if table_names.nil?
35
57
  puts "Invalid table name, only characters A-Z, 0-9, and _ are allowed."
36
58
  puts opt_parser
@@ -45,7 +67,8 @@ table_names[1].split(',').each do |table|
45
67
  table.downcase!
46
68
 
47
69
  DMap::Tables.add model_name, model_name.underscore
48
- if File.file? "./#{table}.rb"
70
+ File.rename("./#{table}.rb", "./#{table}.rb.bk") if File.file? "./#{table}.rb" and DMap::Commands.options['backup'] == true
71
+ if File.file? "./#{table}.rb" and DMap::Commands.options['test'] != true
49
72
  puts "A model with the name of #{table} already exists."
50
73
  exit 1
51
74
  end
@@ -53,40 +76,42 @@ end
53
76
 
54
77
  ARGV[2..-1].each do |command|
55
78
  # TODO: Add a shortcut module/class
56
- command = "serial:id" if command == "id"
79
+ command = "id:serial" if command == "id"
57
80
 
58
81
  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"
82
+ keys[1] = '' if keys[1].class.name == "NilClass"
83
+
84
+ unless DMap::Fields.list.include? keys[1] or DMap::Properties.valid? keys[1].camelcase
85
+ puts keys[1] + " is not a valid property or field"
61
86
  puts opt_parser
62
87
  exit 1
63
88
  end
64
89
 
65
90
  # 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]])
91
+ if DMap::Fields.list.include?(keys[1])
92
+ keys.unshift(DMap::Fields.list[keys[1]])
68
93
  else
69
94
  # 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."
95
+ if DMap::Fields.list.include?(keys[0])
96
+ puts keys[0] + " is already a declared field. You cannot declare a field twice."
72
97
  puts opt_parser
73
98
  exit 1
74
99
  end
75
100
 
76
101
  # We really only need to do this when we're declaring a field with a type
77
102
  # Gets proper property name (e.g. "Dt" becomes "DateTime")
78
- property_class = DMap::Properties.const_get(keys[0].camelcase)
103
+ property_class = DMap::Properties.const_get(keys[1].camelcase)
79
104
  begin
80
- keys[0] = property_class.superclass.parent_name
105
+ keys[1] = property_class.superclass.parent_name
81
106
  rescue
82
- keys[0] = keys[0].camelcase
107
+ keys[1] = keys[1].camelcase
83
108
  end
84
109
 
85
110
  # 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'
111
+ keys[0].split(',').each do |key|
112
+ DMap::Fields.add key, keys[1]
113
+ DMap::Tables.list.each_value do |table|
114
+ DMap::Properties.add table, key, keys[1], 'type'
90
115
  end
91
116
  end
92
117
  end
@@ -96,52 +121,64 @@ ARGV[2..-1].each do |command|
96
121
  keys[2].split(',').each do |cmds|
97
122
  validation = cmds.split('=')
98
123
 
99
- # Let's check if it's a validates_*_of first
124
+ # Does the validation exist?
125
+ # Check if the validation belongs to the property or within it's own command
100
126
  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
127
+ validate = DMap::Validations.const_get validation[0].camelcase
128
+ rescue
129
+ validate = DMap::Associations.const_get validation[0].camelcase
130
+ rescue
131
+ puts "Invalid validation command " + validation[0].camelcase + " in type " + validate.class.name.to_s
126
132
  puts opt_parser
127
133
  exit 1
128
134
  end
129
135
 
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
136
+ # Do we need a default value?
137
+ begin
138
+ validation[1] ||= validate.default
139
+ rescue
140
+ end
133
141
 
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
142
+ # Store in variable for -s / silent option
143
+ valid_command = validate.method("is_valid?").call validation[1]
144
+ unless valid_command != true
145
+ if !validate.respond_to? "property"
146
+ # Compile all of the options for the validation
147
+ struct = validate.method("validate").call validation[1]
148
+
149
+ # Get the original name
150
+ begin
151
+ original_name = validate.superclass.parent_name.underscore
152
+ rescue
153
+ original_name = validation[0].underscore
154
+ end
155
+
156
+ # Finally, add the validations!
157
+ if struct.is_a?(Hash) or struct.is_a? Hash
158
+ struct.each do |key, value|
159
+ if validate.respond_to? "associations"
160
+ DMap::Associations.add keys[0], original_name, key, value unless value.nil? || key == :cmd
161
+ else
162
+ DMap::Validations.add keys[0], original_name, key, value unless value.nil? || key == :cmd
163
+ end
164
+ end
165
+ end
166
+ else
167
+ # Add the "core" validations (on properties)
168
+ struct = validate.method("validate").call validation[1]
169
+ DMap::Tables.list.each do |k, table|
170
+ validation[1] = true if validation[1].nil?
171
+ DMap::Properties.add table, keys[0], struct, validation[0]
172
+ end
173
+ end
139
174
  end
140
175
 
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]
176
+ if valid_command == false
177
+ puts validation[0] + " validation has an incorrect value for " + keys[0] + "."
178
+ if DMap::Commands.options['silent'] != true
179
+ puts opt_parser
180
+ exit 1
181
+ end
145
182
  end
146
183
  end
147
184
  end
@@ -152,21 +189,6 @@ end
152
189
  #p DMap::Tables.list
153
190
  #p DMap::Properties.list
154
191
  #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
192
+ #p DMap::Associations.list
193
+
194
+ DMap::Commands.method("cmd_" + ARGV[0]).call