default_value_for 2.0.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
metadata.gz.asc CHANGED
@@ -2,11 +2,7 @@
2
2
  Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
3
3
  Comment: GPGTools - http://gpgtools.org
4
4
 
5
- iQEcBAABAgAGBQJRnikCAAoJECrHRaUKISqMKUUIALD1qS846cCZWu67qXrkLy65
6
- yMS2APHvlz3EXfHUR2RAZ9HAagf5E+VR4XT+e4zJ51YrkH1vKLqIVyOf14FUbp3i
7
- 4a/34aZdKmmzy+4BO5qU/MqMeYd6e6kEWYy/YICYceGH3hrKZzO3gtsBfV9e7tzI
8
- VL/raxpG2XzLvHX5S/a1LCKcLRQQtrD3jp2BvUb1OcVzkxOWFCcfbLh/u1vC51i0
9
- V8IqRlBgJHPpKScyegVtCS1FSESjru5C3DgtqtYOyrshN4y+Fv6TuGfsMfnxt4XE
10
- HdUpPhEVtQQ52+MTWY11iQfLORLtvcQRk0NOO1ltoX1i3am2ZY9cIWDF2yqgQdU=
11
- =XHs9
5
+ iEYEABECAAYFAlLNhXUACgkQBqExCUtvQzJlagCfa5h4Zvo2ALI3QOtwFq3TE0QD
6
+ 1hMAnjL92O6u5fDrF2lXv/+sIZ02YvJT
7
+ =k8Of
12
8
  -----END PGP SIGNATURE-----
data/README.rdoc DELETED
@@ -1,510 +0,0 @@
1
- = Introduction
2
-
3
- The default_value_for plugin allows one to define default values for ActiveRecord
4
- models in a declarative manner. For example:
5
-
6
- class User < ActiveRecord::Base
7
- default_value_for :name, "(no name)"
8
- default_value_for :last_seen do
9
- Time.now
10
- end
11
- end
12
-
13
- u = User.new
14
- u.name # => "(no name)"
15
- u.last_seen # => Mon Sep 22 17:28:38 +0200 2008
16
-
17
- *Note*: critics might be interested in the "When (not) to use default_value_for?"
18
- section. Please read on.
19
-
20
-
21
- == Installation
22
-
23
- === Rails 3
24
-
25
- Add it to your Gemfile:
26
-
27
- gem "default_value_for"
28
-
29
- This gem is signed using PGP with the Phusion Software Signing key: http://www.phusion.nl/about/gpg. That key in turn is signed by the rubygems-openpgp Certificate Authority: http://www.rubygems-openpgp-ca.org/.
30
-
31
- You can verify the authenticity of the gem by following The Complete Guide to Verifying Gems with rubygems-openpgp: http://www.rubygems-openpgp-ca.org/blog/the-complete-guide-to-verifying-gems-with-rubygems-openpgp.html
32
-
33
- === Rails 2
34
-
35
- default_value_for no longer supports Rails 2! The last version that supported Rails
36
- 2 is version 1.0.7. Install that with:
37
-
38
- ./script/plugin install git://github.com/FooBarWidget/default_value_for.git -r release-1.0.7
39
-
40
-
41
- == The default_value_for method
42
-
43
- The +default_value_for+ method is available in all ActiveRecord model classes.
44
-
45
- The first argument is the name of the attribute for which a default value should
46
- be set. This may either be a Symbol or a String.
47
-
48
- The default value itself may either be passed as the second argument:
49
-
50
- default_value_for :age, 20
51
-
52
- ...or it may be passed as the return value of a block:
53
-
54
- default_value_for :age do
55
- if today_is_sunday?
56
- 20
57
- else
58
- 30
59
- end
60
- end
61
-
62
- If you pass a value argument, then the default value is static and never
63
- changes. However, if you pass a block, then the default value is retrieved by
64
- calling the block. This block is called not once, but every time a new record is
65
- instantiated and default values need to be filled in.
66
-
67
- The latter form is especially useful if your model has a UUID column. One can
68
- generate a new, random UUID for every newly instantiated record:
69
-
70
- class User < ActiveRecord::Base
71
- default_value_for :uuid do
72
- UuidGenerator.new.generate_uuid
73
- end
74
- end
75
-
76
- User.new.uuid # => "51d6d6846f1d1b5c9a...."
77
- User.new.uuid # => "ede292289e3484cb88...."
78
-
79
- Note that record is passed to the block as an argument, in case you need it for
80
- whatever reason:
81
-
82
- class User < ActiveRecord::Base
83
- default_value_for :uuid do |x|
84
- x # <--- a User object
85
- UuidGenerator.new.generate_uuid
86
- end
87
- end
88
-
89
- == default_value_for options
90
-
91
- * allows_nil (default: true) - Sets explicitly passed nil values if option is set to true.
92
-
93
- You can pass this options hash as 2nd parameter and have to pass the default value through the :value option in this case e.g.:
94
-
95
- default_value_for :age, :value => 20, :allows_nil => false
96
-
97
- You can still pass the default value through a block:
98
-
99
- default_value_for :uuid, :allows_nil => false do
100
- UuidGenerator.new.generate_uuid
101
- end
102
-
103
- == The default_values method
104
-
105
- As a shortcut, you can use +default_values+ to set multiple default values at once.
106
-
107
- default_values :age => 20,
108
- :uuid => lambda { UuidGenerator.new.generate_uuid }
109
-
110
- If you like to override default_value_for options for each attribute you can do so:
111
-
112
- default_values :age => { :value => 20 },
113
- :uuid => { :value => lambda { UuidGenerator.new.generate_uuid }, :allows_nil => false }
114
-
115
- The difference is purely aesthetic. If you have lots of default values which are constants or constructed with one-line blocks, +default_values+ may look nicer. If you have default values constructed by longer blocks, +default_value_for+ suit you better. Feel free to mix and match.
116
-
117
- As a side note, due to specifics of Ruby's parser, you cannot say,
118
-
119
- default_value_for :uuid { UuidGenerator.new.generate_uuid }
120
-
121
- because it will not parse. One needs to write
122
-
123
- default_value_for(:uuid) { UuidGenerator.new.generate_uuid }
124
-
125
- instead. This is in part the inspiration for the +default_values+ syntax.
126
-
127
- == Rules
128
-
129
- === Instantiation of new record
130
-
131
- Upon instantiating a new record, the declared default values are filled into
132
- the record. You've already seen this in the above examples.
133
-
134
- === Retrieval of existing record
135
-
136
- Upon retrieving an existing record in the following case, the declared default values are _not_
137
- filled into the record. Consider the example with the UUID:
138
-
139
- user = User.create
140
- user.uuid # => "529c91b8bbd3e..."
141
-
142
- user = User.find(user.id)
143
- # UUID remains unchanged because it's retrieved from the database!
144
- user.uuid # => "529c91b8bbd3e..."
145
-
146
- But when the declared default value is set to not allow nil and nil is passed the default values will be set on retrieval.
147
- Consider this example:
148
-
149
- default_value_for(:number, :allows_nil => false) { 123 }
150
-
151
- user = User.create
152
-
153
- # manual SQL by-passing active record and the default value for gem logic through ActiveRecord's after_initialize callback
154
- user.update_attribute(:number, nil)
155
-
156
- # declared default value should be set
157
- User.find(user.id).number # => 123 # = declared default value
158
-
159
- === Mass-assignment
160
-
161
- If a certain attribute is being assigned via the model constructor's
162
- mass-assignment argument, that the default value for that attribute will _not_
163
- be filled in:
164
-
165
- user = User.new(:uuid => "hello")
166
- user.uuid # => "hello"
167
-
168
- However, if that attribute is protected by +attr_protected+ or +attr_accessible+,
169
- then it will be filled in:
170
-
171
- class User < ActiveRecord::Base
172
- default_value_for :name, 'Joe'
173
- attr_protected :name
174
- end
175
-
176
- user = User.new(:name => "Jane")
177
- user.name # => "Joe"
178
-
179
- # the without protection option will work as expected
180
- user = User.new({:name => "Jane"}, :without_protection => true)
181
- user.name # => "Jane"
182
-
183
- Explicitly set nil values for accessible attributes will be accepted:
184
-
185
- class User < ActiveRecord::Base
186
- default_value_for :name, 'Joe'
187
- end
188
-
189
- user = User(:name => nil)
190
- user.name # => nil
191
-
192
- ... unless the accessible attribute is set to not allowing nil:
193
-
194
- class User < ActiveRecord::Base
195
- default_value_for :name, 'Joe', :allows_nil => false
196
- end
197
-
198
- user = User(:name => nil)
199
- user.name # => "Joe"
200
-
201
- === Inheritance
202
-
203
- Inheritance works as expected. All default values are inherited by the child
204
- class:
205
-
206
- class User < ActiveRecord::Base
207
- default_value_for :name, 'Joe'
208
- end
209
-
210
- class SuperUser < User
211
- end
212
-
213
- SuperUser.new.name # => "Joe"
214
-
215
- === Attributes that aren't database columns
216
-
217
- +default_value_for+ also works with attributes that aren't database columns.
218
- It works with anything for which there's an assignment method:
219
-
220
- # Suppose that your 'users' table only has a 'name' column.
221
- class User < ActiveRecord::Base
222
- default_value_for :name, 'Joe'
223
- default_value_for :age, 20
224
- default_value_for :registering, true
225
-
226
- attr_accessor :age
227
-
228
- def registering=(value)
229
- @registering = true
230
- end
231
- end
232
-
233
- user = User.new
234
- user.age # => 20
235
- user.instance_variable_get('@registering') # => true
236
-
237
- === Default values are duplicated
238
-
239
- The given default values are duplicated when they are filled in, so if
240
- you mutate a value that was filled in with a default value, then it will
241
- not affect all subsequent default values:
242
-
243
- class Author < ActiveRecord::Base
244
- # This model only has a 'name' attribute.
245
- end
246
-
247
- class Book < ActiveRecord::Base
248
- belongs_to :author
249
-
250
- # By default, a Book belongs to a new, unsaved author.
251
- default_value_for :author, Author.new
252
- end
253
-
254
- book1 = Book.new
255
- book1.author.name # => nil
256
- # This does not mutate the default value:
257
- book1.author.name = "John"
258
-
259
- book2 = Book.new
260
- book2.author.name # => nil
261
-
262
- However the duplication is shallow. If you modify any objects that are
263
- referenced by the default value then it will affect subsequent default values:
264
-
265
- class Author < ActiveRecord::Base
266
- attr_accessor :useless_hash
267
- default_value_for :useless_hash, { :foo => [] }
268
- end
269
-
270
- author1 = Author.new
271
- author1.useless_hash # => { :foo => [] }
272
- # This mutates the referred array:
273
- author1.useless_hash[:foo] << 1
274
-
275
- author2 = Author.new
276
- author2.useless_hash # => { :foo => [1] }
277
-
278
- You can prevent this from happening by passing a block to +default_value_for+,
279
- which returns a new object instance with fresh references every time:
280
-
281
- class Author < ActiveRecord::Base
282
- attr_accessor :useless_hash
283
- default_value_for :useless_hash do
284
- { :foo => [] }
285
- end
286
- end
287
-
288
- author1 = Author.new
289
- author1.useless_hash # => { :foo => [] }
290
- author1.useless_hash[:foo] << 1
291
-
292
- author2 = Author.new
293
- author2.useless_hash # => { :foo => [] }
294
-
295
- === Caveats
296
-
297
- A conflict can occur if your model class overrides the 'initialize' method,
298
- because this plugin overrides 'initialize' as well to do its job.
299
-
300
- class User < ActiveRecord::Base
301
- def initialize # <-- this constructor causes problems
302
- super(:name => 'Name cannot be changed in constructor')
303
- end
304
- end
305
-
306
- We recommend you to alias chain your initialize method in models where you use
307
- +default_value_for+:
308
-
309
- class User < ActiveRecord::Base
310
- default_value_for :age, 20
311
-
312
- def initialize_with_my_app
313
- initialize_without_my_app(:name => 'Name cannot be changed in constructor')
314
- end
315
-
316
- alias_method_chain :initialize, :my_app
317
- end
318
-
319
- Also, stick with the following rules:
320
- - There is no need to +alias_method_chain+ your initialize method in models that
321
- don't use +default_value_for+.
322
- - Make sure that +alias_method_chain+ is called *after* the last
323
- +default_value_for+ occurance.
324
-
325
- If your default value is accidentally similar to default_value_for's options hash wrap your default value like this:
326
-
327
- default_value_for :attribute_name, :value => { :value => 123, :other_value => 1234 }
328
-
329
- == When (not) to use default_value_for?
330
-
331
- You can also specify default values in the database schema. For example, you
332
- can specify a default value in a migration as follows:
333
-
334
- create_table :users do |t|
335
- t.string :username, :null => false, :default => 'default username'
336
- t.integer :age, :null => false, :default => 20
337
- end
338
-
339
- This has similar effects as passing the default value as the second argument to
340
- +default_value_for+:
341
-
342
- default_value_for(:username, 'default_username')
343
- default_value_for(:age, 20)
344
-
345
- Default values are filled in whether you use the schema defaults or the
346
- default_value_for defaults:
347
-
348
- user = User.new
349
- user.username # => 'default username'
350
- user.age # => 20
351
-
352
- It's recommended that you use this over +default_value_for+ whenever possible.
353
-
354
- However, it's not possible to specify a schema default for serialized columns.
355
- With +default_value_for+, you can:
356
-
357
- class User < ActiveRecord::Base
358
- serialize :color
359
- default_value_for :color, [255, 0, 0]
360
- end
361
-
362
- And if schema defaults don't provide the flexibility that you need, then
363
- +default_value_for+ is the perfect choice. For example, with +default_value_for+
364
- you could specify a per-environment default:
365
-
366
- class User < ActiveRecord::Base
367
- if Rails.env == "development"
368
- default_value_for :is_admin, true
369
- end
370
- end
371
-
372
- Or, as you've seen in an earlier example, you can use +default_value_for+ to
373
- generate a default random UUID:
374
-
375
- class User < ActiveRecord::Base
376
- default_value_for :uuid do
377
- UuidGenerator.new.generate_uuid
378
- end
379
- end
380
-
381
- Or you could use it to generate a timestamp that's relative to the time at which
382
- the record is instantiated:
383
-
384
- class User < ActiveRecord::Base
385
- default_value_for :account_expires_at do
386
- 3.years.from_now
387
- end
388
- end
389
-
390
- User.new.account_expires_at # => Mon Sep 22 18:43:42 +0200 2008
391
- sleep(2)
392
- User.new.account_expires_at # => Mon Sep 22 18:43:44 +0200 2008
393
-
394
- Finally, it's also possible to specify a default via an association:
395
-
396
- # Has columns: 'name' and 'default_price'
397
- class SuperMarket < ActiveRecord::Base
398
- has_many :products
399
- end
400
-
401
- # Has columns: 'name' and 'price'
402
- class Product < ActiveRecord::Base
403
- belongs_to :super_market
404
-
405
- default_value_for :price do |product|
406
- product.super_market.default_price
407
- end
408
- end
409
-
410
- super_market = SuperMarket.create(:name => 'Albert Zwijn', :default_price => 100)
411
- soap = super_market.products.create(:name => 'Soap')
412
- soap.price # => 100
413
-
414
- === What about before_validate/before_save?
415
-
416
- True, +before_validate+ and +before_save+ does what we want if we're only
417
- interested in filling in a default before saving. However, if one wants to be
418
- able to access the default value even before saving, then be prepared to write
419
- a lot of code. Suppose that we want to be able to access a new record's UUID,
420
- even before it's saved. We could end up with the following code:
421
-
422
- # In the controller
423
- def create
424
- @user = User.new(params[:user])
425
- @user.generate_uuid
426
- email_report_to_admin("#{@user.username} with UUID #{@user.uuid} created.")
427
- @user.save!
428
- end
429
-
430
- # Model
431
- class User < ActiveRecord::Base
432
- before_save :generate_uuid_if_necessary
433
-
434
- def generate_uuid
435
- self.uuid = ...
436
- end
437
-
438
- private
439
- def generate_uuid_if_necessary
440
- if uuid.blank?
441
- generate_uuid
442
- end
443
- end
444
- end
445
-
446
- The need to manually call +generate_uuid+ here is ugly, and one can easily forget
447
- to do that. Can we do better? Let's see:
448
-
449
- # Controller
450
- def create
451
- @user = User.new(params[:user])
452
- email_report_to_admin("#{@user.username} with UUID #{@user.uuid} created.")
453
- @user.save!
454
- end
455
-
456
- # Model
457
- class User < ActiveRecord::Base
458
- before_save :generate_uuid_if_necessary
459
-
460
- def uuid
461
- value = read_attribute('uuid')
462
- if !value
463
- value = generate_uuid
464
- write_attribute('uuid', value)
465
- end
466
- value
467
- end
468
-
469
- # We need to override this too, otherwise User.new.attributes won't return
470
- # a default UUID value. I've never tested with User.create() so maybe we
471
- # need to override even more things.
472
- def attributes
473
- uuid
474
- super
475
- end
476
-
477
- private
478
- def generate_uuid_if_necessary
479
- uuid # Reader method automatically generates UUID if it doesn't exist
480
- end
481
- end
482
-
483
- That's an awful lot of code. Using +default_value_for+ is easier, don't you think?
484
-
485
- === What about other plugins?
486
-
487
- I've only been able to find 2 similar plugins:
488
-
489
- - Default Value: http://agilewebdevelopment.com/plugins/default_value
490
- - ActiveRecord Defaults: http://agilewebdevelopment.com/plugins/activerecord_defaults
491
-
492
- 'Default Value' appears to be unmaintained; its SVN link is broken. This leaves
493
- only 'ActiveRecord Defaults'. However, it is semantically dubious, which leaves
494
- it wide open for corner cases. For example, it is not clearly specified what
495
- ActiveRecord Defaults will do when attributes are protected by +attr_protected+
496
- or +attr_accessible+. It is also not clearly specified what one is supposed to
497
- do if one needs a custom +initialize+ method in the model.
498
-
499
- I've taken my time to thoroughly document default_value_for's behavior.
500
-
501
-
502
- == Credits
503
-
504
- I've wanted such functionality for a while now and it baffled me that ActiveRecord
505
- doesn't provide a clean way for me to specify default values. After reading
506
- http://groups.google.com/group/rubyonrails-core/browse_thread/thread/b509a2fe2b62ac5/3e8243fa1954a935,
507
- it became clear that someone needs to write a plugin. This is the result.
508
-
509
- Thanks to Pratik Naik for providing the initial code snippet on which this plugin
510
- is based on: http://m.onkey.org/2007/7/24/how-to-set-default-values-in-your-model