hydra_attribute 0.3.2 → 0.4.0.rc1

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.
Files changed (65) hide show
  1. data/CHANGELOG.md +1 -1
  2. data/README.md +7 -0
  3. data/features/entity/create.feature +128 -0
  4. data/features/entity/destroy.feature +111 -0
  5. data/features/entity/new.feature +121 -0
  6. data/features/entity/update.feature +147 -0
  7. data/features/{attributes → hydra_attribute}/create.feature +7 -7
  8. data/features/{attributes → hydra_attribute}/destroy.feature +2 -4
  9. data/features/{attributes → hydra_attribute}/update.feature +10 -10
  10. data/features/hydra_set/destroy.feature +31 -0
  11. data/features/migrations/create_and_drop.feature +165 -0
  12. data/features/migrations/migrate_and_rollback.feature +211 -0
  13. data/features/relation/query_methods/group.feature +42 -0
  14. data/features/relation/query_methods/order.feature +67 -0
  15. data/features/relation/query_methods/reorder.feature +29 -0
  16. data/features/relation/query_methods/reverse_order.feature +29 -0
  17. data/features/relation/query_methods/select.feature +50 -0
  18. data/features/relation/query_methods/where.feature +70 -0
  19. data/features/step_definitions/connections.rb +65 -0
  20. data/features/step_definitions/model_steps.rb +79 -6
  21. data/features/step_definitions/query_methods.rb +3 -3
  22. data/features/step_definitions/record_steps.rb +3 -4
  23. data/features/support/env.rb +17 -3
  24. data/features/support/world.rb +15 -10
  25. data/gemfiles/3.1.gemfile.lock +15 -15
  26. data/gemfiles/3.2.gemfile.lock +15 -15
  27. data/lib/hydra_attribute/active_record/association.rb +74 -38
  28. data/lib/hydra_attribute/active_record/association_preloader.rb +49 -49
  29. data/lib/hydra_attribute/active_record/attribute_methods.rb +37 -85
  30. data/lib/hydra_attribute/active_record/migration.rb +2 -2
  31. data/lib/hydra_attribute/active_record/reflection.rb +1 -1
  32. data/lib/hydra_attribute/active_record/relation/query_methods.rb +8 -7
  33. data/lib/hydra_attribute/active_record/relation.rb +1 -0
  34. data/lib/hydra_attribute/active_record.rb +20 -12
  35. data/lib/hydra_attribute/association_builder.rb +1 -2
  36. data/lib/hydra_attribute/builder.rb +7 -8
  37. data/lib/hydra_attribute/entity_callbacks.rb +12 -32
  38. data/lib/hydra_attribute/hydra_attribute.rb +25 -16
  39. data/lib/hydra_attribute/hydra_attribute_methods.rb +85 -0
  40. data/lib/hydra_attribute/hydra_methods.rb +123 -0
  41. data/lib/hydra_attribute/hydra_set.rb +36 -0
  42. data/lib/hydra_attribute/hydra_set_methods.rb +39 -0
  43. data/lib/hydra_attribute/hydra_value_methods.rb +14 -0
  44. data/lib/hydra_attribute/memoize.rb +37 -0
  45. data/lib/hydra_attribute/migrator.rb +100 -51
  46. data/lib/hydra_attribute/railtie.rb +1 -3
  47. data/lib/hydra_attribute/version.rb +1 -1
  48. data/lib/hydra_attribute.rb +7 -1
  49. data/spec/hydra_attribute_methods_spec.rb +458 -0
  50. data/spec/hydra_attribute_spec.rb +19 -0
  51. data/spec/hydra_methods_spec.rb +457 -0
  52. data/spec/hydra_set_methods_spec.rb +203 -0
  53. data/spec/hydra_set_spec.rb +19 -0
  54. data/spec/memoize_spec.rb +95 -0
  55. data/spec/spec_helper.rb +42 -2
  56. metadata +71 -43
  57. data/features/create.feature +0 -47
  58. data/features/define.feature +0 -38
  59. data/features/destroy.feature +0 -102
  60. data/features/query_methods/group.feature +0 -42
  61. data/features/query_methods/order.feature +0 -99
  62. data/features/query_methods/select.feature +0 -50
  63. data/features/query_methods/where.feature +0 -70
  64. data/features/support/schema.rb +0 -79
  65. data/features/update.feature +0 -114
