default_value_for 1.0.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -20,21 +20,18 @@ section. Please read on.
20
20
 
21
21
  == Installation
22
22
 
23
- === Rails 2
24
-
25
- Install with:
26
-
27
- ./script/plugin install git://github.com/FooBarWidget/default_value_for.git
28
-
29
23
  === Rails 3
30
24
 
31
- You can either install it as a plugin:
25
+ Add it to your Gemfile:
32
26
 
33
- rails plugin install git://github.com/FooBarWidget/default_value_for.git
27
+ gem "default_value_for"
34
28
 
35
- or install it by adding it to your Gemfile:
29
+ === Rails 2
36
30
 
37
- gem "default_value_for"
31
+ default_value_for no longer supports Rails 2! The last version that supported Rails
32
+ 2 is version 1.0.7. Install that with:
33
+
34
+ ./script/plugin install git://github.com/FooBarWidget/default_value_for.git -r release-1.0.7
38
35
 
39
36
 
40
37
  == The default_value_for method
@@ -84,6 +81,20 @@ whatever reason:
84
81
  UuidGenerator.new.generate_uuid
85
82
  end
86
83
  end
84
+
85
+ == default_value_for options
86
+
87
+ * allows_nil (default: true) - Sets explicitly passed nil values if option is set to true.
88
+
89
+ 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.:
90
+
91
+ default_value_for :age, :value => 20, :allows_nil => false
92
+
93
+ You can still pass the default value through a block:
94
+
95
+ default_value_for :uuid, :allows_nil => false do
96
+ UuidGenerator.new.generate_uuid
97
+ end
87
98
 
88
99
  == The default_values method
89
100
 
@@ -92,6 +103,11 @@ As a shortcut, you can use +default_values+ to set multiple default values at on
92
103
  default_values :age => 20,
93
104
  :uuid => lambda { UuidGenerator.new.generate_uuid }
94
105
 
106
+ If you like to override default_value_for options for each attribute you can do so:
107
+
108
+ default_values :age => { :value => 20 },
109
+ :uuid => { :value => lambda { UuidGenerator.new.generate_uuid }, :allows_nil => false }
110
+
95
111
  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.
96
112
 
97
113
  As a side note, due to specifics of Ruby's parser, you cannot say,
@@ -103,7 +119,7 @@ because it will not parse. One needs to write
103
119
  default_value_for(:uuid) { UuidGenerator.new.generate_uuid }
104
120
 
105
121
  instead. This is in part the inspiration for the +default_values+ syntax.
106
-
122
+
107
123
  == Rules
108
124
 
109
125
  === Instantiation of new record
@@ -113,7 +129,7 @@ the record. You've already seen this in the above examples.
113
129
 
114
130
  === Retrieval of existing record
115
131
 
116
- Upon retrieving an existing record, the declared default values are _not_
132
+ Upon retrieving an existing record in the following case, the declared default values are _not_
117
133
  filled into the record. Consider the example with the UUID:
118
134
 
119
135
  user = User.create
@@ -123,6 +139,19 @@ filled into the record. Consider the example with the UUID:
123
139
  # UUID remains unchanged because it's retrieved from the database!
124
140
  user.uuid # => "529c91b8bbd3e..."
125
141
 
142
+ But when the declared default value is set to not allow nil and nil is passed the default values will be set on retrieval.
143
+ Consider this example:
144
+
145
+ default_value_for(:number, :allows_nil => false) { 123 }
146
+
147
+ user = User.create
148
+
149
+ # manual SQL by-passing active record and the default value for gem logic through ActiveRecord's after_initialize callback
150
+ user.update_attribute(:number, nil)
151
+
152
+ # declared default value should be set
153
+ User.find(user.id).number # => 123 # = declared default value
154
+
126
155
  === Mass-assignment
127
156
 
128
157
  If a certain attribute is being assigned via the model constructor's
@@ -142,6 +171,28 @@ then it will be filled in:
142
171
 
143
172
  user = User.new(:name => "Jane")
144
173
  user.name # => "Joe"
174
+
175
+ # the without protection option will work as expected
176
+ user = User.new({:name => "Jane"}, :without_protection => true)
177
+ user.name # => "Jane"
178
+
179
+ Explicitly set nil values for accessible attributes will be accepted:
180
+
181
+ class User < ActiveRecord::Base
182
+ default_value_for :name, 'Joe'
183
+ end
184
+
185
+ user = User(:name => nil)
186
+ user.name # => nil
187
+
188
+ ... unless the accessible attribute is set to not allowing nil:
189
+
190
+ class User < ActiveRecord::Base
191
+ default_value_for :name, 'Joe', :allows_nil => false
192
+ end
193
+
194
+ user = User(:name => nil)
195
+ user.name # => "Joe"
145
196
 
146
197
  === Inheritance
147
198
 
@@ -267,6 +318,9 @@ Also, stick with the following rules:
267
318
  - Make sure that +alias_method_chain+ is called *after* the last
268
319
  +default_value_for+ occurance.
269
320
 
