custom-attributes 0.2.17 → 0.2.18
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.
- 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
|