@@ -1,12 +1,12 @@
1
1
  module HydraAttribute
2
2
  module ActiveRecord
3
3
  class AssociationPreloader
4
- attr_reader :relation, :records, :hashed_records
4
+ attr_reader :relation, :records
5
5
 
6
6
  def initialize(relation, records = [])
7
- @relation = relation
8
- @records = records
9
- @hashed_records = records.each_with_object({}) { |record, hash| hash[record.id] = record }
7
+ @relation = relation
8
+ @records = records
9
+ prepared_records # lock attributes
10
10
  end
11
11
 
12
12
  def self.run(relation, records)
@@ -14,69 +14,69 @@ module HydraAttribute
14
14
  end
15
15
 
16
16
  def run
17
- grouped_values do |association, values, white_list_attribute_ids|
18
- association.target.concat(values)
19
- association.lock_for_build!(white_list_attribute_ids)
20
- end
21
- end
17
+ return if records.blank?
22
18
 
23
- private
19
+ prepared_records.keys.each_slice(in_clause_length || prepared_records.keys.length) do |entity_ids|
20
+ grouped_attribute_ids.each do |backend_type, hydra_attribute_ids|
21
+ next if hydra_attribute_ids.blank?
24
22
 
25
- def grouped_values
26
- grouped_attribute_ids do |type, attribute_ids|
27
- association_name = AssociationBuilder.association_name(type)
28
- load_values(type, attribute_ids) do |record, values|
29
- yield(record.association(association_name), values, attribute_ids)
23
+ hydra_attribute_ids.each_slice(in_clause_length || hydra_attribute_ids.length) do |attribute_ids|
24
+ value_class(backend_type).select(%w(id entity_id hydra_attribute_id value)).where(entity_id: entity_ids, hydra_attribute_id: attribute_ids).each do |model|
25
+ assoc = association_builder.association_name(backend_type)
26
+ prepared_records[model.entity_id].association(assoc).target.push(model)
27
+ end
28
+ end
30
29
  end
31
30
  end
32
31
  end
33
32
 
34
- def load_values(type, attribute_ids)
35
- return records.each { |record| yield(record, []) } if attribute_ids.empty?
33
+ private
34
+ def prepared_records
35
+ limit = attribute_limit?
36
+ @prepared_records ||= records.each_with_object({}) do |record, hash|
37
+ grouped_attribute_ids.each do |backend_type, hydra_attribute_ids|
38
+ association = record.association(association_builder.association_name(backend_type))
39
+ limit ? association.lock!(hydra_attribute_ids) : association.loaded!
40
+ end
41
+ hash[record.id] = record
42
+ end
43
+ end
36
44
 
37
- attribute_ids.each_slice(in_clause_length || attribute_ids.length) do |sliced_attribute_ids|
38
- records.each_slice(in_clause_length || records.length) do |sliced_records|
39
- values = AssociationBuilder.class_name(klass, type).constantize.select([:id, :entity_id, :hydra_attribute_id, :value]).where(entity_id: sliced_records, hydra_attribute_id: sliced_attribute_ids)
40
- group_records_with_values(sliced_records, values).each do |record_id, grouped_values|
41
- yield(hashed_records[record_id], grouped_values)
45
+ def grouped_attribute_ids
46
+ @grouped_attribute_ids ||= if attribute_limit?
47
+ map = klass.hydra_attribute_backend_types.each_with_object({}) { |backend_type, hash| hash[backend_type] = [] }
48
+ relation.hydra_select_values.each_with_object(map) do |name, grouped_ids|
49
+ hydra_attribute = klass.hydra_attribute(name)
50
+ grouped_ids[hydra_attribute.backend_type] << hydra_attribute.id
42
51
  end
52
+ else
53
+ klass.hydra_attribute_ids_by_backend_type
43
54
  end
44
55
  end
45
- end
46
56
 
47
- def group_records_with_values(records, values)
48
- hash = records.each_with_object({}) { |record, hash| hash[record.id] = [] }
49
- values.each { |value| hash[value.entity_id] << value }
50
- hash
51
- end
57
+ def attribute_limit?
58
+ relation.select_values.any? or relation.hydra_select_values.any?
59
+ end
52
60
 
53
- def grouped_attribute_ids
54
- map = klass.hydra_attribute_backend_types.each_with_object({}) { |type, object| object[type] = [] }
55
- mapping = hydra_attributes.each_with_object(map) do |hydra_attribute, mapping|
56
- mapping[hydra_attribute.backend_type] << hydra_attribute.id
61
+ def value_class(backend_type)
62
+ instance_variable_get(:"@#{backend_type}_class") || instance_variable_set(:"@#{backend_type}_class", association_builder.class_name(klass, backend_type).constantize)
57
63
  end
58
- mapping.each { |type, ids| yield(type, ids) }
59
- end
60
64
 
61
- def hydra_attributes
62
- if attribute_limit?
63
- relation.hydra_select_values.map { |name| klass.hydra_attribute(name) }
64
- else
65
- klass.hydra_attributes
65
+ def association_builder
66
+ AssociationBuilder
66
67
  end
67
- end
68
68
 
69
- def attribute_limit?
70
- relation.select_values.any? or relation.hydra_select_values.any?
71
- end
69
+ def connection
70
+ relation.connection
71
+ end
72
72
 
73
- def klass
74
- relation.klass
75
- end
73
+ def klass
74
+ relation.klass
75
+ end
76
76
 
77
- def in_clause_length
78
- klass.connection.in_clause_length
79
- end
77
+ def in_clause_length
78
+ connection.in_clause_length
79
+ end
80
80
  end
81
81
  end
82
82
  end
@@ -3,6 +3,8 @@ module HydraAttribute
3
3
  module AttributeMethods
4
4
  extend ActiveSupport::Concern
5
5
 
6
+ include HydraMethods
7
+
6
8
  NAME_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?=]?\z/
7
9
  CALL_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?]?\z/
8
10
 
@@ -23,34 +25,6 @@ module HydraAttribute
23
25
  end
24
26
  end
25
27
 
26
- def hydra_attributes
27
- @hydra_attributes ||= HydraAttribute.where(entity_type: base_class.model_name)
28
- end
29
-
30
- def grouped_hydra_attributes
31
- @grouped_hydra_attributes ||= hydra_attributes.group_by(&:backend_type)
32
- end
33
-
34
- %w(id name backend_type).each do |prefix|
35
- class_eval <<-EOS, __FILE__, __LINE__ + 1
36
- def hydra_attribute_#{prefix}s
37
- @hydra_attribute_#{prefix}s ||= hydra_attributes.map(&:#{prefix}).uniq
38
- end
39
-
40
- def grouped_hydra_attribute_#{prefix}s(type)
41
- instance = "@grouped_hydra_attribute_\#{type}_#{prefix}s"
42
- instance_variable_get(instance) || instance_variable_set(instance, grouped_hydra_attributes[type].map(&:#{prefix}).uniq)
43
- end
44
- EOS
45
- end
46
-
47
- def hydra_attribute(identifier)
48
- @hydra_attribute_cache ||= {}
49
- @hydra_attribute_cache[identifier] ||= hydra_attributes.find do |hydra_attribute|
50
- hydra_attribute.id == identifier || hydra_attribute.name == identifier
51
- end
52
- end
53
-
54
28
  def define_hydra_attribute_methods
55
29
  @hydra_attribute_methods_mutex.synchronize do
56
30
  return if hydra_attribute_methods_generated?
@@ -78,6 +52,10 @@ module HydraAttribute
78
52
 
79
53
  generated_hydra_attribute_methods.module_eval <<-EOS, __FILE__, __LINE__ + 1
80
54
  #{defn}
55
+ if hydra_set_id? and self.class.hydra_set_attribute_ids(hydra_set_id).exclude?(#{hydra_attribute.id})
56
+ raise MissingAttributeInHydraSetError, 'Attribute "#{hydra_attribute.name}" does not exist in hydra set "\#{hydra_set(hydra_set_id).name}"'
57
+ end
58
+
81
59
  if value_model = hydra_value_model(#{hydra_attribute.id})
82
60
  value_model.#{send}
83
61
  else
@@ -88,27 +66,17 @@ module HydraAttribute
88
66
  end
89
67
  end
90
68
 
91
- def reset_hydra_attribute_methods
69
+ def reset_hydra_attribute_methods!
92
70
  generated_hydra_attribute_methods.module_eval do
93
71
  instance_methods.each { |m| undef_method(m) }
94
72
  end
95
-
96
- @hydra_attributes = nil
97
73
  @hydra_attribute_methods_generated = false
98
- @hydra_attribute_cache = {}
99
- @grouped_hydra_attributes = nil
100
-
101
- %w(id name backend_type).each do |prefix|
102
- instance_variable_set("@hydra_attribute_#{prefix}s", nil)
103
74
 
104
- SUPPORT_TYPES.each do |type|
105
- instance_variable_set("@grouped_hydra_attribute_#{type}_#{prefix}s", nil)
106
- end
107
- end
75
+ clear_hydra_method_cache!
108
76
  end
109
77
 
110
78
  def undefine_attribute_methods
111
- reset_hydra_attribute_methods
79
+ reset_hydra_attribute_methods!
112
80
  super
113
81
  end
114
82
 
@@ -121,18 +89,32 @@ module HydraAttribute
121
89
 
122
90
  def respond_to?(name, include_private = false)
123
91
  self.class.define_hydra_attribute_methods unless self.class.hydra_attribute_methods_generated?
124
- super
92
+
93
+ # @COMPATIBILITY with 3.1.x active_model doesn't have "attribute_method_matcher" method
94
+ if ::ActiveRecord::VERSION::STRING.start_with?('3.1.')
95
+ matchers = attribute_method_matchers.partition { |m| m.prefix.empty? && m.suffix.empty? }.reverse.flatten(1)
96
+ matcher = matchers.detect { |method| method.match(name) }
97
+ attr_name = matcher.match(name).attr_name
98
+ else
99
+ attr_name = self.class.send(:attribute_method_matcher, name).attr_name
100
+ end
101
+
102
+ if hydra_attribute?(attr_name)
103
+ self.class.hydra_set_attribute_names(hydra_set_id).include?(attr_name)
104
+ else
105
+ super
106
+ end
125
107
  end
126
108
 
127
109
  def attributes
128
110
  hydra_value_models.each_with_object(super) do |model, attributes|
129
- attributes[model.attribute_name] = model.read_attribute('value')
111
+ attributes[model.hydra_attribute_name] = model.read_attribute('value')
130
112
  end
131
113
  end
132
114
 
133
115
  def attributes_before_type_cast
134
116
  hydra_value_models.each_with_object(super) do |model, attributes|
135
- attributes[model.attribute_name] = model.read_attribute_before_type_cast('value')
117
+ attributes[model.hydra_attribute_name] = model.read_attribute_before_type_cast('value')
136
118
  end
137
119
  end
138
120
 
@@ -140,7 +122,7 @@ module HydraAttribute
140
122
  class_eval <<-EOS, __FILE__, __LINE__ + 1
141
123
  def #{method}(attr_name)
142
124
  identifier = attr_name.to_s
143
- if self.class.hydra_attribute_names.include?(identifier)
125
+ if self.class.hydra_set_attribute_names(hydra_set_id).include?(identifier)
144
126
  if value_model = hydra_value_model(identifier)
145
127
  value_model.#{method}('value')
146
128
  else
@@ -153,55 +135,25 @@ module HydraAttribute
153
135
  EOS
154
136
  end
155
137
 
156
- def hydra_attribute_names
157
- @hydra_attribute_names ||= hydra_value_models.map(&:attribute_name)
158
- end
159
-
160
- def hydra_attribute_backend_types
161
- @hydra_attribute_backend_types ||= self.class.hydra_attribute_backend_types.select do |backend_type|
162
- hydra_value_association(backend_type).all_models.any?
163
- end
164
- end
165
-
166
138
  def inspect
167
139
  attrs = self.class.column_names.map { |name| "#{name}: #{attribute_for_inspect(name)}" }
168
- attrs += hydra_value_models.map { |model| "#{model.attribute_name}: #{model.attribute_for_inspect('value')}" }
140
+ attrs += hydra_value_models.map { |model| "#{model.hydra_attribute_name}: #{model.attribute_for_inspect('value')}" }
169
141
  "#<#{self.class} #{attrs.join(', ')}>"
170
142
  end
171
143
 
172
144
  private
173
-
174
- def hydra_value_model(identifier)
175
- @hydra_value_model_cache ||= {}
176
- @hydra_value_model_cache[identifier] ||= begin
177
- hydra_attribute = self.class.hydra_attribute(identifier)
178
- association = hydra_value_association(hydra_attribute.backend_type)
179
- association.find_model_or_build(hydra_attribute_id: hydra_attribute.id)
180
- end
181
- end
182
-
183
- def hydra_value_models
184
- @hydra_value_models ||= self.class.hydra_attribute_backend_types.inject([]) do |models, backend_type|
185
- models + hydra_value_association(backend_type).all_models
186
- end
187
- end
188
-
189
- def hydra_value_association(backend_type)
190
- association(::HydraAttribute::AssociationBuilder.association_name(backend_type))
191
- end
192
-
193
- def method_missing(method, *args, &block)
194
- if self.class.hydra_attribute_methods_generated?
195
- super
196
- else
197
- self.class.define_hydra_attribute_methods
198
- if respond_to_without_attributes?(method)
199
- send(method, *args, &block)
200
- else
145
+ def method_missing(method, *args, &block)
146
+ if self.class.hydra_attribute_methods_generated?
201
147
  super
148
+ else
149
+ self.class.define_hydra_attribute_methods
150
+ if respond_to_without_attributes?(method)
151
+ send(method, *args, &block)
152
+ else
153
+ super
154
+ end
202
155
  end
203
156
  end
204
- end
205
157
  end
206
158
  end
207
159
  end
@@ -9,8 +9,8 @@ module HydraAttribute
9
9
  Migrator.drop(self, name)
10
10
  end
11
11
 
12
- def migrate_to_hydra_entity(name)
13
- Migrator.migrate(self, name)
12
+ def migrate_to_hydra_entity(name, options = {}, &block)
13
+ Migrator.migrate(self, name, options, &block)
14
14
  end
15
15
 
16
16
  def rollback_from_hydra_entity(name)
@@ -9,7 +9,7 @@ module HydraAttribute
9
9
  end
10
10
 
11
11
  def backend_type
12
- @backend_type ||= SUPPORT_TYPES.find { |type| type == klass.model_name.demodulize.underscore.split('_')[1] }
12
+ @backend_type ||= SUPPORTED_BACKEND_TYPES.find { |type| type == klass.model_name.demodulize.underscore.split('_')[1] }
13
13
  end
14
14
  end
15
15
  end
@@ -42,7 +42,8 @@ module HydraAttribute
42
42
  @group_values = hydra_helper.quote_columns(@group_values.uniq.reject(&:blank?))
43
43
  @order_values = hydra_helper.quote_columns(@order_values.uniq.reject(&:blank?))
44
44
 
45
- if instance_variable_defined?(:@reorder_value) and instance_variable_get(:@reorder_value).present? # for compatibility with 3.1.x
45
+ # @COMPATIBILITY with 3.1.x active_record 3.1 uses the separate @reorder_value instance
46
+ if instance_variable_defined?(:@reorder_value) and instance_variable_get(:@reorder_value).present?
46
47
  @reorder_value = hydra_helper.quote_columns(@reorder_value.uniq.reject(&:blank?))
47
48
  end
48
49
 
@@ -51,9 +52,10 @@ module HydraAttribute
51
52
  @hydra_select_values.map!(&:to_s)
52
53
  @select_values.map!{ |value| hydra_helper.prepend_table_name(value) }
53
54
 
54
- # force add ID for preloading hydra attributes
55
- if @hydra_select_values.any? && @select_values.none? { |v| hydra_helper.attr_eq_column?(v, klass.primary_key) }
55
+ # attributes "id" and "hydra_set_id" are important for hydra_attribute gem
56
+ if @hydra_select_values.any? or @select_values.any?
56
57
  @select_values << hydra_helper.prepend_table_name(klass.primary_key)
58
+ @select_values << hydra_helper.prepend_table_name('hydra_set_id')
57
59
  end
58
60
 
59
61
  super
@@ -153,10 +155,9 @@ module HydraAttribute
153
155
  end
154
156
 
155
157
  private
156
-
157
- def hydra_helper
158
- @hydra_helper ||= Helper.new(self)
159
- end
158
+ def hydra_helper
159
+ @hydra_helper ||= Helper.new(self)
160
+ end
160
161
  end
161
162
  end
162
163
  end
@@ -6,6 +6,7 @@ module HydraAttribute
6
6
  included do
7
7
  include QueryMethods
8
8
 
9
+ # @COMPATIBILITY with 3.1.x active_record 3.1 doesn't have "exec_queries" method
9
10
  target = ::ActiveRecord::VERSION::STRING.starts_with?('3.1.') ? :to_a : :exec_queries
10
11
  alias_method :__old_exec_queries__, target
11
12
  alias_method target, :__exec_queries__
@@ -1,21 +1,29 @@
1
1
  module HydraAttribute
2
-
3
- # ActiveRecord::Base extends this module.
4
2
  module ActiveRecord
3
+ def self.append_features(base)
4
+ unless base.ancestors.include?(::ActiveRecord::Base)
5
+ raise %(Cannot include HydraAttribute::ActiveRecord module because "#{base}" is not inherited from ActiveRecord::Base)
6
+ end
7
+
8
+ unless base.base_class.equal?(base)
9
+ raise %(HydraAttribute::ActiveRecord module should be included to base class "#{base.base_class}" instead of "#{base}")
10
+ end
11
+
12
+ super
5
13
 
6
- # Add EAV behavior to this model.
7
- # Generate attribute and value associations.
8
- def use_hydra_attributes
9
- Builder.build(self)
14
+ base.extend(ClassMethods)
15
+ Builder.build(base)
10
16
  end
11
17
 
12
- # Create reflection for hydra association
13
- def create_reflection(macro, name, options, active_record)
14
- if name.to_s.start_with?('hydra_')
15
- reflections[name] = Reflection.new(macro, name, options, active_record)
16
- else
17
- super
18
+ module ClassMethods
19
+ def create_reflection(macro, name, options, active_record)
20
+ if name.to_s.start_with?('hydra_')
21
+ reflections[name] = Reflection.new(macro, name, options, active_record)
22
+ else
23
+ super
24
+ end
18
25
  end
19
26
  end
27
+
20
28
  end
21
29
  end
@@ -38,10 +38,9 @@ module HydraAttribute
38
38
  value_model.table_name = table_name
39
39
  value_model.belongs_to :entity, class_name: klass.model_name, autosave: false
40
40
  value_model.belongs_to :hydra_attribute, class_name: 'HydraAttribute::HydraAttribute'
41
- value_model.attr_accessible :hydra_attribute_id, :value
42
41
 
43
42
  value_model.class_eval <<-EOS, __FILE__, __LINE__ + 1
44
- def attribute_name
43
+ def hydra_attribute_name
45
44
  #{klass.model_name}.hydra_attribute(hydra_attribute_id).name
46
45
  end
47
46
  EOS
@@ -24,15 +24,14 @@ module HydraAttribute
24
24
  end
25
25
 
26
26
  private
27
-
28
- def build_associations
29
- SUPPORT_TYPES.each do |type|
30
- AssociationBuilder.build(klass, type)
27
+ def build_associations
28
+ SUPPORTED_BACKEND_TYPES.each do |type|
29
+ AssociationBuilder.build(klass, type)
30
+ end
31
31
  end
32
- end
33
32
 
34
- def build_white_list
35
- klass.hydra_attributes.each(&:toggle_white_list!)
36
- end
33
+ def build_white_list
34
+ klass.hydra_attributes.each(&:toggle_white_list!)
35
+ end
37
36
  end
38
37
  end
@@ -3,44 +3,24 @@ module HydraAttribute
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- after_create :create_hydra_values
7
- after_update :update_hydra_values
6
+ after_create :save_hydra_values
7
+ after_update :save_hydra_values
8
8
  before_destroy :destroy_hydra_values
9
9
  end
10
10
 
11
11
  private
12
-
13
- def create_hydra_values
14
- created = false
15
- each_hydra_value_model do |model|
16
- model.entity_id = id
17
- model.save
18
- created = true
12
+ def save_hydra_values
13
+ changed = false
14
+ self.class.hydra_set_attribute_backend_types(hydra_set_id).each do |backend_type|
15
+ changed = true if hydra_value_association(backend_type).save
16
+ end
17
+ touch if changed
19
18
  end
20
- touch if created
21
- end
22
-
23
- def update_hydra_values
24
- updated = false
25
- each_hydra_value_model do |model|
26
- if model.changed?
27
- updated = true
28
- model.save
29
- end
30
- end
31
- touch if updated
32
- end
33
19
 
34
- def destroy_hydra_values
35
- self.class.hydra_attribute_backend_types.each do |type|
36
- AssociationBuilder.class_name(self.class, type).constantize.where(entity_id: id).delete_all
20
+ def destroy_hydra_values
21
+ self.class.hydra_attribute_backend_types.each do |backend_type|
22
+ AssociationBuilder.class_name(self.class, backend_type).constantize.where(entity_id: id).delete_all
23
+ end
37
24
  end
38
- end
39
-
40
- def each_hydra_value_model(&block)
41
- self.class.hydra_attribute_backend_types.each do |type|
42
- association(AssociationBuilder.association_name(type)).all_models.each(&block)
43
- end
44
- end
45
25
  end
46
26
  end
@@ -9,16 +9,26 @@ module HydraAttribute
9
9
  end
10
10
  attr_accessible :white_list, as: :admin
11
11
 
12
+ has_and_belongs_to_many :hydra_sets, join_table: 'hydra_attribute_sets', class_name: 'HydraAttribute::HydraSet', conditions: proc { {hydra_sets: {entity_type: entity_type}} }
13
+
12
14
  with_options presence: true do |klass|
13
15
  klass.validates :entity_type, inclusion: { in: lambda { |attr| [(attr.entity_type.constantize.name rescue nil)] } }
14
16
  klass.validates :name, uniqueness: { scope: :entity_type }
15
- klass.validates :backend_type, inclusion: SUPPORT_TYPES
17
+ klass.validates :backend_type, inclusion: SUPPORTED_BACKEND_TYPES
16
18
  end
17
19
 
18
20
  before_destroy :delete_dependent_values
19
- after_commit :reload_attribute_methods
21
+ after_commit :clear_entity_cache
20
22
  after_commit :toggle_white_list!
21
23
 
24
+ # @COMPATIBILITY with 3.1.x association module is directly added to the class instead of including module
25
+ def hydra_sets_with_clearing_cache=(value)
26
+ self.hydra_sets_without_clearing_cache = value
27
+ clear_entity_cache
28
+ value
29
+ end
30
+ alias_method_chain :hydra_sets=, :clearing_cache
31
+
22
32
  def toggle_white_list!
23
33
  if destroyed? or !white_list?
24
34
  remove_from_white_list
@@ -28,22 +38,21 @@ module HydraAttribute
28
38
  end
29
39
 
30
40
  private
41
+ def delete_dependent_values
42
+ value_class = AssociationBuilder.class_name(entity_type.constantize, backend_type).constantize
43
+ value_class.delete_all(hydra_attribute_id: id)
44
+ end
31
45
 
32
- def delete_dependent_values
33
- value_class = AssociationBuilder.class_name(entity_type.constantize, backend_type).constantize
34
- value_class.delete_all(hydra_attribute_id: id)
35
- end
36
-
37
- def reload_attribute_methods
38
- entity_type.constantize.reset_hydra_attribute_methods # TODO should not remove all generated methods just for this attribute
39
- end
46
+ def clear_entity_cache
47
+ entity_type.constantize.clear_hydra_method_cache!
48
+ end
40
49
 
41
- def add_to_white_list
42
- entity_type.constantize.accessible_attributes.add(name)
43
- end
50
+ def add_to_white_list
51
+ entity_type.constantize.accessible_attributes.add(name)
52
+ end
44
53
 
45
- def remove_from_white_list
46
- entity_type.constantize.accessible_attributes.delete(name)
47
- end
54
+ def remove_from_white_list
55
+ entity_type.constantize.accessible_attributes.delete(name)
56
+ end
48
57
  end
49
58
  end