321
+ If your default value is accidentally similar to default_value_for's options hash wrap your default value like this:
322
+
323
+ default_value_for :attribute_name, :value => { :value => 123, :other_value => 1234 }
270
324
 
271
325
  == When (not) to use default_value_for?
272
326
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{default_value_for}
3
- s.version = "1.0.7"
3
+ s.version = "2.0.0"
4
4
  s.summary = %q{Provides a way to specify default values for ActiveRecord models}
5
5
  s.description = %q{The default_value_for plugin allows one to define default values for ActiveRecord models in a declarative manner}
6
6
  s.email = %q{info@phusion.nl}
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2008, 2009, 2010, 2011 Phusion
1
+ # Copyright (c) 2008-2012 Phusion
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the "Software"), to deal
@@ -19,104 +19,144 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module DefaultValueFor
22
- class NormalValueContainer
23
- def initialize(value)
24
- @value = value
25
- end
22
+ class NormalValueContainer
23
+ def initialize(value)
24
+ @value = value
25
+ end
26
26
 
27
- def evaluate(instance)
28
- if @value.duplicable?
29
- return @value.dup
30
- else
31
- return @value
32
- end
33
- end
34
- end
27
+ def evaluate(instance)
28
+ if @value.duplicable?
29
+ return @value.dup
30
+ else
31
+ return @value
32
+ end
33
+ end
34
+ end
35
35
 
36
- class BlockValueContainer
37
- def initialize(block)
38
- @block = block
39
- end
36
+ class BlockValueContainer
37
+ def initialize(block)
38
+ @block = block
39
+ end
40
40
 
41
- def evaluate(instance)
42
- if @block.arity == 0
43
- return @block.call
44
- else
45
- return @block.call(instance)
46
- end
47
- end
48
- end
41
+ def evaluate(instance)
42
+ if @block.arity == 0
43
+ return @block.call
44
+ else
45
+ return @block.call(instance)
46
+ end
47
+ end
48
+ end
49
49
 
50
- module ClassMethods
51
- def default_value_for(attribute, value = nil, &block)
52
- if !method_defined?(:initialize_with_defaults)
53
- include(InstanceMethods)
54
- alias_method_chain :initialize, :defaults
55
- if respond_to?(:class_attribute)
56
- class_attribute :_default_attribute_values
57
- else
58
- class_inheritable_accessor :_default_attribute_values
59
- end
60
- extend(DelayedClassMethods)
61
- init_hash = true
62
- end
63
- if init_hash || !singleton_methods(false).to_s.include?("_default_attribute_values")
64
- self._default_attribute_values = ActiveSupport::OrderedHash.new
65
- end
66
- if block_given?
67
- container = BlockValueContainer.new(block)
68
- else
69
- container = NormalValueContainer.new(value)
70
- end
71
- _default_attribute_values[attribute.to_s] = container
72
- end
50
+ module ClassMethods
51
+ # Declares a default value for the given attribute.
52
+ #
53
+ # Sets the default value to the given options parameter unless the given options equal { :value => ... }
54
+ #
55
+ # The <tt>options</tt> can be used to specify the following things:
56
+ # * <tt>value</tt> - Sets the default value.
57
+ # * <tt>allows_nil (default: true)</tt> - Sets explicitly passed nil values if option is set to true.
58
+ def default_value_for(attribute, options = {}, &block)
59
+ value = options.is_a?(Hash) && options.stringify_keys.has_key?('value') ? options.stringify_keys['value'] : options
60
+ allows_nil = options.is_a?(Hash) && options.stringify_keys.has_key?('allows_nil') ? options.stringify_keys['allows_nil'] : true
61
+
62
+ if !method_defined?(:set_default_values)
63
+ include(InstanceMethods)
73
64
 
74
- def default_values(values)
75
- values.each_pair do |key, value|
76
- if value.kind_of? Proc
77
- default_value_for(key, &value)
78
- else
79
- default_value_for(key, value)
80
- end
81
- end
82
- end
83
- end
65
+ after_initialize :set_default_values
66
+
67
+ if respond_to?(:class_attribute)
68
+ class_attribute :_default_attribute_values
69
+ class_attribute :_default_attribute_values_not_allowing_nil
70
+ else
71
+ class_inheritable_accessor :_default_attribute_values
72
+ class_inheritable_accessor :_default_attribute_values_not_allowing_nil
73
+ end
74
+
75
+ extend(DelayedClassMethods)
76
+ init_hash = true
77
+ end
78
+ if init_hash || !singleton_methods(false).to_s.include?("_default_attribute_values")
79
+ self._default_attribute_values = ActiveSupport::OrderedHash.new
80
+ self._default_attribute_values_not_allowing_nil = []
81
+ end
82
+ if block_given?
83
+ container = BlockValueContainer.new(block)
84
+ else
85
+ container = NormalValueContainer.new(value)
86
+ end
87
+ _default_attribute_values[attribute.to_s] = container
88
+ _default_attribute_values_not_allowing_nil << attribute.to_s unless allows_nil
89
+ end
84
90
 
85
- module DelayedClassMethods
86
- def _all_default_attribute_values
87
- return _default_attribute_values unless superclass.respond_to?(:_default_attribute_values)
88
- superclass._all_default_attribute_values.merge(_default_attribute_values)
89
- end
90
- end
91
+ def default_values(values)
92
+ values.each_pair do |key, options|
93
+ options = options.stringify_keys if options.is_a?(Hash)
94
+
95
+ value = options.is_a?(Hash) && options.has_key?('value') ? options['value'] : options
96
+
97
+ if value.kind_of? Proc
98
+ default_value_for(key, options.is_a?(Hash) ? options : {}, &value)
99
+ else
100
+ default_value_for(key, options)
101
+ end
102
+ end
103
+ end
104
+ end
91
105
 
92
- module InstanceMethods
93
- def initialize_with_defaults(attrs = nil, *args, &block)
94
- initialize_without_defaults(attrs, *args, &block)
95
- if attrs
96
- stringified_attrs = attrs.stringify_keys
97
- safe_attrs = if respond_to? :sanitize_for_mass_assignment
98
- sanitize_for_mass_assignment(stringified_attrs)
99
- else
100
- remove_attributes_protected_from_mass_assignment(stringified_attrs)
101
- end
102
- safe_attribute_names = safe_attrs.keys.map do |x|
103
- x.to_s
104
- end
105
- end
106
- self.class._all_default_attribute_values.each do |attribute, container|
107
- if safe_attribute_names.nil? || !safe_attribute_names.any? { |attr_name| attr_name =~ /^#{attribute}($|\()/ }
108
- __send__("#{attribute}=", container.evaluate(self))
109
- changed_attributes.delete(attribute)
110
- end
111
- end
112
- yield(self) if block_given?
113
- end
114
- end
106
+ module DelayedClassMethods
107
+ def _all_default_attribute_values
108
+ return _default_attribute_values unless superclass.respond_to?(:_default_attribute_values)
109
+ superclass._all_default_attribute_values.merge(_default_attribute_values)
110
+ end
111
+
112
+ def _all_default_attribute_values_not_allowing_nil
113
+ return _default_attribute_values_not_allowing_nil unless superclass.respond_to?(:_default_attribute_values_not_allowing_nil)
114
+ superclass._all_default_attribute_values_not_allowing_nil.merge(_default_attribute_values_not_allowing_nil)
115
+ end
116
+ end
117
+
118
+ module InstanceMethods
119
+ def initialize(attributes = nil, options = {})
120
+ @initialization_attributes = attributes.is_a?(Hash) ? attributes.stringify_keys : {}
121
+
122
+ unless options[:without_protection]
123
+ if respond_to?(:mass_assignment_options) && options.has_key?(:as)
124
+ @initialization_attributes = sanitize_for_mass_assignment(@initialization_attributes, options[:as])
125
+ elsif respond_to?(:sanitize_for_mass_assignment)
126
+ @initialization_attributes = sanitize_for_mass_assignment(@initialization_attributes)
127
+ else
128
+ @initialization_attributes = remove_attributes_protected_from_mass_assignment(@initialization_attributes)
129
+ end
130
+ end
131
+
132
+ if ActiveRecord::VERSION::MAJOR > 3 || (ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR > 0)
133
+ super(attributes, options)
134
+ else
135
+ super(attributes)
136
+ end
137
+ end
138
+
139
+ def set_default_values
140
+ self.class._all_default_attribute_values.each do |attribute, container|
141
+ next unless self.new_record? || self.class._all_default_attribute_values_not_allowing_nil.include?(attribute)
142
+
143
+ connection_default_value_defined = new_record? && respond_to?("#{attribute}_changed?") && !__send__("#{attribute}_changed?")
144
+
145
+ next unless connection_default_value_defined || self.attributes[attribute].blank?
146
+
147
+ # allow explicitly setting nil through allow nil option
148
+ next if @initialization_attributes.is_a?(Hash) && @initialization_attributes.has_key?(attribute) && !self.class._all_default_attribute_values_not_allowing_nil.include?(attribute)
149
+
150
+ __send__("#{attribute}=", container.evaluate(self))
151
+ changed_attributes.delete(attribute)
152
+ end
153
+ end
154
+ end
115
155
  end
116
156
 
117
157
  if defined?(Rails::Railtie)
118
- require 'default_value_for/railtie'
158
+ require 'default_value_for/railtie'
119
159
  else
120
- # Rails 2 initialization
121
- ActiveRecord::Base.extend(DefaultValueFor::ClassMethods)
160
+ # Rails 2 initialization
161
+ ActiveRecord::Base.extend(DefaultValueFor::ClassMethods)
122
162
  end
data/test.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2008, 2009 Phusion
1
+ # Copyright (c) 2008-2012 Phusion
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the "Software"), to deal
@@ -18,13 +18,13 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
- want_rails_version = '~> 3.1.0'
21
+ want_rails_version = '~> ' + ENV.fetch('WANT_RAILS_VERSION', '3.2.0')
22
22
 
23
23
  require 'rubygems'
24
24
  gem 'rails', want_rails_version
25
25
  gem 'activerecord', want_rails_version
26
26
  begin
27
- require 'rails/railtie'
27
+ require 'rails/railtie'
28
28
  rescue LoadError
29
29
  end
30
30
  require 'active_record'
@@ -36,335 +36,392 @@ require 'default_value_for'
36
36
  Dir.chdir(File.dirname(__FILE__))
37
37
 
38
38
  if RUBY_PLATFORM == "java"
39
- database_adapter = "jdbcsqlite3"
39
+ database_adapter = "jdbcsqlite3"
40
40
  else
41
- database_adapter = "sqlite3"
41
+ database_adapter = "sqlite3"
42
42
  end
43
43
 
44
44
  File.unlink('test.sqlite3') rescue nil
45
45
  ActiveRecord::Base.logger = Logger.new(STDERR)
46
46
  ActiveRecord::Base.logger.level = Logger::WARN
47
47
  ActiveRecord::Base.establish_connection(
48
- :adapter => database_adapter,
49
- :database => 'test.sqlite3'
48
+ :adapter => database_adapter,
49
+ :database => 'test.sqlite3'
50
50
  )
51
51
  ActiveRecord::Base.connection.create_table(:users, :force => true) do |t|
52
- t.string :username
53
- t.integer :default_number
52
+ t.string :username
53
+ t.integer :default_number
54
54
  end
55
55
  ActiveRecord::Base.connection.create_table(:numbers, :force => true) do |t|
56
- t.string :type
57
- t.integer :number
58
- t.integer :count, :null => false, :default => 1
59
- t.integer :user_id
60
- t.timestamp :timestamp
56
+ t.string :type
57
+ t.integer :number
58
+ t.integer :count, :null => false, :default => 1
59
+ t.integer :user_id
60
+ t.timestamp :timestamp
61
61
  end
62
62
 
63
63
  if defined?(Rails::Railtie)
64
- DefaultValueFor.initialize_railtie
65
- DefaultValueFor.initialize_active_record_extensions
64
+ DefaultValueFor.initialize_railtie
65
+ DefaultValueFor.initialize_active_record_extensions
66
66
  end
67
67
 
68
68
  class User < ActiveRecord::Base
69
- has_many :numbers, :class_name => 'TestClass'
69
+ has_many :numbers, :class_name => 'TestClass'
70
70
  end
71
71
 
72
72
  class Number < ActiveRecord::Base
73
73
  end
74
74
 
75
75
  class DefaultValuePluginTest < Test::Unit::TestCase
