custom-attributes 0.2.17 → 0.2.18
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -1
- data/Gemfile.lock +25 -25
- data/VERSION +1 -1
- data/lib/active_record/custom_attributes.rb +21 -2
- data/lib/active_record/custom_attributes/custom_attribute.rb +38 -12
- data/lib/active_record/custom_attributes/custom_attribute_list.rb +30 -14
- data/lib/active_record/custom_attributes/custom_attribute_model.rb +8 -0
- data/spec/custom_attributes/custom_attributes.sqlite3 +0 -0
- data/spec/custom_attributes/has_custom_attributes_spec.rb +63 -21
- data/spec/models.rb +12 -2
- metadata +5 -4
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -2,12 +2,12 @@ GEM
|
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
4
|
abstract (1.0.0)
|
5
|
-
actionmailer (3.0.
|
6
|
-
actionpack (= 3.0.
|
5
|
+
actionmailer (3.0.1)
|
6
|
+
actionpack (= 3.0.1)
|
7
7
|
mail (~> 2.2.5)
|
8
|
-
actionpack (3.0.
|
9
|
-
activemodel (= 3.0.
|
10
|
-
activesupport (= 3.0.
|
8
|
+
actionpack (3.0.1)
|
9
|
+
activemodel (= 3.0.1)
|
10
|
+
activesupport (= 3.0.1)
|
11
11
|
builder (~> 2.1.2)
|
12
12
|
erubis (~> 2.6.6)
|
13
13
|
i18n (~> 0.4.1)
|
@@ -15,19 +15,19 @@ GEM
|
|
15
15
|
rack-mount (~> 0.6.12)
|
16
16
|
rack-test (~> 0.5.4)
|
17
17
|
tzinfo (~> 0.3.23)
|
18
|
-
activemodel (3.0.
|
19
|
-
activesupport (= 3.0.
|
18
|
+
activemodel (3.0.1)
|
19
|
+
activesupport (= 3.0.1)
|
20
20
|
builder (~> 2.1.2)
|
21
21
|
i18n (~> 0.4.1)
|
22
|
-
activerecord (3.0.
|
23
|
-
activemodel (= 3.0.
|
24
|
-
activesupport (= 3.0.
|
22
|
+
activerecord (3.0.1)
|
23
|
+
activemodel (= 3.0.1)
|
24
|
+
activesupport (= 3.0.1)
|
25
25
|
arel (~> 1.0.0)
|
26
26
|
tzinfo (~> 0.3.23)
|
27
|
-
activeresource (3.0.
|
28
|
-
activemodel (= 3.0.
|
29
|
-
activesupport (= 3.0.
|
30
|
-
activesupport (3.0.
|
27
|
+
activeresource (3.0.1)
|
28
|
+
activemodel (= 3.0.1)
|
29
|
+
activesupport (= 3.0.1)
|
30
|
+
activesupport (3.0.1)
|
31
31
|
arel (1.0.1)
|
32
32
|
activesupport (~> 3.0.0)
|
33
33
|
builder (2.1.2)
|
@@ -59,17 +59,17 @@ GEM
|
|
59
59
|
rack (>= 1.0.0)
|
60
60
|
rack-test (0.5.6)
|
61
61
|
rack (>= 1.0)
|
62
|
-
rails (3.0.
|
63
|
-
actionmailer (= 3.0.
|
64
|
-
actionpack (= 3.0.
|
65
|
-
activerecord (= 3.0.
|
66
|
-
activeresource (= 3.0.
|
67
|
-
activesupport (= 3.0.
|
62
|
+
rails (3.0.1)
|
63
|
+
actionmailer (= 3.0.1)
|
64
|
+
actionpack (= 3.0.1)
|
65
|
+
activerecord (= 3.0.1)
|
66
|
+
activeresource (= 3.0.1)
|
67
|
+
activesupport (= 3.0.1)
|
68
68
|
bundler (~> 1.0.0)
|
69
|
-
railties (= 3.0.
|
70
|
-
railties (3.0.
|
71
|
-
actionpack (= 3.0.
|
72
|
-
activesupport (= 3.0.
|
69
|
+
railties (= 3.0.1)
|
70
|
+
railties (3.0.1)
|
71
|
+
actionpack (= 3.0.1)
|
72
|
+
activesupport (= 3.0.1)
|
73
73
|
rake (>= 0.8.4)
|
74
74
|
thor (~> 0.14.0)
|
75
75
|
rake (0.8.7)
|
@@ -100,7 +100,7 @@ DEPENDENCIES
|
|
100
100
|
jeweler
|
101
101
|
mysql
|
102
102
|
pg
|
103
|
-
rails (= 3.0.
|
103
|
+
rails (= 3.0.1)
|
104
104
|
rcov
|
105
105
|
rspec (= 2.0.0)
|
106
106
|
sqlite3-ruby
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.18
|
@@ -21,14 +21,19 @@ module ActiveRecord
|
|
21
21
|
field_definitions = CustomAttributeDefinitionHelper.new field_types
|
22
22
|
yield field_definitions if block_given?
|
23
23
|
defined_custom_attributes = field_definitions.defined_attributes
|
24
|
+
defined_custom_validations = field_definitions.defined_validations
|
24
25
|
|
25
26
|
if has_custom_attributes?
|
26
27
|
write_inheritable_attribute(:defined_custom_attributes, self.defined_custom_attributes.deep_merge(defined_custom_attributes))
|
28
|
+
write_inheritable_attribute(:defined_custom_validations, self.defined_custom_validations.deep_merge(defined_custom_validations))
|
27
29
|
write_inheritable_attribute(:defined_custom_field_types, field_types)
|
28
30
|
else
|
29
31
|
write_inheritable_attribute(:defined_custom_attributes, defined_custom_attributes)
|
30
32
|
class_inheritable_reader(:defined_custom_attributes)
|
31
33
|
|
34
|
+
write_inheritable_attribute(:defined_custom_validations, defined_custom_validations)
|
35
|
+
class_inheritable_reader(:defined_custom_validations)
|
36
|
+
|
32
37
|
write_inheritable_attribute(:defined_custom_field_types, extra_field_types)
|
33
38
|
class_inheritable_reader(:defined_custom_field_types)
|
34
39
|
|
@@ -48,6 +53,7 @@ module ActiveRecord
|
|
48
53
|
|
49
54
|
def initialize extra_field_types
|
50
55
|
@defined_attributes = {}
|
56
|
+
@defined_validations = {}
|
51
57
|
|
52
58
|
extra_field_types.each do |key, value|
|
53
59
|
class_eval do
|
@@ -64,12 +70,14 @@ module ActiveRecord
|
|
64
70
|
end
|
65
71
|
end
|
66
72
|
|
67
|
-
attr_reader :defined_attributes
|
73
|
+
attr_reader :defined_attributes, :defined_validations
|
68
74
|
|
69
75
|
private
|
70
76
|
|
71
77
|
def define_field(type, *args)
|
72
78
|
options = args.extract_options!
|
79
|
+
options.assert_valid_keys(:on_model, :validate_with, :validate_all_with)
|
80
|
+
|
73
81
|
attributes_on_model = {}
|
74
82
|
if options[:on_model].is_a? Array
|
75
83
|
options[:on_model].each do |attribute|
|
@@ -78,13 +86,18 @@ module ActiveRecord
|
|
78
86
|
elsif options[:on_model].is_a? Hash
|
79
87
|
attributes_on_model = options[:on_model]
|
80
88
|
end
|
89
|
+
if options[:validate_all_with]
|
90
|
+
@defined_validations[type] = options[:validate_all_with]
|
91
|
+
end
|
92
|
+
|
81
93
|
args.each do |field|
|
82
94
|
field = field.to_sym
|
83
95
|
@defined_attributes[type] ||= {}
|
84
96
|
@defined_attributes[type][field] = {
|
85
97
|
:type => type,
|
86
98
|
:name => field,
|
87
|
-
:on_model => attributes_on_model[field] || false
|
99
|
+
:on_model => attributes_on_model[field] || false,
|
100
|
+
:validate_with => options[:validate_with] || nil
|
88
101
|
}
|
89
102
|
end
|
90
103
|
end
|
@@ -101,6 +114,7 @@ module ActiveRecord
|
|
101
114
|
|
102
115
|
base.before_save :cache_custom_attributes
|
103
116
|
base.after_save :save_custom_attributes
|
117
|
+
base.validate :validate_custom_attributes
|
104
118
|
end
|
105
119
|
|
106
120
|
module ClassMethods
|
@@ -126,6 +140,11 @@ module ActiveRecord
|
|
126
140
|
def save_custom_attributes
|
127
141
|
custom_attributes.save
|
128
142
|
end
|
143
|
+
|
144
|
+
def validate_custom_attributes
|
145
|
+
custom_attributes.validate(errors)
|
146
|
+
end
|
147
|
+
|
129
148
|
end
|
130
149
|
|
131
150
|
end
|
@@ -5,6 +5,7 @@ class ActiveRecord::CustomAttributes::CustomAttribute
|
|
5
5
|
@item_list = item_list
|
6
6
|
@attribute_model = attribute_model
|
7
7
|
@marked_for_destruction = false
|
8
|
+
@errors = ActiveModel::Errors.new(self)
|
8
9
|
load if @attribute_model
|
9
10
|
end
|
10
11
|
|
@@ -30,23 +31,34 @@ class ActiveRecord::CustomAttributes::CustomAttribute
|
|
30
31
|
@marked_for_destruction
|
31
32
|
end
|
32
33
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
attribute_model.
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
def validate
|
35
|
+
errors.clear
|
36
|
+
return if marked_for_destruction?
|
37
|
+
assign_model_value
|
38
|
+
unless attribute_model.valid?
|
39
|
+
attribute_model.errors.each do |attribute, message|
|
40
|
+
errors.add :value, message
|
41
|
+
end
|
42
|
+
end
|
43
|
+
validations = item_list.get_custom_validations_for type, internal_label
|
44
|
+
validations.each do |validator|
|
45
|
+
main_model.send(validator, self) if validator.is_a? Symbol
|
46
|
+
validator.call(self) if validator.is_a? Proc
|
47
|
+
end
|
48
|
+
end
|
41
49
|
|
42
|
-
|
43
|
-
|
50
|
+
def valid?
|
51
|
+
errors.empty?
|
52
|
+
end
|
44
53
|
|
45
|
-
|
46
|
-
attribute_model.
|
54
|
+
def save
|
55
|
+
attribute_model.destroy and return if marked_for_destruction?
|
56
|
+
assign_model_value
|
47
57
|
attribute_model.save
|
48
58
|
end
|
49
59
|
|
60
|
+
attr_reader :errors
|
61
|
+
|
50
62
|
private
|
51
63
|
|
52
64
|
attr_reader :main_model, :item_list
|
@@ -62,6 +74,20 @@ class ActiveRecord::CustomAttributes::CustomAttribute
|
|
62
74
|
:time => :date_time
|
63
75
|
}
|
64
76
|
|
77
|
+
def assign_model_value
|
78
|
+
attribute_model.value_type = type.to_s
|
79
|
+
attribute_model.field_name = internal_label.to_s
|
80
|
+
attribute_model.field_label = label
|
81
|
+
write_value = item_list.supported_attribute_types[type]
|
82
|
+
field = FIELD_MAPPING[write_value]
|
83
|
+
|
84
|
+
converted_value = value
|
85
|
+
converted_value = value ? 1 : 0 if write_value == :boolean
|
86
|
+
|
87
|
+
([:text, :date_time, :number, :float] - [field]).each { |value_field| attribute_model.send("#{value_field}_value=", nil) }
|
88
|
+
attribute_model.send("#{field}_value=", converted_value)
|
89
|
+
end
|
90
|
+
|
65
91
|
def load
|
66
92
|
self.type = attribute_model.value_type.to_sym
|
67
93
|
self.internal_label = attribute_model.field_name.to_sym
|
@@ -1,8 +1,9 @@
|
|
1
1
|
class ActiveRecord::CustomAttributes::CustomAttributeList
|
2
2
|
|
3
3
|
def initialize(record)
|
4
|
-
@record
|
5
|
-
@defined_attributes
|
4
|
+
@record = record
|
5
|
+
@defined_attributes = @record.class.defined_custom_attributes
|
6
|
+
@defined_validations = @record.class.defined_custom_validations
|
6
7
|
@extra_attribute_types = @record.class.defined_custom_field_types
|
7
8
|
define_attribute_methods
|
8
9
|
end
|
@@ -21,10 +22,10 @@ class ActiveRecord::CustomAttributes::CustomAttributeList
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def add(type, label, value)
|
24
|
-
type
|
25
|
+
type = type.to_sym
|
25
26
|
return if label.blank? and value.respond_to? :blank? and value.blank?
|
26
|
-
internal_label
|
27
|
-
attribute
|
27
|
+
internal_label = convert_to_internal_label(type, label)
|
28
|
+
attribute = get_attribute(type, internal_label || label, true)
|
28
29
|
attribute.value = value
|
29
30
|
end
|
30
31
|
|
@@ -46,6 +47,21 @@ class ActiveRecord::CustomAttributes::CustomAttributeList
|
|
46
47
|
loaded_attributes.each(&:save)
|
47
48
|
end
|
48
49
|
|
50
|
+
def validate(errors)
|
51
|
+
loaded_attributes.each do |a|
|
52
|
+
a.validate
|
53
|
+
unless a.valid?
|
54
|
+
a.errors.each do |attribute, error_message|
|
55
|
+
errors.add(:custom_attributes, error_message)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_custom_validations_for(type, name)
|
62
|
+
[defined_validations[type], defined_attributes[type][name][:validate_with]].compact
|
63
|
+
end
|
64
|
+
|
49
65
|
def defined_attribute_types
|
50
66
|
(extra_attribute_types.keys + defined_attributes.keys).uniq
|
51
67
|
end
|
@@ -60,14 +76,14 @@ class ActiveRecord::CustomAttributes::CustomAttributeList
|
|
60
76
|
|
61
77
|
def supported_attribute_types
|
62
78
|
return @supported_attribute_types if @supported_attribute_types
|
63
|
-
standard_attribute_types
|
79
|
+
standard_attribute_types = {}
|
64
80
|
ActiveRecord::CustomAttributes::CUSTOM_ATTRIBUTE_TYPES.each { |t| standard_attribute_types[t.to_sym] = t.to_sym }
|
65
81
|
@supported_attribute_types = (standard_attribute_types.merge extra_attribute_types)
|
66
82
|
end
|
67
83
|
|
68
84
|
def rename_label_of attribute, new_name
|
69
|
-
internal_label
|
70
|
-
attribute.label
|
85
|
+
internal_label = convert_to_internal_label(attribute.type, new_name)
|
86
|
+
attribute.label = new_name
|
71
87
|
attribute.internal_label = internal_label
|
72
88
|
end
|
73
89
|
|
@@ -77,26 +93,26 @@ class ActiveRecord::CustomAttributes::CustomAttributeList
|
|
77
93
|
|
78
94
|
private
|
79
95
|
|
80
|
-
attr_reader :defined_attributes, :extra_attribute_types, :record
|
96
|
+
attr_reader :defined_attributes, :extra_attribute_types, :defined_validations, :record
|
81
97
|
|
82
98
|
def get_attribute(type, internal_label, auto_create = false)
|
83
99
|
if internal_label.is_a? Symbol
|
84
|
-
attribute = loaded_attributes.find { |a| a.type == type and a.internal_label.to_s == internal_label.to_s
|
100
|
+
attribute = loaded_attributes.find { |a| a.type == type and a.internal_label.to_s == internal_label.to_s }
|
85
101
|
else
|
86
102
|
attribute = loaded_attributes.find { |a| a.type == type and a.label == internal_label }
|
87
103
|
end
|
88
104
|
return attribute if attribute
|
89
105
|
return nil unless auto_create
|
90
106
|
|
91
|
-
new_attribute
|
107
|
+
new_attribute = ActiveRecord::CustomAttributes::CustomAttribute.new(self, record, nil)
|
92
108
|
new_attribute.type = type.to_sym
|
93
109
|
|
94
110
|
if internal_label.is_a? Symbol
|
95
111
|
new_attribute.internal_label = internal_label
|
96
|
-
new_attribute.label
|
112
|
+
new_attribute.label = human_label_for(type, internal_label)
|
97
113
|
else
|
98
114
|
new_attribute.internal_label = convert_to_internal_label(type, internal_label)
|
99
|
-
new_attribute.label
|
115
|
+
new_attribute.label = internal_label
|
100
116
|
end
|
101
117
|
|
102
118
|
loaded_attributes << new_attribute
|
@@ -112,7 +128,7 @@ class ActiveRecord::CustomAttributes::CustomAttributeList
|
|
112
128
|
|
113
129
|
def human_label_for(type, internal_name)
|
114
130
|
translate_scope = [:activerecord, :custom_attributes, record.class.name.underscore.to_sym, type.to_sym]
|
115
|
-
defaults
|
131
|
+
defaults = [internal_name.to_s.underscore.gsub("_", " ").capitalize]
|
116
132
|
I18n.t(internal_name, :scope => translate_scope, :default => defaults)
|
117
133
|
end
|
118
134
|
|
@@ -2,4 +2,12 @@ class ActiveRecord::CustomAttributes::CustomAttributeModel < ActiveRecord::Base
|
|
2
2
|
set_table_name "custom_attributes"
|
3
3
|
|
4
4
|
belongs_to :item, :polymorphic => true
|
5
|
+
validates :date_time_value, :presence => { :if => :date_storage? }
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def date_storage?
|
10
|
+
["date_time", "date", "time"].include? value_type
|
11
|
+
end
|
12
|
+
|
5
13
|
end
|
Binary file
|
@@ -1,19 +1,13 @@
|
|
1
1
|
require File.expand_path('../../spec_helper', __FILE__)
|
2
2
|
|
3
3
|
describe "Model without custom attributes" do
|
4
|
-
|
5
4
|
subject { Location }
|
6
|
-
|
7
5
|
it { should_not have_custom_attributes }
|
8
|
-
|
9
6
|
end
|
10
7
|
|
11
8
|
describe "Model with custom attributes" do
|
12
|
-
|
13
9
|
subject { Person }
|
14
|
-
|
15
10
|
it { should have_custom_attributes }
|
16
|
-
|
17
11
|
end
|
18
12
|
|
19
13
|
describe "Custom attributes of a person" do
|
@@ -21,11 +15,12 @@ describe "Custom attributes of a person" do
|
|
21
15
|
clean_database!
|
22
16
|
|
23
17
|
I18n.backend.store_translations :'nl', {
|
24
|
-
:activerecord => {:custom_attributes => {:person => {:telephone => {:private => "Prive"}}}}
|
18
|
+
:activerecord => {:custom_attributes => {:person => {:telephone => {:private => "Prive"}}}},
|
19
|
+
:date => {:formats => {:default => "%d-%m-%Y"}}
|
25
20
|
}
|
26
21
|
I18n.default_locale = 'nl'
|
27
22
|
|
28
|
-
@person
|
23
|
+
@person = Person.new
|
29
24
|
end
|
30
25
|
|
31
26
|
subject { @person.custom_attributes }
|
@@ -51,7 +46,7 @@ describe "Custom attributes of a person" do
|
|
51
46
|
@person.save
|
52
47
|
|
53
48
|
loaded_person = Person.find @person.id
|
54
|
-
fields
|
49
|
+
fields = loaded_person.custom_attributes.telephone_attributes
|
55
50
|
fields.should have(1).item
|
56
51
|
fields[0].value.should == "06 28 61 06 28"
|
57
52
|
end
|
@@ -86,7 +81,7 @@ describe "Custom attributes of a person" do
|
|
86
81
|
it "should mark attributes for deletion" do
|
87
82
|
@person.custom_attributes.add_telephone "Prive", "06 28 61 06 28"
|
88
83
|
|
89
|
-
fields
|
84
|
+
fields = @person.custom_attributes.telephone_attributes
|
90
85
|
fields.should have(1).item
|
91
86
|
fields[0].mark_for_destruction
|
92
87
|
|
@@ -100,7 +95,7 @@ describe "Custom attributes of a person" do
|
|
100
95
|
it "should accept post data in an custom_attributes hash" do
|
101
96
|
# field format is #{@object.class.model_name.underscore}[custom_attributes][#{attribute_type}][#{field_type}][]
|
102
97
|
|
103
|
-
custom_attribute_post_data
|
98
|
+
custom_attribute_post_data = {
|
104
99
|
"telephone" => {
|
105
100
|
"0" => {
|
106
101
|
"label" => "Prive",
|
@@ -111,7 +106,7 @@ describe "Custom attributes of a person" do
|
|
111
106
|
"value" => "1234567890"
|
112
107
|
}
|
113
108
|
},
|
114
|
-
"email"
|
109
|
+
"email" => {
|
115
110
|
"0" => {
|
116
111
|
"label" => "Prive",
|
117
112
|
"value" => "matthijs.groen@gmail.com"
|
@@ -119,9 +114,9 @@ describe "Custom attributes of a person" do
|
|
119
114
|
}
|
120
115
|
}
|
121
116
|
|
122
|
-
@person.custom_attributes
|
117
|
+
@person.custom_attributes = custom_attribute_post_data
|
123
118
|
|
124
|
-
fields
|
119
|
+
fields = @person.custom_attributes.telephone_attributes
|
125
120
|
fields.should have(2).items
|
126
121
|
fields[0].value.should == "06 28 61 06 28"
|
127
122
|
fields[1].value.should == "1234567890"
|
@@ -130,31 +125,63 @@ describe "Custom attributes of a person" do
|
|
130
125
|
custom_attribute_second_post_data = {
|
131
126
|
"telephone" => {
|
132
127
|
"0" => {
|
133
|
-
"label"
|
134
|
-
"value"
|
128
|
+
"label" => "Prive",
|
129
|
+
"value" => "06 28 61 06 28",
|
135
130
|
"_destroy" => true
|
136
131
|
},
|
137
132
|
"1" => {
|
138
|
-
"label"
|
139
|
-
"value"
|
133
|
+
"label" => "Werk",
|
134
|
+
"value" => "1234567890",
|
140
135
|
"_destroy" => "false"
|
141
136
|
}
|
142
137
|
},
|
143
|
-
"email"
|
138
|
+
"email" => {
|
144
139
|
"0" => {
|
145
140
|
"label" => "Prive",
|
146
141
|
"value" => "matthijs.groen@gmail.com"
|
147
142
|
}
|
148
143
|
}
|
149
144
|
}
|
150
|
-
@person.custom_attributes
|
145
|
+
@person.custom_attributes = custom_attribute_second_post_data
|
151
146
|
|
152
|
-
fields
|
147
|
+
fields = @person.custom_attributes.telephone_attributes
|
153
148
|
fields.should have(1).items
|
154
149
|
fields[0].value.should == "1234567890"
|
155
150
|
|
156
151
|
end
|
157
152
|
|
153
|
+
it "should invalidate incorrect values" do
|
154
|
+
custom_attribute_invalid_post_data = {
|
155
|
+
"date" => {
|
156
|
+
"0" => {
|
157
|
+
"label" => "Born on",
|
158
|
+
"value" => "23422stufferror"
|
159
|
+
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}
|
163
|
+
@person.custom_attributes = custom_attribute_invalid_post_data
|
164
|
+
@person.should_not be_valid
|
165
|
+
|
166
|
+
date_attributes = @person.custom_attributes.date_attributes
|
167
|
+
date_attributes.should have(1).items
|
168
|
+
date_attributes[0].should_not be_valid
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should validate correct values" do
|
172
|
+
custom_attribute_valid_post_data = {
|
173
|
+
"date" => {
|
174
|
+
"0" => {
|
175
|
+
"label" => "Born on",
|
176
|
+
"value" => "31-05-1981"
|
177
|
+
|
178
|
+
}
|
179
|
+
}
|
180
|
+
}
|
181
|
+
@person.custom_attributes = custom_attribute_valid_post_data
|
182
|
+
@person.should be_valid
|
183
|
+
end
|
184
|
+
|
158
185
|
end
|
159
186
|
|
160
187
|
describe "Custom attributes of a product" do
|
@@ -199,4 +226,19 @@ describe "Custom attributes of a product" do
|
|
199
226
|
@product.custom_attributes.size_value_of(:width).should == nil
|
200
227
|
end
|
201
228
|
|
229
|
+
it "should run custom validations as method" do
|
230
|
+
@product.custom_attributes.add_size "Width", 16.3 # too large
|
231
|
+
@product.should_not be_valid
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should run custom validations as lambda (value incorrect)" do
|
235
|
+
@product.custom_attributes.add_date "In stock since", Date.civil(2009, 12, 31)
|
236
|
+
@product.should_not be_valid
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should run custom validations as lambda (value correct)" do
|
240
|
+
@product.custom_attributes.add_date "In stock since", Date.civil(2010, 1, 1)
|
241
|
+
@product.should be_valid
|
242
|
+
end
|
243
|
+
|
202
244
|
end
|
data/spec/models.rb
CHANGED
@@ -3,7 +3,11 @@ class Person < ActiveRecord::Base
|
|
3
3
|
has_custom_attributes :telephone => :string, :email => :string do |fields|
|
4
4
|
fields.telephone :work, :private, :mobile, :fax
|
5
5
|
fields.email :work, :private
|
6
|
-
fields.date :born_on, :wed_on, :died_on, :on_model => [
|
6
|
+
fields.date :born_on, :wed_on, :died_on, :on_model => [:born_on]
|
7
|
+
end
|
8
|
+
|
9
|
+
def attribute_email(errors)
|
10
|
+
|
7
11
|
end
|
8
12
|
|
9
13
|
end
|
@@ -14,7 +18,13 @@ class Product < ActiveRecord::Base
|
|
14
18
|
|
15
19
|
has_custom_attributes :size => :float do |fields|
|
16
20
|
fields.size :width, :height, :depth
|
17
|
-
fields.
|
21
|
+
fields.size :validate_all_with => :attribute_size_validation
|
22
|
+
fields.url :details, :on_model => {:details => :details_url}
|
23
|
+
fields.date :in_stock_since, :validate_with => lambda { |attribute| attribute.errors.add(:value, "must be after 2010") if attribute.value.to_date.year < 2010 }
|
24
|
+
end
|
25
|
+
|
26
|
+
def attribute_size_validation(attribute)
|
27
|
+
attribute.errors.add(:value, "should be between 1 and 10") if attribute.value < 1 or attribute.value > 10
|
18
28
|
end
|
19
29
|
|
20
30
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: custom-attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 51
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 18
|
10
|
+
version: 0.2.18
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matthijs Groen
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-27 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -45,6 +45,7 @@ files:
|
|
45
45
|
- lib/generators/custom_attributes/migration/migration_generator.rb
|
46
46
|
- lib/generators/custom_attributes/migration/templates/active_record/migration.rb
|
47
47
|
- rails/init.rb
|
48
|
+
- spec/custom_attributes/custom_attributes.sqlite3
|
48
49
|
- spec/custom_attributes/has_custom_attributes_spec.rb
|
49
50
|
- spec/database.yml
|
50
51
|
- spec/database.yml.sample
|