custom_fields 1.0.0.beta.7 → 1.0.0.beta.8

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.
@@ -55,7 +55,7 @@ module CustomFields
55
55
  class_eval <<-EOV
56
56
  embeds_one :#{collection_name}, :class_name => '::CustomFields::Metadata'
57
57
 
58
- def #{singular_name}
58
+ def safe_#{singular_name}
59
59
  self.#{collection_name} || self.build_#{collection_name}
60
60
  end
61
61
 
@@ -65,16 +65,20 @@ module CustomFields
65
65
  # common part
66
66
  class_eval <<-EOV
67
67
  field :#{singular_name}_custom_fields_counter, :type => Integer, :default => 0
68
+ field :#{singular_name}_custom_fields_version, :type => Integer, :default => 0
68
69
 
69
70
  embeds_many :#{singular_name}_custom_fields, :class_name => '#{dynamic_custom_field_class_name}'
70
71
 
71
- validates_associated :#{singular_name}_custom_fields
72
+ attr_accessor :invalidate_#{singular_name}_klass_flag
72
73
 
73
- after_validation do |record|
74
- if record.errors.empty?
75
- record.invalidate_#{singular_name}_klass
74
+ before_save do |record|
75
+ if record.invalidate_#{singular_name}_klass?
76
+ record.#{singular_name}_custom_fields_version ||= 0
77
+ record.#{singular_name}_custom_fields_version += 1
78
+ # puts "[parent/before_save] set #{singular_name}_custom_fields_version " + record.#{singular_name}_custom_fields_version.to_s # debug purpose
76
79
  end
77
80
  end
81
+
78
82
  after_destroy :invalidate_#{singular_name}_klass
79
83
 
80
84
  accepts_nested_attributes_for :#{singular_name}_custom_fields, :allow_destroy => true
@@ -88,13 +92,26 @@ module CustomFields
88
92
  metadata.klass.to_klass_with_custom_fields(self.ordered_#{singular_name}_custom_fields, self, metadata.name)
89
93
  end
90
94
 
95
+ def #{singular_name}_klass
96
+ metadata = self.relations['#{collection_name.to_s}']
97
+ metadata.klass.current_klass_with_custom_fields(self, metadata.name)
98
+ end
99
+
100
+ def #{singular_name}_klass_out_of_date?
101
+ self.#{singular_name}_klass.nil? || self.#{singular_name}_klass.version != self.#{singular_name}_custom_fields_version
102
+ end
103
+
91
104
  def invalidate_#{singular_name}_klass
92
105
  metadata = self.relations['#{collection_name.to_s}']
93
106
  metadata.klass.invalidate_proxy_class_with_custom_fields(self, metadata.name)
94
107
  end
108
+
109
+ def invalidate_#{singular_name}_klass?
110
+ self.invalidate_#{singular_name}_klass_flag == true
111
+ end
95
112
  EOV
96
113
 
97
- # mongoid tiny patch: for performance optimization (ie: we do want to invalidate klass every time we save a field)
114
+ # mongoid tiny patch: for performance optimization (ie: we do want to invalidate klass with custom fields every time we save a field)
98
115
  unless instance_methods.include?('write_attributes_with_custom_fields')
99
116
  class_eval do
100
117
  def write_attributes_with_custom_fields(attrs = nil)
@@ -34,7 +34,11 @@ module CustomFields
34
34
 
35
35
  ## callbacks ##
36
36
  before_validation :set_alias
37
- after_save :invalidate_klass
37
+ after_validation :set_target_klass_flag, :if => Proc.new { |f| f.changed? }
38
+
39
+ before_create :invalidate_target_klass
40
+ before_update :invalidate_target_klass
41
+ after_destroy :invalidate_target_klass
38
42
 
39
43
  ## methods ##
40
44
 
@@ -69,13 +73,7 @@ module CustomFields
69
73
  end
70
74
 
71
75
  def write_attributes_with_invalidation(attrs = nil)
72
- if self.association_name.to_s == '_metadata_custom_fields'
73
- target_name = 'metadata'
74
- else
75
- target_name = self.association_name.to_s.gsub('_custom_fields', '').pluralize
76
- end
77
-
78
- klass = self._parent.send(:"fetch_#{target_name.singularize}_klass")
76
+ klass = self._parent.send(:"fetch_#{singular_target_name}_klass")
79
77
 
80
78
  write_attributes_without_invalidation(attrs)
81
79
 
@@ -84,6 +82,14 @@ module CustomFields
84
82
 
85
83
  alias_method_chain :write_attributes, :invalidation
86
84
 
85
+ def singular_target_name
86
+ if self.association_name.to_s == '_metadata_custom_fields'
87
+ 'metadata'
88
+ else
89
+ self.association_name.to_s.gsub('_custom_fields', '').singularize
90
+ end
91
+ end
92
+
87
93
  def to_hash(more = {})
88
94
  self.fields.keys.inject({}) do |memo, meth|
89
95
  memo[meth] = self.send(meth.to_sym); memo
@@ -152,11 +158,20 @@ module CustomFields
152
158
 
153
159
  alias_method_chain :parentize, :custom_fields
154
160
 
155
- def invalidate_klass
156
- return if self._parent.instance_variable_get(:@_writing_attributes_with_custom_fields)
161
+ def invalidate_target_klass
162
+ # puts "[field/#{self.label}] invalidate_target_klass" # for debug purpose
163
+ if self._parent.instance_variable_get(:@_writing_attributes_with_custom_fields)
164
+ if self.destroyed? # force the parent to invalidate the related target class
165
+ self.set_target_klass_flag
166
+ end
167
+ else
168
+ self._parent.save
169
+ end
170
+ end
157
171
 
158
- target_name = self.association_name.to_s.gsub('_custom_fields', '')
159
- self._parent.send(:"invalidate_#{target_name}_klass")
172
+ def set_target_klass_flag
173
+ # puts "[field/set_target_klass_flag/#{self.label}] called" # debug purpose
174
+ self._parent.send(:"invalidate_#{self.singular_target_name}_klass_flag=", true)
160
175
  end
161
176
 
162
177
  end
@@ -24,8 +24,6 @@ module CustomFields
24
24
 
25
25
  alias_method_chain :parentize, :custom_fields
26
26
 
27
-
28
-
29
27
  end
30
28
 
31
29
  end
@@ -6,11 +6,16 @@ module CustomFields
6
6
  included do
7
7
 
8
8
  def self.to_klass_with_custom_fields(fields, parent, association_name)
9
- klass_name = self.klass_name_with_custom_fields(parent, association_name)
9
+ klass = self.current_klass_with_custom_fields(parent, association_name)
10
10
 
11
- klass = Object.const_defined?(klass_name) ? Object.const_get(klass_name): nil
11
+ # for debug purpose
12
+ # if klass.nil?
13
+ # puts "[#{association_name.to_s.gsub(/^_/, '').singularize} / #{parent.name rescue 'unknown'}] no klass found"
14
+ # else
15
+ # puts "[#{association_name.to_s.gsub(/^_/, '').singularize} / #{parent.name rescue 'unknown'}] klass nil ? #{klass.nil?} / current version ? #{klass.version.inspect} / parent ? #{self.custom_fields_version(parent, association_name)}" # for debug purpose
16
+ # end
12
17
 
13
- if klass && klass.built_at != parent.updated_at.try(:utc) # new version ?
18
+ if klass && klass.version != self.custom_fields_version(parent, association_name) # new version ?
14
19
  self.invalidate_proxy_class_with_custom_fields(parent, association_name)
15
20
  klass = nil
16
21
  end
@@ -18,13 +23,21 @@ module CustomFields
18
23
  if klass.nil?
19
24
  klass = self.build_proxy_class_with_custom_fields(fields, parent, association_name)
20
25
 
26
+ klass_name = self.klass_name_with_custom_fields(parent, association_name)
27
+
21
28
  Object.const_set(klass_name, klass)
22
29
  end
23
30
 
24
31
  klass
25
32
  end
26
33
 
34
+ def self.custom_fields_version(parent, association_name)
35
+ singular_name = association_name.to_s.gsub(/^_/, '').singularize
36
+ parent.send(:"#{singular_name}_custom_fields_version")
37
+ end
38
+
27
39
  def self.invalidate_proxy_class_with_custom_fields(parent, association_name)
40
+ # puts "-> invalidate_proxy_class_with_custom_fields !!!!!" # for debug purpose
28
41
  klass_name = self.klass_name_with_custom_fields(parent, association_name)
29
42
 
30
43
  if Object.const_defined?(klass_name)
@@ -32,14 +45,22 @@ module CustomFields
32
45
  end
33
46
  end
34
47
 
48
+ def self.current_klass_with_custom_fields(parent, association_name)
49
+ klass_name = self.klass_name_with_custom_fields(parent, association_name)
50
+
51
+ Object.const_defined?(klass_name) ? Object.const_get(klass_name): nil
52
+ end
53
+
35
54
  def self.klass_name_with_custom_fields(parent, association_name)
36
55
  "#{association_name.to_s.gsub(/^_/, '').singularize.camelize}#{parent.class.name.camelize}#{parent._id}"
37
56
  end
38
57
 
39
58
  def self.build_proxy_class_with_custom_fields(fields, parent, association_name)
59
+ # puts "BUILDING PROXY CLASS #{association_name} / parent version #{self.custom_fields_version(parent, association_name)}" # for debug purpose
60
+
40
61
  (klass = Class.new(self)).class_eval <<-EOF
41
62
 
42
- cattr_accessor :custom_fields, :_parent, :association_name, :built_at
63
+ cattr_accessor :custom_fields, :_parent, :association_name, :built_at, :version
43
64
 
44
65
  def self.model_name
45
66
  @_model_name ||= ActiveModel::Name.new(self.superclass)
@@ -90,7 +111,7 @@ module CustomFields
90
111
 
91
112
  [*fields].each { |field| klass.apply_custom_field(field) }
92
113
 
93
- klass.built_at = parent.updated_at.try(:utc)
114
+ klass.version = self.custom_fields_version(parent, association_name)
94
115
 
95
116
  klass
96
117
  end
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module CustomFields
3
- VERSION = "1.0.0.beta.7"
3
+ VERSION = "1.0.0.beta.8"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: custom_fields
3
3
  version: !ruby/object:Gem::Version
4
- hash: 62196365
4
+ hash: 62196371
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
9
  - 0
10
10
  - beta
11
- - 7
12
- version: 1.0.0.beta.7
11
+ - 8
12
+ version: 1.0.0.beta.8
13
13
  platform: ruby
14
14
  authors:
15
15
  - Didier Lafforgue
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2011-03-18 00:00:00 +01:00
20
+ date: 2011-03-20 00:00:00 +01:00
21
21
  default_executable:
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency