mongoid_nested_fields 0.1.1 → 0.1.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.
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"