assignable_values 0.14.0 → 0.16.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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +44 -27
- data/CHANGELOG.md +36 -2
- data/Gemfile +1 -1
- data/{gemfiles/Gemfile.2.3 → Gemfile.2.3} +1 -1
- data/{gemfiles/Gemfile.2.3.lock → Gemfile.2.3.lock} +2 -2
- data/{gemfiles/Gemfile.3.2 → Gemfile.3.2} +1 -1
- data/{gemfiles/Gemfile.3.2.lock → Gemfile.3.2.lock} +2 -2
- data/{gemfiles/Gemfile.4.2 → Gemfile.4.2} +1 -1
- data/{gemfiles/Gemfile.4.2.lock → Gemfile.4.2.lock} +2 -2
- data/{gemfiles/Gemfile.5.0 → Gemfile.5.0} +1 -1
- data/{gemfiles/Gemfile.5.0.lock → Gemfile.5.0.lock} +2 -2
- data/{gemfiles/Gemfile.5.1 → Gemfile.5.1} +1 -1
- data/{gemfiles/Gemfile.5.1.lock → Gemfile.5.1.lock} +3 -3
- data/{gemfiles/Gemfile.5.1.pg → Gemfile.5.1.pg} +1 -1
- data/{gemfiles/Gemfile.5.1.pg.lock → Gemfile.5.1.pg.lock} +2 -2
- data/Gemfile.6.0.pg +16 -0
- data/Gemfile.6.0.pg.lock +68 -0
- data/Gemfile.lock +1 -1
- data/README.md +24 -14
- data/lib/assignable_values.rb +1 -0
- data/lib/assignable_values/active_record/restriction/base.rb +30 -10
- data/lib/assignable_values/active_record/restriction/scalar_attribute.rb +33 -8
- data/lib/assignable_values/humanizable_string.rb +2 -1
- data/lib/assignable_values/version.rb +1 -1
- data/spec/assignable_values/active_record_spec.rb +249 -56
- data/spec/support/database.rb +1 -1
- data/spec/support/i18n.yml +7 -1
- data/spec/support/models.rb +3 -3
- metadata +17 -16
data/lib/assignable_values.rb
CHANGED
@@ -48,25 +48,31 @@ module AssignableValues
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def assignable_values(record, options = {})
|
51
|
-
|
51
|
+
additional_assignable_values = []
|
52
52
|
current_values = assignable_values_from_record_or_delegate(record)
|
53
53
|
|
54
54
|
if options.fetch(:include_old_value, true) && has_previously_saved_value?(record)
|
55
55
|
old_value = previously_saved_value(record)
|
56
56
|
if @options[:multiple]
|
57
57
|
if old_value.is_a?(Array)
|
58
|
-
|
58
|
+
additional_assignable_values |= old_value
|
59
59
|
end
|
60
60
|
elsif !old_value.blank? && !current_values.include?(old_value)
|
61
|
-
|
61
|
+
additional_assignable_values << old_value
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
assignable_values += current_values
|
66
65
|
if options[:decorate]
|
67
|
-
|
66
|
+
current_values = decorate_values(current_values)
|
67
|
+
additional_assignable_values = decorate_values(additional_assignable_values)
|
68
|
+
end
|
69
|
+
|
70
|
+
if additional_assignable_values.present?
|
71
|
+
# will not keep current_values scoped
|
72
|
+
additional_assignable_values + current_values
|
73
|
+
else
|
74
|
+
current_values
|
68
75
|
end
|
69
|
-
assignable_values
|
70
76
|
end
|
71
77
|
|
72
78
|
private
|
@@ -94,7 +100,21 @@ module AssignableValues
|
|
94
100
|
def assignable_single_value?(record, value)
|
95
101
|
(has_previously_saved_value?(record) && value == previously_saved_value(record)) ||
|
96
102
|
(value.blank? && allow_blank?(record)) ||
|
97
|
-
|
103
|
+
included_in_assignable_values?(record, value)
|
104
|
+
end
|
105
|
+
|
106
|
+
def included_in_assignable_values?(record, value)
|
107
|
+
values_or_scope = assignable_values(record, :include_old_value => false)
|
108
|
+
|
109
|
+
if is_scope?(values_or_scope)
|
110
|
+
values_or_scope.exists?(value.id)
|
111
|
+
else
|
112
|
+
values_or_scope.include?(value)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def is_scope?(object)
|
117
|
+
object.respond_to?(:scoped) || object.respond_to?(:all)
|
98
118
|
end
|
99
119
|
|
100
120
|
def assignable_multi_value?(record, value)
|
@@ -217,9 +237,9 @@ module AssignableValues
|
|
217
237
|
|
218
238
|
def assignable_values_from_record_or_delegate(record)
|
219
239
|
if delegate?
|
220
|
-
assignable_values_from_delegate(record)
|
240
|
+
assignable_values_from_delegate(record)
|
221
241
|
else
|
222
|
-
record.instance_exec(&@values)
|
242
|
+
record.instance_exec(&@values)
|
223
243
|
end
|
224
244
|
end
|
225
245
|
|
@@ -240,7 +260,7 @@ module AssignableValues
|
|
240
260
|
delegate = delegate(record)
|
241
261
|
delegate.present? or raise DelegateUnavailable, "Cannot query a nil delegate for assignable values"
|
242
262
|
delegate_query_method = :"assignable_#{model.name.underscore.gsub('/', '_')}_#{property.to_s.pluralize}"
|
243
|
-
args = delegate.method(delegate_query_method).arity ==
|
263
|
+
args = delegate.method(delegate_query_method).arity == 0 ? [] : [record]
|
244
264
|
delegate.send(delegate_query_method, *args)
|
245
265
|
end
|
246
266
|
|
@@ -7,7 +7,7 @@ module AssignableValues
|
|
7
7
|
super
|
8
8
|
define_humanized_value_instance_method
|
9
9
|
define_humanized_value_class_method
|
10
|
-
|
10
|
+
define_humanized_assignable_values_instance_method
|
11
11
|
end
|
12
12
|
|
13
13
|
def humanized_value(value)
|
@@ -17,8 +17,8 @@ module AssignableValues
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
values = assignable_values(record)
|
20
|
+
def humanized_assignable_values(record, options = {})
|
21
|
+
values = assignable_values(record, options)
|
22
22
|
values.collect do |value|
|
23
23
|
HumanizedValue.new(value, humanized_value(value))
|
24
24
|
end
|
@@ -37,7 +37,7 @@ module AssignableValues
|
|
37
37
|
def define_humanized_value_class_method
|
38
38
|
restriction = self
|
39
39
|
enhance_model_singleton do
|
40
|
-
define_method :"humanized_#{restriction.property}" do |given_value|
|
40
|
+
define_method :"humanized_#{restriction.property.to_s.singularize}" do |given_value|
|
41
41
|
restriction.humanized_value(given_value)
|
42
42
|
end
|
43
43
|
end
|
@@ -45,20 +45,45 @@ module AssignableValues
|
|
45
45
|
|
46
46
|
def define_humanized_value_instance_method
|
47
47
|
restriction = self
|
48
|
+
multiple = @options[:multiple]
|
48
49
|
enhance_model do
|
49
|
-
define_method :"humanized_#{restriction.property}" do |*args|
|
50
|
+
define_method :"humanized_#{restriction.property.to_s.singularize}" do |*args|
|
51
|
+
if args.size > 1 || (multiple && args.size == 0)
|
52
|
+
raise ArgumentError.new("wrong number of arguments (#{args.size} for #{multiple ? '1' : '0..1'})")
|
53
|
+
end
|
50
54
|
given_value = args[0]
|
51
55
|
value = given_value || send(restriction.property)
|
52
56
|
restriction.humanized_value(value)
|
53
57
|
end
|
58
|
+
|
59
|
+
if multiple
|
60
|
+
define_method :"humanized_#{restriction.property}" do
|
61
|
+
values = send(restriction.property)
|
62
|
+
if values.respond_to?(:map)
|
63
|
+
values.map do |value|
|
64
|
+
restriction.humanized_value(value)
|
65
|
+
end
|
66
|
+
else
|
67
|
+
values
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
54
71
|
end
|
55
72
|
end
|
56
73
|
|
57
|
-
def
|
74
|
+
def define_humanized_assignable_values_instance_method
|
58
75
|
restriction = self
|
76
|
+
multiple = @options[:multiple]
|
59
77
|
enhance_model do
|
60
|
-
define_method :"
|
61
|
-
restriction.
|
78
|
+
define_method :"humanized_assignable_#{restriction.property.to_s.pluralize}" do |*args|
|
79
|
+
restriction.humanized_assignable_values(self, *args)
|
80
|
+
end
|
81
|
+
|
82
|
+
unless multiple
|
83
|
+
define_method :"humanized_#{restriction.property.to_s.pluralize}" do
|
84
|
+
ActiveSupport::Deprecation.warn("humanized_<value>s is deprecated, use humanized_assignable_<value>s instead", caller)
|
85
|
+
restriction.humanized_assignable_values(self)
|
86
|
+
end
|
62
87
|
end
|
63
88
|
end
|
64
89
|
end
|
@@ -1,6 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'ostruct'
|
3
3
|
|
4
|
+
def save_without_validation(record)
|
5
|
+
if ActiveRecord::VERSION::MAJOR < 3
|
6
|
+
record.save(false)
|
7
|
+
else
|
8
|
+
record.save(:validate => false)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
4
12
|
describe AssignableValues::ActiveRecord do
|
5
13
|
|
6
14
|
describe '.assignable_values' do
|
@@ -17,24 +25,30 @@ describe AssignableValues::ActiveRecord do
|
|
17
25
|
|
18
26
|
before :each do
|
19
27
|
@klass = Song.disposable_copy do
|
20
|
-
assignable_values_for :
|
28
|
+
assignable_values_for :virtual_sub_genre do
|
29
|
+
%w[pop rock]
|
30
|
+
end
|
31
|
+
|
32
|
+
assignable_values_for :virtual_multi_genres, :multiple => true, :allow_blank => true do
|
21
33
|
%w[pop rock]
|
22
34
|
end
|
23
35
|
end
|
24
36
|
end
|
25
37
|
|
26
38
|
it 'should validate that the attribute is allowed' do
|
27
|
-
@klass.new(:
|
28
|
-
@klass.new(:
|
39
|
+
@klass.new(:virtual_sub_genre => 'pop').should be_valid
|
40
|
+
@klass.new(:virtual_sub_genre => 'disallowed value').should_not be_valid
|
29
41
|
end
|
30
42
|
|
31
43
|
it 'should not allow nil for the attribute value' do
|
32
|
-
@klass.new(:
|
44
|
+
@klass.new(:virtual_sub_genre => nil).should_not be_valid
|
33
45
|
end
|
34
46
|
|
35
47
|
it 'should generate a method returning the humanized value' do
|
36
|
-
song = @klass.new(:
|
37
|
-
song.
|
48
|
+
song = @klass.new(:virtual_sub_genre => 'pop')
|
49
|
+
song.humanized_virtual_sub_genre.should == 'Pop music'
|
50
|
+
song.humanized_virtual_sub_genre('rock').should == 'Rock music'
|
51
|
+
song.humanized_virtual_multi_genre('rock').should == 'Rock music'
|
38
52
|
end
|
39
53
|
|
40
54
|
end
|
@@ -45,21 +59,21 @@ describe AssignableValues::ActiveRecord do
|
|
45
59
|
|
46
60
|
before :each do
|
47
61
|
@klass = Song.disposable_copy do
|
48
|
-
assignable_values_for :
|
62
|
+
assignable_values_for :virtual_multi_genres, :multiple => true do
|
49
63
|
%w[pop rock]
|
50
64
|
end
|
51
65
|
end
|
52
66
|
end
|
53
67
|
|
54
68
|
it 'should validate that the attribute is a subset' do
|
55
|
-
@klass.new(:
|
56
|
-
@klass.new(:
|
57
|
-
@klass.new(:
|
69
|
+
@klass.new(:virtual_multi_genres => ['pop']).should be_valid
|
70
|
+
@klass.new(:virtual_multi_genres => ['pop', 'rock']).should be_valid
|
71
|
+
@klass.new(:virtual_multi_genres => ['pop', 'disallowed value']).should_not be_valid
|
58
72
|
end
|
59
73
|
|
60
74
|
it 'should not allow nil or [] for allow_blank: false' do
|
61
|
-
@klass.new(:
|
62
|
-
@klass.new(:
|
75
|
+
@klass.new(:virtual_multi_genres => nil).should_not be_valid
|
76
|
+
@klass.new(:virtual_multi_genres => []).should_not be_valid
|
63
77
|
end
|
64
78
|
|
65
79
|
end
|
@@ -68,15 +82,15 @@ describe AssignableValues::ActiveRecord do
|
|
68
82
|
|
69
83
|
before :each do
|
70
84
|
@klass = Song.disposable_copy do
|
71
|
-
assignable_values_for :
|
85
|
+
assignable_values_for :virtual_multi_genres, :multiple => true, :allow_blank => true do
|
72
86
|
%w[pop rock]
|
73
87
|
end
|
74
88
|
end
|
75
89
|
end
|
76
90
|
|
77
91
|
it 'should allow nil or [] for allow_blank: false' do
|
78
|
-
@klass.new(:
|
79
|
-
@klass.new(:
|
92
|
+
@klass.new(:virtual_multi_genres => nil).should be_valid
|
93
|
+
@klass.new(:virtual_multi_genres => []).should be_valid
|
80
94
|
end
|
81
95
|
|
82
96
|
end
|
@@ -92,6 +106,10 @@ describe AssignableValues::ActiveRecord do
|
|
92
106
|
assignable_values_for :genre do
|
93
107
|
%w[pop rock]
|
94
108
|
end
|
109
|
+
|
110
|
+
assignable_values_for :virtual_multi_genres, :multiple => true, :allow_blank => true do
|
111
|
+
%w[pop rock]
|
112
|
+
end
|
95
113
|
end
|
96
114
|
end
|
97
115
|
|
@@ -153,6 +171,31 @@ describe AssignableValues::ActiveRecord do
|
|
153
171
|
@klass.humanized_genre('rock').should == 'Rock music'
|
154
172
|
end
|
155
173
|
|
174
|
+
context 'for multiple: true' do
|
175
|
+
it 'should raise when trying to humanize a value without an argument' do
|
176
|
+
song = @klass.new
|
177
|
+
proc { song.humanized_virtual_multi_genre }.should raise_error(ArgumentError)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should generate an instance method to retrieve the humanization of any given value' do
|
181
|
+
song = @klass.new(:genre => 'pop')
|
182
|
+
song.humanized_virtual_multi_genre('rock').should == 'Rock music'
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'should generate a class method to retrieve the humanization of any given value' do
|
186
|
+
@klass.humanized_virtual_multi_genre('rock').should == 'Rock music'
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'should generate an instance method to retrieve the humanizations of all current values' do
|
190
|
+
song = @klass.new
|
191
|
+
song.virtual_multi_genres = nil
|
192
|
+
song.humanized_virtual_multi_genres.should == nil
|
193
|
+
song.virtual_multi_genres = []
|
194
|
+
song.humanized_virtual_multi_genres.should == []
|
195
|
+
song.virtual_multi_genres = ['pop', 'rock']
|
196
|
+
song.humanized_virtual_multi_genres.should == ['Pop music', 'Rock music']
|
197
|
+
end
|
198
|
+
end
|
156
199
|
end
|
157
200
|
|
158
201
|
context 'if the :allow_blank option is set to true' do
|
@@ -220,11 +263,11 @@ describe AssignableValues::ActiveRecord do
|
|
220
263
|
context 'if the :message option is set to a string' do
|
221
264
|
|
222
265
|
before :each do
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
266
|
+
@klass = Song.disposable_copy do
|
267
|
+
assignable_values_for :genre, :message => 'should be something different' do
|
268
|
+
%w[pop rock]
|
269
|
+
end
|
270
|
+
end
|
228
271
|
end
|
229
272
|
|
230
273
|
it 'should use this string as a custom error message' do
|
@@ -245,43 +288,39 @@ describe AssignableValues::ActiveRecord do
|
|
245
288
|
|
246
289
|
before :each do
|
247
290
|
@klass = Song.disposable_copy do
|
248
|
-
assignable_values_for :
|
291
|
+
assignable_values_for :multi_genres, :multiple => true do
|
249
292
|
%w[pop rock]
|
250
293
|
end
|
251
294
|
end
|
252
295
|
end
|
253
296
|
|
254
297
|
it 'should validate that the attribute is allowed' do
|
255
|
-
@klass.new(:
|
256
|
-
@klass.new(:
|
257
|
-
@klass.new(:
|
298
|
+
@klass.new(:multi_genres => ['pop']).should be_valid
|
299
|
+
@klass.new(:multi_genres => ['pop', 'rock']).should be_valid
|
300
|
+
@klass.new(:multi_genres => ['pop', 'invalid value']).should_not be_valid
|
258
301
|
end
|
259
302
|
|
260
303
|
it 'should not allow a scalar attribute' do
|
261
|
-
@klass.new(:
|
304
|
+
@klass.new(:multi_genres => 'pop').should_not be_valid
|
262
305
|
end
|
263
306
|
|
264
307
|
it 'should not allow nil or [] for the attribute value' do
|
265
|
-
@klass.new(:
|
266
|
-
@klass.new(:
|
308
|
+
@klass.new(:multi_genres => nil).should_not be_valid
|
309
|
+
@klass.new(:multi_genres => []).should_not be_valid
|
267
310
|
end
|
268
311
|
|
269
312
|
it 'should allow a subset of previously saved values even if that value is no longer allowed' do
|
270
|
-
record = @klass.create!(:
|
271
|
-
record.
|
272
|
-
|
273
|
-
record.save(false)
|
274
|
-
else
|
275
|
-
record.save(:validate => false) # update without validations for the sake of this test
|
276
|
-
end
|
313
|
+
record = @klass.create!(:multi_genres => ['pop'])
|
314
|
+
record.multi_genres = ['pretend', 'previously', 'valid', 'value']
|
315
|
+
save_without_validation(record) # update without validation for the sake of this test
|
277
316
|
record.reload.should be_valid
|
278
|
-
record.
|
317
|
+
record.multi_genres = ['valid', 'previously', 'pop']
|
279
318
|
record.should be_valid
|
280
319
|
end
|
281
320
|
|
282
321
|
it 'should allow a previously saved, blank value even if that value is no longer allowed' do
|
283
|
-
record = @klass.create!(:
|
284
|
-
@klass.update_all(:
|
322
|
+
record = @klass.create!(:multi_genres => ['pop'])
|
323
|
+
@klass.update_all(:multi_genres => []) # update without validations for the sake of this test
|
285
324
|
record.reload.should be_valid
|
286
325
|
end
|
287
326
|
|
@@ -291,18 +330,18 @@ describe AssignableValues::ActiveRecord do
|
|
291
330
|
|
292
331
|
before :each do
|
293
332
|
@klass = Song.disposable_copy do
|
294
|
-
assignable_values_for :
|
333
|
+
assignable_values_for :multi_genres, :multiple => true, :allow_blank => true do
|
295
334
|
%w[pop rock]
|
296
335
|
end
|
297
336
|
end
|
298
337
|
end
|
299
338
|
|
300
339
|
it 'should allow nil for the attribute value' do
|
301
|
-
@klass.new(:
|
340
|
+
@klass.new(:multi_genres => nil).should be_valid
|
302
341
|
end
|
303
342
|
|
304
343
|
it 'should allow an empty array as value' do
|
305
|
-
@klass.new(:
|
344
|
+
@klass.new(:multi_genres => []).should be_valid
|
306
345
|
end
|
307
346
|
|
308
347
|
end
|
@@ -409,7 +448,7 @@ describe AssignableValues::ActiveRecord do
|
|
409
448
|
record.should be_valid
|
410
449
|
end
|
411
450
|
|
412
|
-
it '
|
451
|
+
it 'should not allow nil for an association (the "previously saved value") if the record is new' do
|
413
452
|
allowed_association = Artist.create!
|
414
453
|
klass = Song.disposable_copy
|
415
454
|
record = klass.new(:artist => nil)
|
@@ -471,6 +510,47 @@ describe AssignableValues::ActiveRecord do
|
|
471
510
|
record.valid?
|
472
511
|
end
|
473
512
|
|
513
|
+
it 'should not load all records to memory when assignable values are scoped' do
|
514
|
+
unless ::ActiveRecord::VERSION::MAJOR < 3 # somehow rails 2 still initializes Objects during the scope.exists?-call
|
515
|
+
initialized_artists_count = 0
|
516
|
+
MyArtist = Artist.disposable_copy
|
517
|
+
|
518
|
+
MyArtist.class_eval do
|
519
|
+
after_initialize :increase_initialized_count
|
520
|
+
|
521
|
+
define_method :increase_initialized_count do
|
522
|
+
initialized_artists_count += 1
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
klass = Song.disposable_copy
|
527
|
+
|
528
|
+
klass.class_eval do
|
529
|
+
assignable_values_for :artist do
|
530
|
+
if ::ActiveRecord::VERSION::MAJOR < 4
|
531
|
+
MyArtist.scoped
|
532
|
+
else
|
533
|
+
MyArtist.all
|
534
|
+
end
|
535
|
+
end
|
536
|
+
end
|
537
|
+
|
538
|
+
artist = MyArtist.create!
|
539
|
+
initialized_artists_count.should == 1
|
540
|
+
|
541
|
+
song = klass.new(:artist => artist)
|
542
|
+
|
543
|
+
song.valid?
|
544
|
+
initialized_artists_count.should == 1
|
545
|
+
|
546
|
+
song.assignable_artists
|
547
|
+
initialized_artists_count.should == 1
|
548
|
+
|
549
|
+
song.assignable_artists.to_a
|
550
|
+
initialized_artists_count.should == 2
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
474
554
|
end
|
475
555
|
|
476
556
|
context 'when delegating using the :through option' do
|
@@ -479,7 +559,11 @@ describe AssignableValues::ActiveRecord do
|
|
479
559
|
klass = Song.disposable_copy do
|
480
560
|
assignable_values_for :genre, :through => :delegate
|
481
561
|
def delegate
|
482
|
-
|
562
|
+
Class.new do
|
563
|
+
def assignable_song_genres
|
564
|
+
%w[pop rock]
|
565
|
+
end
|
566
|
+
end.new
|
483
567
|
end
|
484
568
|
end
|
485
569
|
klass.new(:genre => 'pop').should be_valid
|
@@ -490,9 +574,14 @@ describe AssignableValues::ActiveRecord do
|
|
490
574
|
klass = Song.disposable_copy do
|
491
575
|
assignable_values_for :genre, :through => lambda { delegate }
|
492
576
|
def delegate
|
493
|
-
|
577
|
+
Class.new do
|
578
|
+
def assignable_song_genres
|
579
|
+
%w[pop rock]
|
580
|
+
end
|
581
|
+
end.new
|
494
582
|
end
|
495
583
|
end
|
584
|
+
|
496
585
|
klass.new(:genre => 'pop').should be_valid
|
497
586
|
klass.new(:genre => 'disallowed value').should_not be_valid
|
498
587
|
end
|
@@ -501,7 +590,11 @@ describe AssignableValues::ActiveRecord do
|
|
501
590
|
klass = Recording::Vinyl.disposable_copy do
|
502
591
|
assignable_values_for :year, :through => :delegate
|
503
592
|
def delegate
|
504
|
-
|
593
|
+
Class.new do
|
594
|
+
def assignable_recording_vinyl_years
|
595
|
+
[1977, 1980, 1983]
|
596
|
+
end
|
597
|
+
end.new
|
505
598
|
end
|
506
599
|
end
|
507
600
|
klass.new.assignable_years.should == [1977, 1980, 1983]
|
@@ -678,7 +771,7 @@ describe AssignableValues::ActiveRecord do
|
|
678
771
|
klass.new.assignable_genres.should == %w[pop rock]
|
679
772
|
end
|
680
773
|
|
681
|
-
it 'should
|
774
|
+
it 'should work with ranges' do
|
682
775
|
klass = Song.disposable_copy do
|
683
776
|
assignable_values_for :year do
|
684
777
|
1999..2001
|
@@ -704,10 +797,28 @@ describe AssignableValues::ActiveRecord do
|
|
704
797
|
assignable_values_for :genre do
|
705
798
|
%w[pop rock]
|
706
799
|
end
|
800
|
+
|
801
|
+
assignable_values_for :multi_genres, :multiple => true do
|
802
|
+
%w[pop rock]
|
803
|
+
end
|
707
804
|
end
|
708
|
-
record = klass.create!(:genre => 'pop')
|
805
|
+
record = klass.create!(:genre => 'pop', :multi_genres => ['rock'])
|
709
806
|
klass.update_all(:genre => 'ballad') # update without validation for the sake of this test
|
710
807
|
record.reload.assignable_genres.should == %w[ballad pop rock]
|
808
|
+
|
809
|
+
humanized_genres = record.humanized_assignable_genres
|
810
|
+
humanized_genres.collect(&:value).should == %w[ballad pop rock]
|
811
|
+
humanized_genres.collect(&:humanized).should == ['Ballad', 'Pop music', 'Rock music']
|
812
|
+
humanized_genres.collect(&:to_s).should == ['Ballad', 'Pop music', 'Rock music']
|
813
|
+
|
814
|
+
record.multi_genres = %w[ballad classic]
|
815
|
+
save_without_validation(record) # update without validation for the sake of this test
|
816
|
+
record.reload.multi_genres.should == %w[ballad classic]
|
817
|
+
|
818
|
+
humanized_multi_genres = record.humanized_assignable_multi_genres
|
819
|
+
humanized_multi_genres.collect(&:value).should == %w[ballad classic pop rock]
|
820
|
+
humanized_multi_genres.collect(&:humanized).should == ['Ballad', 'Classic', 'Pop music', 'Rock music']
|
821
|
+
humanized_multi_genres.collect(&:to_s).should == ['Ballad', 'Classic', 'Pop music', 'Rock music']
|
711
822
|
end
|
712
823
|
|
713
824
|
it 'should not prepend a previously saved value to the top of the list if it is still allowed (bugfix)' do
|
@@ -747,10 +858,28 @@ describe AssignableValues::ActiveRecord do
|
|
747
858
|
assignable_values_for :genre do
|
748
859
|
%w[pop rock]
|
749
860
|
end
|
861
|
+
|
862
|
+
assignable_values_for :multi_genres, :multiple => true do
|
863
|
+
%w[pop rock]
|
864
|
+
end
|
750
865
|
end
|
751
|
-
record = klass.create!(:genre => 'pop')
|
866
|
+
record = klass.create!(:genre => 'pop', :multi_genres => ['rock'])
|
752
867
|
klass.update_all(:genre => 'ballad') # update without validation for the sake of this test
|
753
868
|
record.reload.assignable_genres(:include_old_value => false).should == %w[pop rock]
|
869
|
+
|
870
|
+
humanized_genres = record.humanized_assignable_genres(:include_old_value => false)
|
871
|
+
humanized_genres.collect(&:value).should == %w[pop rock]
|
872
|
+
humanized_genres.collect(&:humanized).should == ['Pop music', 'Rock music']
|
873
|
+
humanized_genres.collect(&:to_s).should == ['Pop music', 'Rock music']
|
874
|
+
|
875
|
+
record.multi_genres = %w[ballad classic]
|
876
|
+
save_without_validation(record) # update without validation for the sake of this test
|
877
|
+
record.reload.multi_genres.should == %w[ballad classic]
|
878
|
+
|
879
|
+
humanized_multi_genres = record.humanized_assignable_multi_genres(:include_old_value => false)
|
880
|
+
humanized_multi_genres.collect(&:value).should == %w[pop rock]
|
881
|
+
humanized_multi_genres.collect(&:humanized).should == ['Pop music', 'Rock music']
|
882
|
+
humanized_multi_genres.collect(&:to_s).should == ['Pop music', 'Rock music']
|
754
883
|
end
|
755
884
|
|
756
885
|
it 'should allow omitting a previously saved association' do
|
@@ -791,11 +920,18 @@ describe AssignableValues::ActiveRecord do
|
|
791
920
|
assignable_values_for :genre do
|
792
921
|
%w[pop rock]
|
793
922
|
end
|
923
|
+
|
924
|
+
assignable_values_for :multi_genres, :multiple => true do
|
925
|
+
%w[pop rock]
|
926
|
+
end
|
794
927
|
end
|
795
|
-
genres = klass.new.
|
928
|
+
genres = klass.new.humanized_assignable_genres
|
796
929
|
genres.collect(&:value).should == ['pop', 'rock']
|
797
930
|
genres.collect(&:humanized).should == ['Pop music', 'Rock music']
|
798
931
|
genres.collect(&:to_s).should == ['Pop music', 'Rock music']
|
932
|
+
|
933
|
+
multi_genres = klass.new.humanized_assignable_multi_genres
|
934
|
+
multi_genres.collect(&:humanized).should == ['Pop music', 'Rock music']
|
799
935
|
end
|
800
936
|
|
801
937
|
it 'should use String#humanize as a default translation' do
|
@@ -804,7 +940,7 @@ describe AssignableValues::ActiveRecord do
|
|
804
940
|
%w[electronic]
|
805
941
|
end
|
806
942
|
end
|
807
|
-
klass.new.
|
943
|
+
klass.new.humanized_assignable_genres.collect(&:humanized).should == ['Electronic']
|
808
944
|
end
|
809
945
|
|
810
946
|
it 'should allow to define humanizations for values that are not strings' do
|
@@ -813,7 +949,7 @@ describe AssignableValues::ActiveRecord do
|
|
813
949
|
[1977, 1980, 1983]
|
814
950
|
end
|
815
951
|
end
|
816
|
-
years = klass.new.
|
952
|
+
years = klass.new.humanized_assignable_years
|
817
953
|
years.collect(&:value).should == [1977, 1980, 1983]
|
818
954
|
years.collect(&:humanized).should == ['The year a new hope was born', 'The year the Empire stroke back', 'The year the Jedi returned']
|
819
955
|
end
|
@@ -824,18 +960,30 @@ describe AssignableValues::ActiveRecord do
|
|
824
960
|
[1977, 1980, 1983]
|
825
961
|
end
|
826
962
|
end
|
827
|
-
years = klass.new.
|
963
|
+
years = klass.new.humanized_assignable_years
|
828
964
|
years.collect(&:humanized).should == ['The year a new hope was born', 'The year the Empire stroke back', 'The year the Jedi returned']
|
829
965
|
end
|
830
966
|
|
831
967
|
context 'legacy methods for API compatibility' do
|
832
968
|
|
969
|
+
it 'should define a method that return pairs of values and their humanization' do
|
970
|
+
klass = Song.disposable_copy do
|
971
|
+
assignable_values_for :genre do
|
972
|
+
%w[pop rock]
|
973
|
+
end
|
974
|
+
end
|
975
|
+
ActiveSupport::Deprecation.should_receive(:warn)
|
976
|
+
genres = klass.new.humanized_genres
|
977
|
+
genres.collect(&:humanized).should == ['Pop music', 'Rock music']
|
978
|
+
end
|
979
|
+
|
833
980
|
it "should define a method #humanized on assignable string values, which return up the value's' translation" do
|
834
981
|
klass = Song.disposable_copy do
|
835
982
|
assignable_values_for :genre do
|
836
983
|
%w[pop rock]
|
837
984
|
end
|
838
985
|
end
|
986
|
+
ActiveSupport::Deprecation.should_receive(:warn).at_least(:once)
|
839
987
|
klass.new.assignable_genres.collect(&:humanized).should == ['Pop music', 'Rock music']
|
840
988
|
end
|
841
989
|
|
@@ -872,7 +1020,7 @@ describe AssignableValues::ActiveRecord do
|
|
872
1020
|
delegate = Object.new
|
873
1021
|
def delegate.assignable_song_genres(record)
|
874
1022
|
record_received(record)
|
875
|
-
|
1023
|
+
%w[pop rock]
|
876
1024
|
end
|
877
1025
|
klass = Song.disposable_copy do
|
878
1026
|
assignable_values_for :genre, :through => :delegate
|
@@ -885,6 +1033,55 @@ describe AssignableValues::ActiveRecord do
|
|
885
1033
|
record.assignable_genres.should == %w[pop rock]
|
886
1034
|
end
|
887
1035
|
|
1036
|
+
it "should call the given method on the delegate if the delegate's query method takes no arguments" do
|
1037
|
+
delegate = Object.new
|
1038
|
+
def delegate.assignable_song_genres
|
1039
|
+
no_record_received
|
1040
|
+
%w[pop rock]
|
1041
|
+
end
|
1042
|
+
klass = Song.disposable_copy do
|
1043
|
+
assignable_values_for :genre, :through => :delegate
|
1044
|
+
define_method :delegate do
|
1045
|
+
delegate
|
1046
|
+
end
|
1047
|
+
end
|
1048
|
+
record = klass.new
|
1049
|
+
delegate.should_receive(:no_record_received)
|
1050
|
+
record.assignable_genres.should == %w[pop rock]
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
it "should pass the record to the given method if the delegate's query method takes variable arguments" do
|
1054
|
+
delegate = Object.new
|
1055
|
+
def delegate.assignable_song_genres(*records)
|
1056
|
+
record_received(*records)
|
1057
|
+
%w[pop rock]
|
1058
|
+
end
|
1059
|
+
klass = Song.disposable_copy do
|
1060
|
+
assignable_values_for :genre, :through => :delegate
|
1061
|
+
define_method :delegate do
|
1062
|
+
delegate
|
1063
|
+
end
|
1064
|
+
end
|
1065
|
+
record = klass.new
|
1066
|
+
delegate.should_receive(:record_received).with(record)
|
1067
|
+
record.assignable_genres.should == %w[pop rock]
|
1068
|
+
end
|
1069
|
+
|
1070
|
+
it "should raise an error if the delegate's query method takes more than one argument" do
|
1071
|
+
delegate = Object.new
|
1072
|
+
def delegate.assignable_song_genres(record, other_arg)
|
1073
|
+
%w[pop rock]
|
1074
|
+
end
|
1075
|
+
klass = Song.disposable_copy do
|
1076
|
+
assignable_values_for :genre, :through => :delegate
|
1077
|
+
define_method :delegate do
|
1078
|
+
delegate
|
1079
|
+
end
|
1080
|
+
end
|
1081
|
+
record = klass.new
|
1082
|
+
expect{record.assignable_genres}.to raise_error(ArgumentError)
|
1083
|
+
end
|
1084
|
+
|
888
1085
|
it 'should raise an error if the given method returns nil' do
|
889
1086
|
klass = Song.disposable_copy do
|
890
1087
|
assignable_values_for :genre, :through => :delegate
|
@@ -894,11 +1091,7 @@ describe AssignableValues::ActiveRecord do
|
|
894
1091
|
end
|
895
1092
|
expect { klass.new.assignable_genres }.to raise_error(AssignableValues::DelegateUnavailable)
|
896
1093
|
end
|
897
|
-
|
898
1094
|
end
|
899
|
-
|
900
1095
|
end
|
901
|
-
|
902
1096
|
end
|
903
|
-
|
904
1097
|
end
|