76
- def setup
77
- Number.create(:number => 9876)
78
- end
79
-
80
- def teardown
81
- Number.delete_all
82
- end
83
-
84
- def define_model_class(name = "TestClass", parent_class_name = "ActiveRecord::Base", &block)
85
- Object.send(:remove_const, name) rescue nil
86
- eval("class #{name} < #{parent_class_name}; end", TOPLEVEL_BINDING)
87
- klass = eval(name, TOPLEVEL_BINDING)
88
- klass.class_eval do
89
- set_table_name 'numbers'
90
- end
91
- klass.class_eval(&block) if block_given?
92
- end
93
-
94
- def test_default_value_can_be_passed_as_argument
95
- define_model_class do
96
- default_value_for(:number, 1234)
97
- end
98
- object = TestClass.new
99
- assert_equal 1234, object.number
100
- end
101
-
102
- def test_default_value_can_be_passed_as_block
103
- define_model_class do
104
- default_value_for(:number) { 1234 }
105
- end
106
- object = TestClass.new
107
- assert_equal 1234, object.number
108
- end
109
-
110
- def test_works_with_create
111
- define_model_class do
112
- default_value_for :number, 1234
113
- end
114
- TestClass.create
115
- assert_not_nil TestClass.find_by_number(1234)
116
- end
117
-
118
- def test_overwrites_db_default
119
- define_model_class do
120
- default_value_for :count, 1234
121
- end
122
- object = TestClass.new
123
- assert_equal 1234, object.count
124
- end
125
-
126
- def test_doesnt_overwrite_values_provided_by_mass_assignment
127
- define_model_class do
128
- default_value_for :number, 1234
129
- end
130
- object = TestClass.new(:number => 1, :count => 2)
131
- assert_equal 1, object.number
132
- end
133
-
134
- def test_doesnt_overwrite_values_provided_by_multiparameter_assignment
135
- define_model_class do
136
- default_value_for :timestamp, Time.mktime(2000, 1, 1)
137
- end
138
- timestamp = Time.mktime(2009, 1, 1)
139
- object = TestClass.new('timestamp(1i)' => '2009', 'timestamp(2i)' => '1', 'timestamp(3i)' => '1')
140
- assert_equal timestamp, object.timestamp
141
- end
142
-
143
- def test_doesnt_overwrite_values_provided_by_constructor_block
144
- define_model_class do
145
- default_value_for :number, 1234
146
- end
147
- object = TestClass.new do |x|
148
- x.number = 1
149
- x.count = 2
150
- end
151
- assert_equal 1, object.number
152
- end
153
-
154
- def test_doesnt_overwrite_explicitly_provided_nil_values_in_mass_assignment
155
- define_model_class do
156
- default_value_for :number, 1234
157
- end
158
- object = TestClass.new(:number => nil)
159
- assert_nil object.number
160
- end
161
-
162
- def test_default_values_are_inherited
163
- define_model_class("TestSuperClass") do
164
- default_value_for :number, 1234
165
- end
166
- define_model_class("TestClass", "TestSuperClass")
167
- object = TestClass.new
168
- assert_equal 1234, object.number
169
- end
170
-
171
- def test_default_values_in_subclass
172
- define_model_class("TestSuperClass") do
173
- end
174
- define_model_class("TestClass", "TestSuperClass") do
175
- default_value_for :number, 5678
176
- end
177
-
178
- object = TestClass.new
179
- assert_equal 5678, object.number
180
-
181
- object = TestSuperClass.new
182
- assert_nil object.number
183
- end
184
-
185
- def test_multiple_default_values_in_subclass_with_default_values_in_parent_class
186
- define_model_class("TestSuperClass") do
187
- default_value_for :other_number, nil
188
- attr_accessor :other_number
189
- end
190
- define_model_class("TestClass", "TestSuperClass") do
191
- default_value_for :number, 5678
192
-
193
- # Ensure second call in this class doesn't reset _default_attribute_values,
194
- # and also doesn't consider the parent class' _default_attribute_values when
195
- # making that check.
196
- default_value_for :user_id, 9999
197
- end
198
-
199
- object = TestClass.new
200
- assert_nil object.other_number
201
- assert_equal 5678, object.number
202
- assert_equal 9999, object.user_id
203
- end
204
-
205
- def test_override_default_values_in_subclass
206
- define_model_class("TestSuperClass") do
207
- default_value_for :number, 1234
208
- end
209
- define_model_class("TestClass", "TestSuperClass") do
210
- default_value_for :number, 5678
211
- end
212
-
213
- object = TestClass.new
214
- assert_equal 5678, object.number
215
-
216
- object = TestSuperClass.new
217
- assert_equal 1234, object.number
218
- end
219
-
220
- def test_default_values_in_subclass_do_not_affect_parent_class
221
- define_model_class("TestSuperClass") do
222
- default_value_for :number, 1234
223
- end
224
- define_model_class("TestClass", "TestSuperClass") do
225
- default_value_for :hello, "hi"
226
- attr_accessor :hello
227
- end
228
-
229
- assert_nothing_raised { TestSuperClass.new }
230
- assert !TestSuperClass._default_attribute_values.include?(:hello)
231
- end
232
-
233
- def test_doesnt_set_default_on_saved_records
234
- define_model_class do
235
- default_value_for :number, 1234
236
- end
237
- assert_equal 9876, TestClass.find(:first).number
238
- end
239
-
240
- def test_also_works_on_attributes_that_arent_database_columns
241
- define_model_class do
242
- default_value_for :hello, "hi"
243
- attr_accessor :hello
244
- end
245
- object = TestClass.new
246
- assert_equal 'hi', object.hello
247
- end
248
-
249
- def test_constructor_ignores_forbidden_mass_assignment_attributes
250
- define_model_class do
251
- default_value_for :number, 1234
252
- attr_protected :number
253
- end
254
- object = TestClass.new(:number => 5678, :count => 987)
255
- assert_equal 1234, object.number
256
- assert_equal 987, object.count
257
- end
258
-
259
- def test_doesnt_conflict_with_overrided_initialize_method_in_model_class
260
- define_model_class do
261
- def initialize(attrs = {})
262
- @initialized = true
263
- super(:count => 5678)
264
- end
265
-
266
- default_value_for :number, 1234
267
- end
268
- object = TestClass.new
269
- assert_equal 1234, object.number
270
- assert_equal 5678, object.count
271
- assert object.instance_variable_get('@initialized')
272
- end
273
-
274
- def test_model_instance_is_passed_to_the_given_block
275
- $instance = nil
276
- define_model_class do
277
- default_value_for :number do |n|
278
- $instance = n
279
- end
280
- end
281
- object = TestClass.new
282
- assert_same object, $instance
283
- end
284
-
285
- def test_can_specify_default_value_via_association
286
- user = User.create(:username => 'Kanako', :default_number => 123)
287
- define_model_class do
288
- belongs_to :user
289
-
290
- default_value_for :number do |n|
291
- n.user.default_number
292
- end
293
- end
294
- object = user.numbers.create
295
- assert_equal 123, object.number
296
- end
297
-
298
- def test_default_values
299
- define_model_class do
300
- default_values :type => "normal",
301
- :number => lambda { 10 + 5 },
302
- :timestamp => lambda {|_| Time.now }
303
- end
304
-
305
- object = TestClass.new
306
- assert_equal("normal", object.type)
307
- assert_equal(15, object.number)
308
- end
309
-
310
- def test_default_value_order
311
- define_model_class do
312
- default_value_for :count, 5
313
- default_value_for :number do |this|
314
- this.count * 2
315
- end
316
- end
317
- object = TestClass.new
318
- assert_equal(5, object.count)
319
- assert_equal(10, object.number)
320
- end
321
-
322
- def test_attributes_with_default_values_are_not_marked_as_changed
323
- define_model_class do
324
- default_value_for :count, 5
325
- default_value_for :number, 2
326
- end
327
-
328
- object = TestClass.new
329
- assert(!object.changed?)
330
- assert_equal([], object.changed)
331
-
332
- object.type = "foo"
333
- assert(object.changed?)
334
- assert_equal(["type"], object.changed)
335
- end
336
-
337
- def test_default_values_are_duplicated
338
- define_model_class do
339
- set_table_name "users"
340
- default_value_for :username, "hello"
341
- end
342
- user1 = TestClass.new
343
- user1.username << " world"
344
- user2 = TestClass.new
345
- assert_equal("hello", user2.username)
346
- end
347
-
348
- def test_default_values_are_shallow_copied
349
- define_model_class do
350
- set_table_name "users"
351
- attr_accessor :hash
352
- default_value_for :hash, { 1 => [] }
353
- end
354
- user1 = TestClass.new
355
- user1.hash[1] << 1
356
- user2 = TestClass.new
357
- assert_equal([1], user2.hash[1])
358
- end
359
-
360
- def test_constructor_does_not_affect_the_hash_passed_to_it
361
- define_model_class do
362
- default_value_for :count, 5
363
- end
364
-
365
- options = { :count => 5, :user_id => 1 }
366
- options_dup = options.dup
367
- object = TestClass.new(options)
368
- assert_equal(options_dup, options)
369
- end
76
+ def setup
77
+ Number.create(:number => 9876)
78
+ end
79
+
80
+ def teardown
81
+ Number.delete_all
82
+ end
83
+
84
+ def define_model_class(name = "TestClass", parent_class_name = "ActiveRecord::Base", &block)
85
+ Object.send(:remove_const, name) rescue nil
86
+ eval("class #{name} < #{parent_class_name}; end", TOPLEVEL_BINDING)
87
+ klass = eval(name, TOPLEVEL_BINDING)
88
+ klass.class_eval do
89
+ if respond_to?(:table_name=)
90
+ self.table_name = 'numbers'
91
+ else
92
+ set_table_name 'numbers'
93
+ end
94
+ end
95
+ klass.class_eval(&block) if block_given?
96
+ end
97
+
98
+ def test_default_value_can_be_passed_as_argument
99
+ define_model_class do
100
+ default_value_for(:number, 1234)
101
+ end
102
+ object = TestClass.new
103
+ assert_equal 1234, object.number
104
+ end
105
+
106
+ def test_default_value_can_be_passed_as_block
107
+ define_model_class do
108
+ default_value_for(:number) { 1234 }
109
+ end
110
+ object = TestClass.new
111
+ assert_equal 1234, object.number
112
+ end
113
+
114
+ def test_works_with_create
115
+ define_model_class do
116
+ default_value_for :number, 1234
117
+ end
118
+
119
+ object = TestClass.create
120
+ assert_not_nil TestClass.find_by_number(1234)
121
+
122
+ # allows nil for existing records
123
+ object.update_attribute(:number, nil)
124
+ assert_nil TestClass.find_by_number(1234)
125
+ assert_nil TestClass.find(object.id).number
126
+ end
127
+
128
+ def test_does_not_allow_nil_for_existing_record
129
+ define_model_class do
130
+ default_value_for(:number, :allows_nil => false) { 1234 }
131
+ end
132
+
133
+ object = TestClass.create
134
+
135
+ # allows nil for existing records
136
+ object.update_attribute(:number, nil)
137
+ assert_nil TestClass.find_by_number(1234)
138
+ assert_equal 1234, TestClass.find(object.id).number
139
+ end
140
+
141
+ def test_overwrites_db_default
142
+ define_model_class do
143
+ default_value_for :count, 1234
144
+ end
145
+ object = TestClass.new
146
+ assert_equal 1234, object.count
147
+ end
148
+
149
+ def test_doesnt_overwrite_values_provided_by_mass_assignment
150
+ define_model_class do
151
+ default_value_for :number, 1234
152
+ end
153
+ object = TestClass.new(:number => 1, :count => 2)
154
+ assert_equal 1, object.number
155
+ end
156
+
157
+ def test_doesnt_overwrite_values_provided_by_multiparameter_assignment
158
+ define_model_class do
159
+ default_value_for :timestamp, Time.mktime(2000, 1, 1)
160
+ end
161
+ timestamp = Time.mktime(2009, 1, 1)
162
+ object = TestClass.new('timestamp(1i)' => '2009', 'timestamp(2i)' => '1', 'timestamp(3i)' => '1')
163
+ assert_equal timestamp, object.timestamp
164
+ end
165
+
166
+ def test_doesnt_overwrite_values_provided_by_constructor_block
167
+ define_model_class do
168
+ default_value_for :number, 1234
169
+ end
170
+ object = TestClass.new do |x|
171
+ x.number = 1
172
+ x.count = 2
173
+ end
174
+ assert_equal 1, object.number
175
+ end
176
+
177
+ def test_doesnt_overwrite_explicitly_provided_nil_values_in_mass_assignment
178
+ define_model_class do
179
+ default_value_for :number, 1234
180
+ end
181
+ object = TestClass.new(:number => nil)
182
+ assert_equal nil, object.number
183
+ end
184
+
185
+ def test_overwrites_explicitly_provided_nil_values_in_mass_assignment
186
+ define_model_class do
187
+ default_value_for :number, :value => 1234, :allows_nil => false
188
+ end
189
+ object = TestClass.new(:number => nil)
190
+ assert_equal 1234, object.number
191
+ end
192
+
193
+ def test_default_values_are_inherited
194
+ define_model_class("TestSuperClass") do
195
+ default_value_for :number, 1234
196
+ end
197
+ define_model_class("TestClass", "TestSuperClass")
198
+ object = TestClass.new
199
+ assert_equal 1234, object.number
200
+ end
201
+
202
+ def test_default_values_in_subclass
203
+ define_model_class("TestSuperClass") do
204
+ end
205
+ define_model_class("TestClass", "TestSuperClass") do
206
+ default_value_for :number, 5678
207
+ end
208
+
209
+ object = TestClass.new
210
+ assert_equal 5678, object.number
211
+
212
+ object = TestSuperClass.new
213
+ assert_nil object.number
214
+ end
215
+
216
+ def test_multiple_default_values_in_subclass_with_default_values_in_parent_class
217
+ define_model_class("TestSuperClass") do
218
+ default_value_for :other_number, nil
219
+ attr_accessor :other_number
220
+ end
221
+ define_model_class("TestClass", "TestSuperClass") do
222
+ default_value_for :number, 5678
223
+
224
+ # Ensure second call in this class doesn't reset _default_attribute_values,
225
+ # and also doesn't consider the parent class' _default_attribute_values when
226
+ # making that check.
227
+ default_value_for :user_id, 9999
228
+ end
229
+
230
+ object = TestClass.new
231
+ assert_nil object.other_number
232
+ assert_equal 5678, object.number
233
+ assert_equal 9999, object.user_id
234
+ end
235
+
236
+ def test_override_default_values_in_subclass
237
+ define_model_class("TestSuperClass") do
238
+ default_value_for :number, 1234
239
+ end
240
+ define_model_class("TestClass", "TestSuperClass") do
241
+ default_value_for :number, 5678
242
+ end
243
+
244
+ object = TestClass.new
245
+ assert_equal 5678, object.number
246
+
247
+ object = TestSuperClass.new
248
+ assert_equal 1234, object.number
249
+ end
250
+
251
+ def test_default_values_in_subclass_do_not_affect_parent_class
252
+ define_model_class("TestSuperClass") do
253
+ default_value_for :number, 1234
254
+ end
255
+ define_model_class("TestClass", "TestSuperClass") do
256
+ default_value_for :hello, "hi"
257
+ attr_accessor :hello
258
+ end
259
+
260
+ assert_nothing_raised { TestSuperClass.new }
261
+ assert !TestSuperClass._default_attribute_values.include?(:hello)
262
+ end
263
+
264
+ def test_doesnt_set_default_on_saved_records
265
+ define_model_class do
266
+ default_value_for :number, 1234
267
+ end
268
+ assert_equal 9876, TestClass.find(:first).number
269
+ end
270
+
271
+ def test_also_works_on_attributes_that_arent_database_columns
272
+ define_model_class do
273
+ default_value_for :hello, "hi"
274
+ attr_accessor :hello
275
+ end
276
+ object = TestClass.new
277
+ assert_equal 'hi', object.hello
278
+ end
279
+
280
+ def test_constructor_ignores_forbidden_mass_assignment_attributes
281
+ define_model_class do
282
+ default_value_for :number, 1234
283
+ attr_protected :number
284
+ end
285
+ object = TestClass.new(:number => 5678, :count => 987)
286
+ assert_equal 1234, object.number
287
+ assert_equal 987, object.count
288
+ end
289
+
290
+ def test_constructor_respects_without_protection_option
291
+ define_model_class do
292
+ default_value_for :number, 1234
293
+ attr_protected :number
294
+
295
+ def respond_to_mass_assignment_options?
296
+ respond_to? :mass_assignment_options
297
+ end
298
+ end
299
+
300
+ if TestClass.new.respond_to_mass_assignment_options?
301
+ # test without protection feature if available in current ActiveRecord version
302
+ object = TestClass.create!({:number => 5678, :count => 987}, :without_protection => true)
303
+ assert_equal 5678, object.number
304
+ assert_equal 987, object.count
305
+ end
306
+ end
307
+
308
+ def test_doesnt_conflict_with_overrided_initialize_method_in_model_class
309
+ define_model_class do
310
+ def initialize(attrs = {})
311
+ @initialized = true
312
+ super(:count => 5678)
313
+ end
314
+
315
+ default_value_for :number, 1234
316
+ end
317
+ object = TestClass.new
318
+ assert_equal 1234, object.number
319
+ assert_equal 5678, object.count
320
+ assert object.instance_variable_get('@initialized')
321
+ end
322
+
323
+ def test_model_instance_is_passed_to_the_given_block
324
+ $instance = nil
325
+ define_model_class do
326
+ default_value_for :number do |n|
327
+ $instance = n
328
+ end
329
+ end
330
+ object = TestClass.new
331
+ assert_same object, $instance
332
+ end
333
+
334
+ def test_can_specify_default_value_via_association
335
+ user = User.create(:username => 'Kanako', :default_number => 123)
336
+ define_model_class do
337
+ belongs_to :user
338
+
339
+ default_value_for :number do |n|
340
+ n.user.default_number
341
+ end
342
+ end
343
+ object = user.numbers.create
344
+ assert_equal 123, object.number
345
+ end
346
+
347
+ def test_default_values
348
+ define_model_class do
349
+ default_values :type => "normal",
350
+ :number => lambda { 10 + 5 },
351
+ :timestamp => lambda {|_| Time.now }
352
+ end
353
+
354
+ object = TestClass.new
355
+ assert_equal("normal", object.type)
356
+ assert_equal(15, object.number)
357
+ end
358
+
359
+ def test_default_value_order
360
+ define_model_class do
361
+ default_value_for :count, 5
362
+ default_value_for :number do |this|
363
+ this.count * 2
364
+ end
365
+ end
366
+ object = TestClass.new
367
+ assert_equal(5, object.count)
368
+ assert_equal(10, object.number)
369
+ end
370
+
371
+ def test_attributes_with_default_values_are_not_marked_as_changed
372
+ define_model_class do
373
+ default_value_for :count, 5
374
+ default_value_for :number, 2
375
+ end
376
+
377
+ object = TestClass.new
378
+ assert(!object.changed?)
379
+ assert_equal([], object.changed)
380
+
381
+ object.type = "foo"
382
+ assert(object.changed?)
383
+ assert_equal(["type"], object.changed)
384
+ end
385
+
386
+ def test_default_values_are_duplicated
387
+ define_model_class do
388
+ if respond_to?(:table_name=)
389
+ self.table_name = "users"
390
+ else
391
+ set_table_name "users"
392
+ end
393
+ default_value_for :username, "hello"
394
+ end
395
+ user1 = TestClass.new
396
+ user1.username << " world"
397
+ user2 = TestClass.new
398
+ assert_equal("hello", user2.username)
399
+ end
400
+
401
+ def test_default_values_are_shallow_copied
402
+ define_model_class do
403
+ if respond_to?(:table_name=)
404
+ self.table_name = "users"
405
+ else
406
+ set_table_name "users"
407
+ end
408
+ attr_accessor :hash
409
+ default_value_for :hash, { 1 => [] }
410
+ end
411
+ user1 = TestClass.new
412
+ user1.hash[1] << 1
413
+ user2 = TestClass.new
414
+ assert_equal([1], user2.hash[1])
415
+ end
416
+
417
+ def test_constructor_does_not_affect_the_hash_passed_to_it
418
+ define_model_class do
419
+ default_value_for :count, 5
420
+ end
421
+
422
+ options = { :count => 5, :user_id => 1 }
423
+ options_dup = options.dup
424
+ object = TestClass.new(options)
425
+ assert_equal(options_dup, options)
426
+ end
370
427
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: default_value_for
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
- - 1
7
+ - 2
8
8
  - 0
9
- - 7
10
- version: 1.0.7
9
+ - 0
10
+ version: 2.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Hongli Lai
@@ -15,8 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-12-02 00:00:00 +01:00
19
- default_executable:
18
+ date: 2012-05-27 00:00:00 Z
20
19
  dependencies: []
21
20
 
22
21
  description: The default_value_for plugin allows one to define default values for ActiveRecord models in a declarative manner
@@ -36,7 +35,6 @@ files:
36
35
  - init.rb
37
36
  - lib/default_value_for.rb
38
37
  - lib/default_value_for/railtie.rb
39
- has_rdoc: true
40
38
  homepage: http://github.com/FooBarWidget/default_value_for
41
39
  licenses: []
42
40
 
@@ -66,9 +64,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
64
  requirements: []
67
65
 
68
66
  rubyforge_project:
69
- rubygems_version: 1.5.2
67
+ rubygems_version: 1.8.15
70
68
  signing_key:
71
69
  specification_version: 3
72
70
  summary: Provides a way to specify default values for ActiveRecord models
73
71
  test_files: []
74
72
 
73
+ has_rdoc: