hydra_attribute 0.3.2 → 0.4.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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