mongoid_nested_fields 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
@@ -6,7 +6,7 @@ module MongoidNestedFields
6
6
  if value.is_a? Array
7
7
  value = value.map do |v|
8
8
  if((v.is_a?(Hash) or v.is_a?(BSON::OrderedHash)) and !v['_type'].nil?)
9
- v = v['_type'].classify.constantize.new(v.to_hash).to_mongo
9
+ v = v['_type'].classify.constantize.new(v.to_hash)
10
10
  end
11
11
  v
12
12
  end
@@ -15,9 +15,6 @@ module MongoidNestedFields
15
15
  end
16
16
 
17
17
  def self.set(value)
18
- if value.is_a? Array
19
- value = value.map{ |v| v.respond_to?(:to_mongo) ? v.to_mongo : v}
20
- end
21
18
  value
22
19
  end
23
20
 
@@ -5,10 +5,14 @@ module MongoidNestedFields
5
5
  module ClassMethods
6
6
 
7
7
  def nested_field(name, options = {})
8
+ options.merge!({:nested => true})
9
+
8
10
  add_nested_field(name)
11
+
9
12
  set_validations
10
- options[:type] = Array
13
+ set_field_options(name, options)
11
14
  set_allowed_types_in_field(name, options.delete(:allowed_types))
15
+
12
16
  define_method("#{name}=") do |value|
13
17
  raise TypeError unless [String, Array].include?(value.class)
14
18
  if value.is_a? String
@@ -30,12 +34,34 @@ module MongoidNestedFields
30
34
 
31
35
  define_method(name) do
32
36
  read_attribute(name).map{ |v| v.respond_to?(:to_mongo) ? v.to_mongo : v }
33
-
37
+ read_attribute(name)
38
+ end
39
+
40
+ end
41
+
42
+ def field(name, options = {})
43
+ add_field(name)
44
+ set_field_options(name, options)
45
+ define_method("#{name}=") do |value|
46
+ klass = options[:type].nil? ? String : options.delete(:type).classify.constantize
47
+ write_attribute(name, klass.new(value))
34
48
  end
35
49
 
50
+ define_method(name) do
51
+ read_attribute(name)
52
+ end
36
53
 
37
54
  end
38
55
 
56
+ def set_field_options(field, options)
57
+ @_field_options ||= {}
58
+ @_field_options[field] = options
59
+ end
60
+
61
+ def field_options
62
+ @_field_options || {}
63
+ end
64
+
39
65
  def set_validations
40
66
  validate :nested_fields_must_be_valid
41
67
  end
@@ -45,31 +71,22 @@ module MongoidNestedFields
45
71
  @_allowed_types_in_field ||= {}
46
72
  @_allowed_types_in_field[field] ||= []
47
73
  @_allowed_types_in_field[field] << type
48
- @_allowed_types_in_field[field].flatten!.uniq!
74
+ @_allowed_types_in_field[field].flatten!
75
+ @_allowed_types_in_field[field].uniq! unless @_allowed_types_in_field[field].nil?
49
76
  end
77
+
50
78
  def allowed_types_in_field(field)
51
79
  field = field.to_sym
52
80
  @_allowed_types_in_field ||= {}
53
81
  return @_allowed_types_in_field[field] || []
54
82
  end
83
+
55
84
  def is_allowed_type?(field, type)
56
85
  field = field.to_sym
57
86
  allowed_types_in_field(field).include?(type)
58
87
  end
59
88
 
60
- def field(name, options = {})
61
- add_field(name)
62
-
63
- define_method("#{name}=") do |value|
64
- klass = options[:type].nil? ? String : options.delete(:type).classify.constantize
65
- write_attribute(name, klass.new(value))
66
- end
67
-
68
- define_method(name) do
69
- read_attribute(name)
70
- end
71
-
72
- end
89
+
73
90
 
74
91
  def add_field(name)
75
92
  @_fields ||= []
@@ -84,8 +101,6 @@ module MongoidNestedFields
84
101
 
85
102
  end
86
103
 
87
-
88
-
89
104
  def self.included(base)
90
105
  base.extend(ClassMethods)
91
106
  base.send(:include, ActiveModel::Validations)
@@ -112,9 +127,16 @@ module MongoidNestedFields
112
127
  @_attributes[name.to_sym] = value
113
128
  end
114
129
 
130
+
115
131
  def read_attribute(name)
116
132
  @_attributes ||= {}
117
- @_attributes[name.to_sym].respond_to?(:to_mongo) ? @_attributes[name.to_sym].to_mongo : @_attributes[name.to_sym]
133
+ fields = self.class.instance_variable_get(:@_fields)
134
+ raise "Field #{name} doesn't exist in #{self.class}" if fields.nil? or !fields.include?(name.to_sym)
135
+ @_attributes[name.to_sym]
136
+ end
137
+
138
+ def [](key)
139
+ read_attribute(key)
118
140
  end
