custom_fields 1.0.0.beta.25 → 1.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -25,31 +25,33 @@ module CustomFields
25
25
  field :required, :type => Boolean, :default => false
26
26
 
27
27
  ## validations ##
28
- validates_presence_of :label, :kind
29
- validates_exclusion_of :_alias, :in => Module.new {
30
- def self.include?(el); CustomFields.options[:reserved_aliases].include?(el); end
31
- }
32
- validates_format_of :_alias, :with => /^[a-z]([A-Za-z0-9_]+)?$/
33
- validate :uniqueness_of_label_and_alias
28
+ validates_presence_of :label, :kind
29
+ validates_exclusion_of :_alias, :in => lambda { |f| CustomFields.options[:reserved_aliases].map(&:to_s) }
30
+ validates_format_of :_alias, :with => /^[a-z]([A-Za-z0-9_]+)?$/
31
+ validate :uniqueness_of_label_and_alias
34
32
 
35
33
  ## other accessors ##
36
- attr_accessor :association_name # missing in 2.0.0 rc 7
37
-
38
34
  attr_accessor :parentized_done # for performance purpose
39
35
 
40
36
  ## callbacks ##
41
37
  before_validation :set_alias
42
- after_validation :set_target_klass_flag
43
-
44
- before_save :invalidate_target_klass
45
- after_destroy :invalidate_target_klass
38
+ before_save :invalidate_proxy_klass
46
39
 
47
40
  ## methods ##
48
41
 
42
+ # Returns the type class related to this field
43
+ #
44
+ # @return [ Class ] The class defining the field type
45
+ #
49
46
  def field_type
50
47
  self.class.field_types[self.safe_kind.to_sym]
51
48
  end
52
49
 
50
+ # Enhance a document class by applying to it the information stored
51
+ # in the type related to this field
52
+ #
53
+ # @param [ Class ] klass The document class
54
+ #
53
55
  def apply(klass)
54
56
  klass.field self._name, :type => self.field_type if self.field_type
55
57
 
@@ -70,33 +72,75 @@ module CustomFields
70
72
  end
71
73
  end
72
74
 
75
+ # Make sure it returns a valid alias
76
+ #
77
+ # @return [ String ] the alias
78
+ #
73
79
  def safe_alias
74
80
  self.set_alias
75
81
  self._alias
76
82
  end
77
83
 
84
+ # Returns the kind (or type) of the current field.
85
+ # Because of compatibility purpose, prior version of CustomFields used to have the value of kind in uppercase.
86
+ #
87
+ # @return [ String ] the kind
88
+ #
78
89
  def safe_kind
79
- self.kind.downcase # for compatibility purpose: prior version of CustomFields used to have the value of kind in uppercase.
80
- end
81
-
82
- def write_attributes_with_invalidation(attrs = nil)
83
- klass = self._parent.send(:"fetch_#{singular_target_name}_klass")
84
-
85
- write_attributes_without_invalidation(attrs)
86
-
87
- klass.apply_custom_field(self)
90
+ self.kind.downcase
91
+ end
92
+
93
+ # Returns the name of the relation binding this field and the custom_fields in the parent class
94
+ #
95
+ # @example:
96
+ # class Company
97
+ # embeds_many :employees
98
+ # custom_fields_for :employees
99
+ # end
100
+ #
101
+ # field = company.employees_custom_fields.build :label => 'His/her position', :_alias => 'position', :kind => 'string'
102
+ # field.custom_fields_relation_name == 'employees'
103
+ #
104
+ # @return [ String ] the relation's name
105
+ #
106
+ def custom_fields_relation_name
107
+ self.metadata.name.to_s.gsub('_custom_fields', '')
108
+ end
109
+
110
+ # Checks if the field is valid without running the callback which marks
111
+ # the proxy class as invalidated
112
+ #
113
+ # @return [ Boolean ] true if the field has no errors, false otherwise
114
+ def quick_valid?
115
+ # true
116
+ # CustomFields::Field.without_callback(:validation, :after, :invalidate_proxy_klass) do
117
+ CustomFields::Field.without_callback(:save, :before, :invalidate_proxy_klass) do
118
+ self.valid?
119
+ end
88
120
  end
89
121
 
90
- alias_method_chain :write_attributes, :invalidation
91
-
92
- def singular_target_name
93
- if self.association_name.to_s == '_metadata_custom_fields'
94
- 'metadata'
95
- else
96
- self.association_name.to_s.gsub('_custom_fields', '').singularize
122
+ # Destroys a field and saves the parent too in order to keep track of the changes
123
+ # for the parent (for instance, the version has to be bumped).
124
+ #
125
+ # @param [ Hash ] options Options to pass to destroy.
126
+ #
127
+ # @return [ true, false ] True if successful, false if not.
128
+ #
129
+ def destroy(options = {})
130
+ super.tap do
131
+ self.mark_proxy_klass_flag_as_invalidated
132
+ self._parent.save
97
133
  end
98
134
  end
99
135
 
136
+ # Collects all the important attributes of this field.
137
+ # It also accepts an extra hash which will be merged with
138
+ # the one built by this method (by default, this is an empty hash)
139
+ #
140
+ # @param [ Hash ] more The extra hash
141
+ #
142
+ # @return [ Hash ] the hash
143
+ #
100
144
  def to_hash(more = {})
101
145
  self.fields.keys.inject({}) do |memo, meth|
102
146
  memo[meth] = self.send(meth.to_sym); memo
@@ -114,6 +158,10 @@ module CustomFields
114
158
  }).merge(more)
115
159
  end
116
160
 
161
+ # Overides the default behaviour of the to_json method by using the to_hash method
162
+ #
163
+ # @return [ String ] the json object
164
+ #
117
165
  def to_json
118
166
  ActiveSupport::JSON.encode(self.to_hash)
119
167
  end
@@ -143,48 +191,36 @@ module CustomFields
143
191
  end
144
192
 
145
193
  def increment_counter!
146
- next_value = (self._parent.send(:"#{self.association_name}_counter") || 0) + 1
147
- self._parent.send(:"#{self.association_name}_counter=", next_value)
148
- next_value
194
+ name = self.custom_fields_relation_name
195
+ self._parent.bump_custom_fields_counter(name)
149
196
  end
150
197
 
151
198
  def siblings
152
- self._parent.send(self.association_name)
199
+ self._parent.send(self.metadata.name)
153
200
  end
154
201
 
155
202
  def parentize_with_custom_fields(object)
156
203
  return if self.parentized_done
157
204
 
158
- object_name = object.class.to_s.underscore
159
-
160
- self.association_name = self.metadata ? self.metadata.name : self.relations[object_name].inverse_of
161
-
162
205
  parentize_without_custom_fields(object)
163
206
 
164
207
  self.send(:set_unique_name!)
165
208
 
166
209
  self.parentized_done = true
167
210
  end
168
-
169
211
  alias_method_chain :parentize, :custom_fields
170
212
 
171
- def invalidate_target_klass
172
- # puts "[field/#{self.label}] invalidate_target_klass" # for debug purpose
173
- if self._parent.instance_variable_get(:@_writing_attributes_with_custom_fields)
174
- if self.destroyed? # force the parent to invalidate the related target class
175
- self.set_target_klass_flag
176
- elsif self.changed?
177
- self.set_target_klass_flag
178
- end
179
- else
180
- self.set_target_klass_flag
181
- self._parent.save
213
+ def invalidate_proxy_klass
214
+ # puts "#{self._name} / #{self._alias} _ invalidate_proxy_klass !!! #{self.flagged_for_destroy?} / #{self.destroyed?}"
215
+ if self.changed? || self.flagged_for_destroy?
216
+ self.mark_proxy_klass_flag_as_invalidated
182
217
  end
183
218
  end
184
219
 
185
- def set_target_klass_flag
186
- # puts "[field/set_target_klass_flag/#{self.label}] called" # debug purpose
187
- self._parent.send(:"invalidate_#{self.singular_target_name}_klass_flag=", true)
220
+ def mark_proxy_klass_flag_as_invalidated
221
+ # puts "\t*** [mark_proxy_klass_flag_as_invalidated] called for '#{self._name}'"
222
+ name = self.custom_fields_relation_name
223
+ self._parent.mark_klass_with_custom_fields_as_invalidated(name)
188
224
  end
189
225
 
190
226
  end
@@ -0,0 +1,112 @@
1
+ module CustomFields
2
+ module ProxyClass
3
+
4
+ module Base
5
+
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ cattr_accessor :custom_fields, :_parent, :association_name, :built_at, :version
10
+ end
11
+
12
+ module InstanceMethods
13
+
14
+ # Returns the list of the custom fields used to build this class
15
+ #
16
+ # @return [ List ] the list of custom fields
17
+ #
18
+ def custom_fields
19
+ self.class.custom_fields
20
+ end
21
+
22
+ # Returns the fields specified by the custom fields and their values
23
+ #
24
+ # @return [ Hash ] the hash
25
+ #
26
+ def aliased_attributes
27
+ hash = { :created_at => self.created_at, :updated_at => self.updated_at } rescue {}
28
+
29
+ (self.custom_fields || []).each do |field|
30
+ case field.kind
31
+ when 'file' then hash[field._alias] = self.send(field._name.to_sym).url
32
+ else
33
+ hash[field._alias] = self.send(field._name.to_sym)
34
+ end
35
+ end
36
+
37
+ hash
38
+ end
39
+
40
+ end
41
+
42
+ module ClassMethods
43
+
44
+ # Returns the fields specified by the custom fields and their values
45
+ #
46
+ def model_name
47
+ @_model_name ||= ActiveModel::Name.new(self.superclass)
48
+ end
49
+
50
+ # Declares a field within the class based on the information given by the custom field
51
+ #
52
+ # @param [ Field ] field The custom field
53
+ #
54
+ def apply_custom_field(field)
55
+ # puts "field #{field._name} persisted? #{field.persisted?} / valid ? #{field.quick_valid?}"
56
+ return if !field.persisted? || !field.quick_valid?
57
+
58
+ self.custom_fields ||= []
59
+
60
+ if self.lookup_custom_field(field._name).nil?
61
+ self.custom_fields << field
62
+ field.apply(self)
63
+ end
64
+ end
65
+
66
+ # Determines if the class has already declared the field
67
+ #
68
+ # @param [ String ] name The name of the custom field
69
+ #
70
+ # @return [ true, false ] True if found it, false if not.
71
+ #
72
+ def lookup_custom_field(name)
73
+ self.custom_fields.detect { |f| f._name == name }
74
+ end
75
+
76
+ # Convenient method to get the name of a custom field from its alias
77
+ #
78
+ # @param [ String ] value The _alias value of the custom field
79
+ #
80
+ # @return [ String ] The name of the custom field.
81
+ #
82
+ def custom_field_alias_to_name(value)
83
+ self.custom_fields.detect { |f| f._alias == value }._name
84
+ end
85
+
86
+ # Convenient method to get the _alias of a custom field from its name
87
+ #
88
+ # @param [ String ] value The name value of the custom field
89
+ #
90
+ # @return [ String ] The _alias of the custom field.
91
+ #
92
+ def custom_field_name_to_alias(value)
93
+ self.custom_fields.detect { |f| f._name == value }._alias
94
+ end
95
+
96
+ # Tells Mongoid that this class is a child of a super class (even if it is no true)
97
+ #
98
+ def hereditary?
99
+ false
100
+ end
101
+
102
+ end
103
+
104
+ end
105
+
106
+ end
107
+ end
108
+
109
+
110
+
111
+
112
+
@@ -0,0 +1,60 @@
1
+ module CustomFields
2
+ module ProxyClass
3
+
4
+ module Builder
5
+
6
+ # Returns the proxy class based on the current class and enhanced by the custom fields.
7
+ # If the custom fields have been modified, then a new version
8
+ # of the proxy class is built
9
+ #
10
+ # @param [ String, Symbol ] name The name of the relation in the parent object
11
+ # @param [ Document ] parent The parent document describing the custom fields
12
+ # @param [ List ] fields The list of custom fields
13
+ #
14
+ # @return [ Class ] The proxy class.
15
+ #
16
+ def to_klass_with_custom_fields(name, parent, fields)
17
+ klass = self.klass_with_custom_fields(name, parent)
18
+
19
+ if klass && klass.version != self.klass_version_with_custom_fields(name, parent) # new version ?
20
+ self.invalidate_klass_with_custom_fields(name, parent)
21
+ klass = nil
22
+ end
23
+
24
+ if klass.nil?
25
+ klass = self.build_klass_with_custom_fields(name, parent, fields)
26
+ klass_name = self.klass_name_with_custom_fields(name, parent)
27
+
28
+ Object.const_set(klass_name, klass)
29
+ end
30
+
31
+ klass
32
+ end
33
+
34
+ # Builds the proxy class based on the current class and enhanced by the custom fields.
35
+ #
36
+ # @param [ String, Symbol ] name The name of the relation in the parent object
37
+ # @param [ Document ] parent The parent document describing the custom fields
38
+ # @param [ List ] fields The list of custom fields
39
+ #
40
+ # @return [ Class ] The proxy class.
41
+ #
42
+ def build_klass_with_custom_fields(name, parent, fields)
43
+ # puts "CREATING new '#{name}' klass (#{self.klass_version_with_custom_fields(name, parent)})"
44
+ Class.new(self).tap do |klass|
45
+ klass.send :include, CustomFields::ProxyClass::Base
46
+
47
+ # copy scopes from the parent class (scopes does not inherit automatically from the parents in mongoid)
48
+ klass.write_inheritable_attribute(:scopes, self.scopes)
49
+
50
+ klass.association_name = name.to_sym
51
+ klass._parent = parent
52
+ klass.version = self.klass_version_with_custom_fields(name, parent)
53
+
54
+ [*fields].each { |field| klass.apply_custom_field(field) }
55
+ end
56
+ end
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,57 @@
1
+ module CustomFields
2
+ module ProxyClass
3
+
4
+ module Helper
5
+
6
+ # Gets the name of the proxy class built with the custom fields.
7
+ #
8
+ # @param [ String, Symbol ] name The name of the relation in the parent object
9
+ # @param [ Document ] parent The parent document describing the custom fields
10
+ #
11
+ # @return [ String ] The class name
12
+ #
13
+ def klass_name_with_custom_fields(name, parent)
14
+ "#{name.to_s.gsub(/^_/, '').singularize.camelize}#{parent.class.name.camelize}#{parent._id}"
15
+ end
16
+
17
+ # Returns the current proxy class built with the custom fields.
18
+ #
19
+ # @param [ String, Symbol ] name The name of the relation in the parent object
20
+ # @param [ Document ] parent The parent document describing the custom fields
21
+ #
22
+ # @return [ Class ] The proxy class
23
+ #
24
+ def klass_with_custom_fields(name, parent)
25
+ klass_name = self.klass_name_with_custom_fields(name, parent)
26
+ Object.const_defined?(klass_name) ? Object.const_get(klass_name): nil
27
+ end
28
+
29
+ # Returns the version of the proxy class built with the custom fields.
30
+ #
31
+ # @param [ String, Symbol ] name The name of the relation in the parent object
32
+ # @param [ Document ] parent The parent document describing the custom fields
33
+ #
34
+ # @return [ String ] The class name
35
+ #
36
+ def klass_version_with_custom_fields(name, parent)
37
+ parent.send(:"#{name}_custom_fields_version")
38
+ end
39
+
40
+ # Destroy the class enhanced by the custom fields so that next time we need it,
41
+ # we have a fresh new one.
42
+ #
43
+ # @param [ String, Symbol ] name The name of the relation in the parent object
44
+ # @param [ Document ] parent The parent document describing the custom fields
45
+ #
46
+ def invalidate_klass_with_custom_fields(name, parent)
47
+ klass_name = self.klass_name_with_custom_fields(name, parent)
48
+
49
+ if Object.const_defined?(klass_name)
50
+ Object.send(:remove_const, klass_name)
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+ end
@@ -1,9 +1,10 @@
1
1
  module CustomFields
2
2
 
3
- class Metadata
3
+ class SelfMetadata
4
4
 
5
5
  include ::Mongoid::Document
6
- include CustomFields::ProxyClassEnabler
6
+ extend CustomFields::ProxyClass::Helper
7
+ extend CustomFields::ProxyClass::Builder
7
8
 
8
9
  ## other accessors ##
9
10
  attr_accessor :association_name # missing in 2.0.0 rc
@@ -1,5 +1,4 @@
1
- module Mongoid
2
- module CustomFields
3
- VERSION = "1.0.0.beta.25"
4
- end
1
+ # encoding: utf-8
2
+ module CustomFields #:nodoc
3
+ VERSION = "1.1.0.rc1"
5
4
  end
data/lib/custom_fields.rb CHANGED
@@ -1,12 +1,12 @@
1
1
  $:.unshift File.expand_path(File.dirname(__FILE__))
2
2
 
3
3
  require 'active_support'
4
- require 'carrierwave'
4
+ require 'carrierwave/mongoid'
5
5
 
6
6
  module CustomFields
7
7
 
8
8
  @@options = {
9
- :reserved_aliases => Mongoid.destructive_fields
9
+ :reserved_aliases => Mongoid.destructive_fields + %w(id _id send class)
10
10
  }
11
11
 
12
12
  def self.options=(options)
@@ -20,6 +20,7 @@ module CustomFields
20
20
  end
21
21
 
22
22
  require 'custom_fields/version'
23
+ require 'custom_fields/extensions/active_support'
23
24
  require 'custom_fields/extensions/mongoid/document'
24
25
  require 'custom_fields/extensions/mongoid/relations/accessors'
25
26
  require 'custom_fields/extensions/mongoid/relations/builders'
@@ -34,18 +35,29 @@ require 'custom_fields/types/has_one'
34
35
  require 'custom_fields/types/has_many/proxy_collection'
35
36
  require 'custom_fields/types/has_many/reverse_lookup_proxy_collection'
36
37
  require 'custom_fields/types/has_many'
37
- require 'custom_fields/proxy_class_enabler'
38
+ require 'custom_fields/proxy_class/base'
39
+ require 'custom_fields/proxy_class/builder'
40
+ require 'custom_fields/proxy_class/helper'
38
41
  require 'custom_fields/field'
39
- require 'custom_fields/metadata'
42
+ require 'custom_fields/self_metadata'
40
43
  require 'custom_fields/custom_fields_for'
41
44
 
42
45
  module Mongoid
43
46
  module CustomFields
44
47
  extend ActiveSupport::Concern
45
48
  included do
49
+ extend ::CustomFields::ProxyClass::Helper
46
50
  include ::CustomFields::CustomFieldsFor
47
51
  end
48
52
  end
53
+
54
+ module TargetCustomFields
55
+ extend ActiveSupport::Concern
56
+ included do
57
+ extend ::CustomFields::ProxyClass::Helper
58
+ extend ::CustomFields::ProxyClass::Builder
59
+ end
60
+ end
49
61
  end
50
62
 
51
63
  ActiveSupport::Inflector.inflections do |inflect|
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: custom_fields
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: 6
5
- version: 1.0.0.beta.25
5
+ version: 1.1.0.rc1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Didier Lafforgue
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-08-31 00:00:00 Z
13
+ date: 2011-10-27 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: mongoid
@@ -19,7 +19,7 @@ dependencies:
19
19
  requirements:
20
20
  - - "="
21
21
  - !ruby/object:Gem::Version
22
- version: 2.0.2
22
+ version: 2.3.2
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: *id001
@@ -30,10 +30,87 @@ dependencies:
30
30
  requirements:
31
31
  - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: 3.0.9
33
+ version: 3.1.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: carrierwave-mongoid
39
+ requirement: &id003 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: 0.1.3
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: yard
50
+ requirement: &id004 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: 0.7.3
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: bson_ext
61
+ requirement: &id005 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ~>
65
+ - !ruby/object:Gem::Version
66
+ version: 1.4.1
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *id005
70
+ - !ruby/object:Gem::Dependency
71
+ name: mocha
72
+ requirement: &id006 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.9.12
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: *id006
81
+ - !ruby/object:Gem::Dependency
82
+ name: rspec
83
+ requirement: &id007 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ~>
87
+ - !ruby/object:Gem::Version
88
+ version: "2.6"
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: *id007
92
+ - !ruby/object:Gem::Dependency
93
+ name: database_cleaner
94
+ requirement: &id008 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ~>
98
+ - !ruby/object:Gem::Version
99
+ version: 0.6.7
100
+ type: :development
101
+ prerelease: false
102
+ version_requirements: *id008
103
+ - !ruby/object:Gem::Dependency
104
+ name: RedCloth
105
+ requirement: &id009 !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 4.2.8
111
+ type: :development
112
+ prerelease: false
113
+ version_requirements: *id009
37
114
  description: Manage custom fields to a mongoid document or a collection. This module is one of the core features we implemented in our custom cms named Locomotive.
38
115
  email:
39
116
  - didier@nocoffee.fr
@@ -49,12 +126,15 @@ files:
49
126
  - MIT-LICENSE
50
127
  - README.textile
51
128
  - lib/custom_fields/custom_fields_for.rb
129
+ - lib/custom_fields/extensions/active_support.rb
52
130
  - lib/custom_fields/extensions/mongoid/document.rb
53
131
  - lib/custom_fields/extensions/mongoid/relations/accessors.rb
54
132
  - lib/custom_fields/extensions/mongoid/relations/builders.rb
55
133
  - lib/custom_fields/field.rb
56
- - lib/custom_fields/metadata.rb
57
- - lib/custom_fields/proxy_class_enabler.rb
134
+ - lib/custom_fields/proxy_class/base.rb
135
+ - lib/custom_fields/proxy_class/builder.rb
136
+ - lib/custom_fields/proxy_class/helper.rb
137
+ - lib/custom_fields/self_metadata.rb
58
138
  - lib/custom_fields/types/boolean.rb
59
139
  - lib/custom_fields/types/category.rb
60
140
  - lib/custom_fields/types/date.rb
@@ -85,7 +165,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
165
  requirements:
86
166
  - - ">="
87
167
  - !ruby/object:Gem::Version
88
- hash: -976967473644545936
168
+ hash: 1403562502793807305
89
169
  segments:
90
170
  - 0
91
171
  version: "0"
@@ -98,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
178
  requirements: []
99
179
 
100
180
  rubyforge_project: nowarning
101
- rubygems_version: 1.8.5
181
+ rubygems_version: 1.8.10
102
182
  signing_key:
103
183
  specification_version: 3
104
184
  summary: Custom fields extension for Mongoid