hobofields 0.8.5 → 0.8.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,41 +1,61 @@
1
- # HoboFields API
2
1
 
3
- ## Connect to the Database
2
+ # HoboFields API
4
3
 
5
4
  In order for the API examples to run we need a connection to a database. You can ignore this if you're just looking for documentation.
5
+ {.hidden}
6
+
7
+ Our test requires rails:
8
+ {.hidden}
6
9
 
7
10
  >> require 'rubygems'
8
11
  >> require 'activesupport'
9
- >> Dependencies.load_paths << '.'
10
- >> Dependencies.mechanism = :require
11
12
  >> require 'activerecord'
12
13
  >> require 'action_controller'
13
- >> require 'hobofields'
14
+ {.hidden}
15
+
16
+ We need a database connection for this test:
17
+ {.hidden}
18
+
14
19
  >> mysql_database = "hobofields_doctest"
20
+ >> system "mysqladmin --force drop #{mysql_database} 2> /dev/null"
15
21
  >> system("mysqladmin create #{mysql_database}") or raise "could not create database"
16
22
  >> ActiveRecord::Base.establish_connection(:adapter => "mysql",
17
23
  :database => mysql_database,
18
24
  :host => "localhost")
25
+ {.hidden}
26
+
27
+ Some load path manipulation you shouldn't need:
28
+ {.hidden}
29
+
30
+ >> $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), '../../hobofields/lib')
31
+ >> $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), '../../hobosupport/lib')
32
+ {.hidden}
33
+
34
+ Require the module we're testing:
35
+ {.hidden}
36
+
37
+ >> require 'hobosupport'
38
+ >> require 'hobofields'
19
39
 
20
40
  ## Example Models
21
41
 
22
42
  Let's define some example models that we can use to demonstrate the API. With HoboFields we define the model's fields, with their name and type, directly in the model like so:
23
43
 
24
- >>
25
- class Advert < ActiveRecord::Base
26
- fields do
27
- title :string
28
- body :text
29
- contact_address :email_address
30
- end
31
- end
44
+ >>
45
+ class Advert < ActiveRecord::Base
46
+ fields do
47
+ title :string
48
+ body :text
49
+ contact_address :email_address
50
+ end
51
+ end
32
52
 
33
53
  (Note: `:email_address` is an example of a "Rich Type" provided by HoboFields -- more on those later)
34
54
 
35
55
  The migration generator uses this information to create a migration. The following creates and runs the migration so we're ready to go.
36
56
 
37
- >> up, down = HoboFields::MigrationGenerator.run
38
- >> ActiveRecord::Migration.class_eval up
57
+ >> up, down = HoboFields::MigrationGenerator.run
58
+ >> ActiveRecord::Migration.class_eval up
39
59
 
40
60
  We're now ready to start demonstrating the API
41
61
 
@@ -47,23 +67,23 @@ The main feature of HoboFields, aside from the migration generator, is the abili
47
67
 
48
68
  Field values are returned as the type you specify.
49
69
 
50
- >> a = Advert.new :body => "This is the body"
51
- >> a.body.class
52
- => HoboFields::Text
70
+ >> a = Advert.new :body => "This is the body"
71
+ >> a.body.class
72
+ => HoboFields::Text
53
73
 
54
74
  This also works after a round-trip to the database
55
75
 
56
- >> a.save
57
- >> b = Advert.find(a.id)
58
- >> b.body.class
59
- => HoboFields::Text
76
+ >> a.save
77
+ >> b = Advert.find(a.id)
78
+ >> b.body.class
79
+ => HoboFields::Text
60
80
 
61
81
  HoboFields::Text is a simple subclass of string. It's a "wrapper type", by which we mean you pass the underlying value to the constructor.
62
82
 
63
- >> t = HoboFields::Text.new("hello")
64
- => "hello"
65
- >> t.class
66
- => HoboFields::Text
83
+ >> t = HoboFields::Text.new("hello")
84
+ => "hello"
85
+ >> t.class
86
+ => HoboFields::Text
67
87
 
68
88
  If you define your own rich types, they need to support a one argument constructor in the same way.
69
89
 
@@ -74,21 +94,20 @@ Although the body of our advert is really just a string, it's very useful that i
74
94
 
75
95
  In the `fields do ... end` block you can give the field-type either as a name (symbol) or a class. For example, we could have said
76
96
 
77
- body HoboFields::Text
97
+ body HoboFields::Text
78
98
 
79
99
  Obviously the symbol form is a nicer:
80
100
 
81
- body :text
101
+ body :text
82
102
 
83
103
  If you provide a class it must define the `COLUMN_TYPE` constant. This instructs the migration generator to create the appropriate underlying database column type. It should be a symbol that is a valid column type in a Rails migration.
84
104
 
85
- >> HoboFields::Text::COLUMN_TYPE
86
- => :text
105
+ >> HoboFields::Text::COLUMN_TYPE
106
+ => :text
87
107
 
88
108
  The full set of available symbolic names is
89
109
 
90
110
  * `:integer`
91
- * `:big_integer`
92
111
  * `:float`
93
112
  * `:string`
94
113
  * `:text`
@@ -99,7 +118,7 @@ The full set of available symbolic names is
99
118
  * `:textile`
100
119
  * `:markdown`
101
120
  * `:password`
102
- * `:email_addresss`
121
+ * `:email_address`
103
122
 
104
123
  You can add your own types too. More on that later.
105
124
 
@@ -112,33 +131,33 @@ HoboFields adds a few features to your models.
112
131
 
113
132
  Returns the type (i.e. class) declared for a given field or attribute
114
133
 
115
- >> Advert.attr_type :title
116
- => String
117
- >> Advert.attr_type :body
118
- => HoboFields::Text
134
+ >> Advert.attr_type :title
135
+ => String
136
+ >> Advert.attr_type :body
137
+ => HoboFields::Text
119
138
 
120
139
  ### `Model.column`
121
140
 
122
141
  A shorthand for accessing column metadata
123
142
 
124
- >> col = Advert.column :title
125
- >> col.name
126
- "title"
127
- >> col.klass
128
- >> String
143
+ >> col = Advert.column :title
144
+ >> col.name
145
+ => "title"
146
+ >> col.klass
147
+ >> String
129
148
 
130
149
  ### `Model.attr_accessor` with types
131
150
 
132
151
  In your HoboFields models you can also give type information to "virtual fields" (i.e. regular Ruby attributes)
133
152
 
134
- >>
135
- class Advert
136
- attr_accessor :my_attr, :type => :text
137
- end
138
- >> a = Advert.new
139
- >> a.my_attr = "hello"
140
- >> a.my_attr.class
141
- => HoboFields::Text
153
+ >>
154
+ class Advert
155
+ attr_accessor :my_attr, :type => :text
156
+ end
157
+ >> a = Advert.new
158
+ >> a.my_attr = "hello"
159
+ >> a.my_attr.class
160
+ => HoboFields::Text
142
161
 
143
162
 
144
163
  ## Field validations
@@ -149,73 +168,73 @@ HoboFields gives you some shorthands for declaring some common validations right
149
168
 
150
169
  The `:required` argument to a field gives a `validates_presence_of`:
151
170
 
152
- >>
153
- class Advert
154
- fields do
155
- title :string, :required
156
- end
157
- end
158
- >> a = Advert.new
159
- >> a.valid?
160
- => false
161
- >> a.errors.full_messages
162
- => ["Title can't be blank"]
163
- >> a.title = "Jimbo"
164
- >> a.save
165
- => true
171
+ >>
172
+ class Advert
173
+ fields do
174
+ title :string, :required
175
+ end
176
+ end
177
+ >> a = Advert.new
178
+ >> a.valid?
179
+ => false
180
+ >> a.errors.full_messages
181
+ => ["Title can't be blank"]
182
+ >> a.title = "Jimbo"
183
+ >> a.save
184
+ => true
166
185
 
167
186
 
168
187
  ### Unique fields
169
188
 
170
189
  The `:unique` argument in a field declaration gives `validates_uniqueness_of`:
171
190
 
172
- >>
173
- class Advert < ActiveRecord::Base
174
- fields do
175
- title :string, :unique
176
- end
177
- end
178
- >> a = Advert.new :title => "Jimbo"
179
- >> a.valid?
180
- => false
181
- >> a.errors.full_messages
182
- => ["Title has already been taken"]
183
- >> a.title = "Sambo"
184
- >> a.save
185
- => true
191
+ >>
192
+ class Advert < ActiveRecord::Base
193
+ fields do
194
+ title :string, :unique
195
+ end
196
+ end
197
+ >> a = Advert.new :title => "Jimbo"
198
+ >> a.valid?
199
+ => false
200
+ >> a.errors.full_messages
201
+ => ["Title has already been taken"]
202
+ >> a.title = "Sambo"
203
+ >> a.save
204
+ => true
186
205
 
187
206
  Let's get back to the basic Advert class with no validations before we continue:
188
207
 
189
- >> Dependencies.remove_constant "Advert"
190
- >>
191
- class Advert < ActiveRecord::Base
192
- fields do
193
- title :string
194
- body :text
195
- contact_address :email_address
196
- end
197
- end
208
+ >> ActiveSupport::Dependencies.remove_constant "Advert"
209
+ >>
210
+ class Advert < ActiveRecord::Base
211
+ fields do
212
+ title :string
213
+ body :text
214
+ contact_address :email_address
215
+ end
216
+ end
198
217
 
199
218
 
200
219
  ### Type specific validations
201
220
 
202
221
  Rich types can define there own validations by a `#validate` method. It should return an error message if the value is invalid, otherwise nil. We can call that method directly to show how it works:
203
222
 
204
- >> a = Advert.new :contact_address => "not really an email address"
205
- >> a.contact_address.class
206
- => HoboFields::EmailAddress
207
- >> a.contact_address.validate
208
- => "is not valid"
223
+ >> a = Advert.new :contact_address => "not really an email address"
224
+ >> a.contact_address.class
225
+ => HoboFields::EmailAddress
226
+ >> a.contact_address.validate
227
+ => "is not valid"
209
228
 
210
229
  But normally that method would be called for us during validation:
211
230
 
212
- >> a.valid?
213
- => false
214
- >> a.errors.full_messages
215
- => ["Contact address is not valid"]
216
- >> a.contact_address = "me@me.com"
217
- >> a.valid?
218
- => true
231
+ >> a.valid?
232
+ => false
233
+ >> a.errors.full_messages
234
+ => ["Contact address is not valid"]
235
+ >> a.contact_address = "me@me.com"
236
+ >> a.valid?
237
+ => true
219
238
 
220
239
  You can add this capability to your own rich types just by defining `#validate`
221
240
 
@@ -223,26 +242,28 @@ You can add this capability to your own rich types just by defining `#validate`
223
242
 
224
243
  You can set the type of a virtual field to a rich type, e.g.
225
244
 
226
- >>
227
- class Advert
228
- attr_accessor :alternative_email, :type => :email_address
229
- end
245
+ >>
246
+ class Advert
247
+ attr_accessor :alternative_email, :type => :email_address
248
+ end
230
249
 
231
250
  By default, virtual fields are not subject to validation.
232
251
 
233
- >> a = Advert.new :alternative_email => "woot!"
234
- >> a.valid?
235
- => true
252
+ >> a = Advert.new :alternative_email => "woot!"
253
+ >> a.valid?
254
+ => true
236
255
 
237
256
  To have them validated use `validate_virtual_field`:
238
257
 
239
- >>
240
- class Advert
241
- validate_virtual_field :alternative_email
242
- end
243
- >> a.valid?
244
- => false
258
+ >>
259
+ class Advert
260
+ validate_virtual_field :alternative_email
261
+ end
262
+ >> a.valid?
263
+ => false
245
264
 
246
- ## Cleanup
265
+ Cleanup
266
+ {.hidden}
247
267
 
248
- >> system "mysqladmin --force drop #{mysql_database}"
268
+ >> system "mysqladmin --force drop #{mysql_database} 2> /dev/null"
269
+ {.hidden}