119
141
 
120
142
  def attributes
@@ -124,7 +146,11 @@ module MongoidNestedFields
124
146
  def to_mongo
125
147
  attrs = MongoidNestedFields::NestedFieldHash.new
126
148
  attributes.each_key do |key|
127
- attrs[key.to_s] = self.send(key.to_sym)
149
+ if self.send(key.to_sym).is_a?(Array)
150
+ attrs[key.to_s] = self.send(key.to_sym).map{ |v| v.respond_to?(:to_mongo) ? v.to_mongo : v }
151
+ else
152
+ attrs[key.to_s] = self.send(key.to_sym)
153
+ end
128
154
  end
129
155
  attrs['_type'] = _type
130
156
  attrs.origin = self
@@ -8,8 +8,9 @@ module MongoidNestedFields
8
8
  @_nested_fields << name.to_s
9
9
  options[:type] = MongoidNestedFields::NestedFieldHolder
10
10
 
11
- set_allowed_types_in_field(name, options.delete(:allowed_types))
12
- set_validations
11
+ _set_allowed_types_in_field(name, options.delete(:allowed_types))
12
+ _set_validations
13
+ _set_serialization
13
14
 
14
15
  field(name, options)
15
16
  meth = options.delete(:as) || name
@@ -25,7 +26,7 @@ module MongoidNestedFields
25
26
  if((v.is_a?(Hash) or v.is_a?(BSON::OrderedHash)) and !v['_type'].nil?)
26
27
  v = v['_type'].classify.constantize.new(v.to_hash)
27
28
  end
28
- raise MongoidNestedFields::Errors::UnexpectedType.new(v.class, name) unless self.class.is_allowed_type?(name, v.class)
29
+ raise MongoidNestedFields::Errors::UnexpectedType.new(v.class, name) unless self.class._is_allowed_type?(name, v.class)
29
30
  processed_values << v
30
31
  end
31
32
  write_attribute(name, processed_values)
@@ -33,25 +34,31 @@ module MongoidNestedFields
33
34
 
34
35
  end
35
36
 
36
- def set_validations
37
- validate :nested_fields_must_be_valid
37
+ def _set_serialization
38
+ before_save :_serialize_nested_fields
39
+ after_save :_restore_nested_fields
38
40
  end
39
-
40
- def set_allowed_types_in_field(field, type)
41
+
42
+ def _set_validations
43
+ validate :_nested_fields_must_be_valid
44
+ end
45
+
46
+ def _set_allowed_types_in_field(field, type)
41
47
  field = field.to_sym
42
48
  @_allowed_types_in_field ||= {}
43
49
  @_allowed_types_in_field[field] ||= []
44
50
  @_allowed_types_in_field[field] << type
45
- @_allowed_types_in_field[field].flatten!.uniq!
51
+ @_allowed_types_in_field[field].flatten!
52
+ @_allowed_types_in_field[field].uniq! unless @_allowed_types_in_field[field].nil?
46
53
  end
47
- def allowed_types_in_field(field)
54
+ def _allowed_types_in_field(field)
48
55
  field = field.to_sym
49
56
  @_allowed_types_in_field ||= {}
50
57
  return @_allowed_types_in_field[field] || []
51
58
  end
52
- def is_allowed_type?(field, type)
59
+ def _is_allowed_type?(field, type)
53
60
  field = field.to_sym
54
- allowed_types_in_field(field).include?(type)
61
+ _allowed_types_in_field(field).include?(type)
55
62
  end
56
63
  end
57
64
 
@@ -59,32 +66,49 @@ module MongoidNestedFields
59
66
  reciever::ClassMethods.send :include, ClassMethods
60
67
  end
61
68
 
62
- def _nested_fields
63
- self.class.instance_variable_get(:@_nested_fields)
64
- end
69
+ private
65
70
 
66
- def rebuild_nested_fields
67
- _nested_fields.each do |c|
68
- value = self.send(c)
69
- self.send("#{c}=", value) unless value.nil?
71
+ def _nested_fields
72
+ self.class.instance_variable_get(:@_nested_fields)
73
+ end
74
+
75
+ def _serialize_nested_fields
76
+ _nested_fields.each do |nested_field|
77
+ serialized_nested_field = []
78
+ value = read_attribute(nested_field)
79
+ value.each do |part|
80
+ serialized_nested_field << (part.respond_to?(:to_mongo) ? part.to_mongo : part)
81
+ end unless value.nil?
82
+ write_attribute(nested_field, serialized_nested_field)
83
+ end
84
+ end
85
+
86
+ def _restore_nested_fields
87
+ _nested_fields.each do |nested_field|
88
+ restored_nested_field = []
89
+ value = read_attribute(nested_field)
90
+ value.each do |part|
91
+ restored_nested_field << (part.respond_to?(:origin) ? part.origin : part)
92
+ end unless value.nil?
93
+ write_attribute(nested_field, restored_nested_field)
94
+ end
70
95
  end
71
- end
72
96
 
73
- def nested_fields_must_be_valid
97
+ def _nested_fields_must_be_valid
74
98
 
75
- _nested_fields.each do |field|
76
- value = read_attribute(field)
77
- i = 0
78
- field_errors = {}
79
- value.each do |v|
80
- if v.respond_to?(:origin) and v.origin.respond_to?(:invalid?) and v.origin.invalid?
81
- field_errors[i.to_s] = v.origin.errors
82
- i += 1
83
- end
84
- end if value.respond_to? :each
85
- errors.add(field, field_errors) unless field_errors.empty?
86
- end unless _nested_fields.nil?
87
- end
99
+ _nested_fields.each do |field|
100
+ value = read_attribute(field)
101
+ i = 0
102
+ field_errors = {}
103
+ value.each do |v|
104
+ if v.respond_to?(:invalid?) and v.invalid?
105
+ field_errors[i.to_s] = v.errors
106
+ i += 1
107
+ end
108
+ end if value.respond_to? :each
109
+ errors.add(field, field_errors) unless field_errors.empty?
110
+ end unless _nested_fields.nil?
111
+ end
88
112
 
89
113
  end
90
114
  end
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongoid_nested_fields}
8
- s.version = "0.1.1"
8
+ s.version = "0.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["retro"]
@@ -78,7 +78,7 @@ class TestMongoidNestedFields < Test::Unit::TestCase
78
78
  ]
79
79
  c.save
80
80
 
81
- assert_equal c.image_with_caption.first, {'_type' => 'image_with_caption', 'image' => 'IMAGE', 'caption' => 'CAPTION'}
81
+ assert_equal c.image_with_caption.first.class, ::ImageWithCaption
82
82
  end
83
83
  should "allow of nesting content fields and content field parts" do
84
84
  class ::Image
@@ -107,13 +107,13 @@ class TestMongoidNestedFields < Test::Unit::TestCase
107
107
  ]
108
108
  }]
109
109
 
110
- assert_equal c.gallery, [{
110
+ assert_equal c.gallery.first.to_mongo, {
111
111
  '_type' => 'image_gallery',
112
112
  'gallery_name' => 'Test',
113
113
  'gallery' => [
114
114
  {'_type' => 'image', 'image' => 'IMG'}
115
115
  ]
116
- }]
116
+ }
117
117
 
118
118
  end
119
119
 
@@ -186,10 +186,46 @@ class TestMongoidNestedFields < Test::Unit::TestCase
186
186
 
187
187
  document = ContentItem.first
188
188
 
189
- assert_equal document.paragraph_with_title.first.origin.class, ::ParagraphWithTitle
189
+ assert_equal document.paragraph_with_title.first.class, ::ParagraphWithTitle
190
190
 
191
191
  end
192
192
 
193
+ should "return options for field definitions" do
194
+ class ::ParagraphWithTitle
195
+ include MongoidNestedFields::NestedField
196
+ field :title, :custom_option => 'custom'
197
+ field :paragraph
198
+ nested_field :test_hash, :allowed_types => [Hash]
199
+ end
200
+ field_options = ::ParagraphWithTitle.field_options
201
+ assert_equal field_options, {
202
+ :title => {:custom_option => 'custom'},
203
+ :paragraph => {},
204
+ :test_hash => {:nested => true}
205
+ }
206
+ end
207
+
208
+ should "allow access through []" do
209
+ class ::ParagraphWithTitle
210
+ include MongoidNestedFields::NestedField
211
+ field :title, :custom_option => 'custom'
212
+ field :paragraph
213
+ end
214
+
215
+ p = ParagraphWithTitle.new(:title => 'test')
216
+ assert_equal p['title'], 'test'
217
+ end
218
+
219
+ should_raise do
220
+ class ::ParagraphWithTitle
221
+ include MongoidNestedFields::NestedField
222
+ field :title, :custom_option => 'custom'
223
+ field :paragraph
224
+ end
225
+ p = ParagraphWithTitle.new
226
+ p['non_existing_attr']
227
+ end
228
+
193
229
  end
194
230
  end
195
231
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 1
9
- version: 0.1.1
8
+ - 2
9
+ version: 0.1.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - retro
@@ -218,7 +218,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
218
218
  requirements:
219
219
  - - ">="
220
220
  - !ruby/object:Gem::Version
221
- hash: -4348957618995795359
221
+ hash: -3846493665174645855
222
222
  segments:
223
223
  - 0
224
224
  version: "0"