hydra_attribute 0.4.2 → 0.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/.gitignore +2 -1
  2. data/.travis.yml +6 -5
  3. data/CHANGELOG.md +6 -0
  4. data/Gemfile +1 -1
  5. data/README.md +3 -3
  6. data/Rakefile +2 -7
  7. data/gemfiles/activerecord-3.2.gemfile +5 -0
  8. data/hydra_attribute.gemspec +6 -7
  9. data/lib/hydra_attribute.rb +17 -18
  10. data/lib/hydra_attribute/active_record.rb +34 -13
  11. data/lib/hydra_attribute/active_record/association_preloader.rb +47 -28
  12. data/lib/hydra_attribute/active_record/attribute_methods.rb +29 -140
  13. data/lib/hydra_attribute/active_record/mass_assignment_security.rb +39 -0
  14. data/lib/hydra_attribute/active_record/migration.rb +4 -4
  15. data/lib/hydra_attribute/active_record/relation.rb +6 -7
  16. data/lib/hydra_attribute/active_record/relation/query_methods.rb +28 -18
  17. data/lib/hydra_attribute/hydra_attribute.rb +12 -49
  18. data/lib/hydra_attribute/hydra_attribute_set.rb +67 -0
  19. data/lib/hydra_attribute/hydra_entity.rb +110 -0
  20. data/lib/hydra_attribute/hydra_entity_attribute_association.rb +155 -0
  21. data/lib/hydra_attribute/hydra_set.rb +24 -26
  22. data/lib/hydra_attribute/hydra_value.rb +210 -0
  23. data/lib/hydra_attribute/identity_map.rb +18 -0
  24. data/lib/hydra_attribute/middleware/identity_map.rb +15 -0
  25. data/lib/hydra_attribute/migrator.rb +24 -21
  26. data/lib/hydra_attribute/model.rb +47 -0
  27. data/lib/hydra_attribute/model/cacheable.rb +207 -0
  28. data/lib/hydra_attribute/model/dirty.rb +39 -0
  29. data/lib/hydra_attribute/model/has_many_through.rb +168 -0
  30. data/lib/hydra_attribute/model/identity_map.rb +59 -0
  31. data/lib/hydra_attribute/model/mediator.rb +89 -0
  32. data/lib/hydra_attribute/model/notifiable.rb +23 -0
  33. data/lib/hydra_attribute/model/persistence.rb +424 -0
  34. data/lib/hydra_attribute/model/validations.rb +40 -0
  35. data/lib/hydra_attribute/version.rb +1 -1
  36. data/spec/environments/mysql.rb +23 -0
  37. data/spec/environments/postgresql.rb +23 -0
  38. data/spec/environments/sqlite.rb +12 -0
  39. data/spec/fixtures/category.rb +8 -0
  40. data/spec/fixtures/product.rb +8 -0
  41. data/spec/fixtures/product_black_list.rb +13 -0
  42. data/spec/fixtures/product_white_list.rb +13 -0
  43. data/spec/hydra_attribute/active_record/attribute_methods_spec.rb +23 -28
  44. data/spec/hydra_attribute/active_record/mass_assignment_security_spec.rb +41 -0
  45. data/spec/hydra_attribute/active_record_spec.rb +577 -0
  46. data/spec/hydra_attribute/hydra_attribute_set_spec.rb +651 -0
  47. data/spec/hydra_attribute/hydra_attribute_spec.rb +208 -10
  48. data/spec/hydra_attribute/hydra_entity_attribute_association_spec.rb +216 -0
  49. data/spec/hydra_attribute/hydra_entity_spec.rb +71 -0
  50. data/spec/hydra_attribute/hydra_set_spec.rb +51 -10
  51. data/spec/hydra_attribute/hydra_value_spec.rb +286 -0
  52. data/spec/hydra_attribute/identity_map_spec.rb +47 -0
  53. data/spec/hydra_attribute/migrator_spec.rb +411 -0
  54. data/spec/hydra_attribute/model/cacheable_spec.rb +106 -0
  55. data/spec/hydra_attribute/model/has_many_through_spec.rb +132 -0
  56. data/spec/hydra_attribute/model/identity_map_spec.rb +39 -0
  57. data/spec/hydra_attribute/model/mediator_spec.rb +62 -0
  58. data/spec/hydra_attribute/model/persistence_spec.rb +550 -0
  59. data/spec/hydra_attribute/model_spec.rb +39 -0
  60. data/spec/hydra_attribute_spec.rb +36 -0
  61. data/spec/spec_helper.rb +10 -42
  62. metadata +76 -100
  63. data/Appraisals +0 -7
  64. data/cucumber.yml +0 -1
  65. data/features/entity/create.feature +0 -145
  66. data/features/entity/destroy.feature +0 -111
  67. data/features/entity/new.feature +0 -121
  68. data/features/entity/update.feature +0 -147
  69. data/features/hydra_attribute/create.feature +0 -30
  70. data/features/hydra_attribute/destroy.feature +0 -26
  71. data/features/hydra_attribute/update.feature +0 -36
  72. data/features/hydra_set/destroy.feature +0 -31
  73. data/features/migrations/create_and_drop.feature +0 -165
  74. data/features/migrations/migrate_and_rollback.feature +0 -211
  75. data/features/relation/query_methods/group.feature +0 -42
  76. data/features/relation/query_methods/order.feature +0 -67
  77. data/features/relation/query_methods/reorder.feature +0 -29
  78. data/features/relation/query_methods/reverse_order.feature +0 -29
  79. data/features/relation/query_methods/select.feature +0 -50
  80. data/features/relation/query_methods/where.feature +0 -115
  81. data/features/step_definitions/connections.rb +0 -65
  82. data/features/step_definitions/model_steps.rb +0 -136
  83. data/features/step_definitions/query_methods.rb +0 -48
  84. data/features/step_definitions/record_steps.rb +0 -93
  85. data/features/support/env.rb +0 -38
  86. data/features/support/world.rb +0 -61
  87. data/lib/hydra_attribute/active_record/association.rb +0 -113
  88. data/lib/hydra_attribute/active_record/reflection.rb +0 -16
  89. data/lib/hydra_attribute/association_builder.rb +0 -69
  90. data/lib/hydra_attribute/builder.rb +0 -37
  91. data/lib/hydra_attribute/entity_callbacks.rb +0 -26
  92. data/lib/hydra_attribute/hydra_attribute_methods.rb +0 -226
  93. data/lib/hydra_attribute/hydra_methods.rb +0 -528
  94. data/lib/hydra_attribute/hydra_set_methods.rb +0 -95
  95. data/lib/hydra_attribute/hydra_value_methods.rb +0 -21
  96. data/lib/hydra_attribute/memoizable.rb +0 -37
  97. data/spec/hydra_attribute/active_record/relation/query_methods_spec.rb +0 -31
  98. data/spec/hydra_attribute/hydra_attribute_methods_spec.rb +0 -458
  99. data/spec/hydra_attribute/hydra_methods_spec.rb +0 -456
  100. data/spec/hydra_attribute/hydra_set_methods_spec.rb +0 -203
  101. data/spec/hydra_attribute/memoizable_spec.rb +0 -95
@@ -1,19 +1,60 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe HydraAttribute::HydraSet do
4
- describe '#hydra_attributes=' do
5
- let!(:hydra_set) { Product.hydra_sets.create(name: 'Default') }
4
+ describe '#hydra_attributes' do
5
+ it 'should return blank array if model has not ID' do
6
+ HydraAttribute::HydraSet.new.hydra_attributes.should be_blank
7
+ end
8
+
9
+ it 'should return blank array if model has not any hydra_attributes' do
10
+ hydra_set = HydraAttribute::HydraSet.create(name: 'default', entity_type: 'Product')
11
+ hydra_set.hydra_attributes.should be_blank
12
+ end
13
+
14
+ it 'should return array of hydra_attributes for the current hydra_set' do
15
+ hydra_set1 = HydraAttribute::HydraSet.create(entity_type: 'Product', name: 'default1')
16
+ hydra_set2 = HydraAttribute::HydraSet.create(entity_type: 'Product', name: 'default2')
17
+ hydra_attribute1 = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'attr1', backend_type: 'string')
18
+ hydra_attribute2 = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'attr2', backend_type: 'string')
19
+ hydra_attribute3 = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'attr3', backend_type: 'string')
20
+
21
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: hydra_set1.id, hydra_attribute_id: hydra_attribute1.id)
22
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: hydra_set1.id, hydra_attribute_id: hydra_attribute2.id)
23
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: hydra_set2.id, hydra_attribute_id: hydra_attribute3.id)
24
+
25
+ hydra_set1.should have(2).hydra_attributes
26
+ hydra_set2.should have(1).hydra_attributes
27
+
28
+ hydra_set1.hydra_attributes.should include(hydra_attribute1)
29
+ hydra_set1.hydra_attributes.should include(hydra_attribute2)
30
+ hydra_set2.hydra_attributes.should include(hydra_attribute3)
31
+ end
32
+ end
33
+
34
+ describe 'validations' do
35
+ it 'should require entity_type' do
36
+ hydra_set = HydraAttribute::HydraSet.new
37
+ hydra_set.valid?
38
+ hydra_set.errors.should include(:entity_type)
39
+
40
+ hydra_set.entity_type = 'Product'
41
+ hydra_set.valid?
42
+ hydra_set.errors.should_not include(:entity_type)
43
+ end
44
+
45
+ it 'should require name' do
46
+ hydra_set = HydraAttribute::HydraSet.new
47
+ hydra_set.valid?
48
+ hydra_set.errors.should include(:name)
6
49
 
7
- it 'should clear entity cache if assign hydra attributes collection' do
8
- hydra_attribute = Product.hydra_attributes.create(name: 'one', backend_type: 'string')
9
- Product.should_receive(:clear_hydra_method_cache!)
10
- hydra_set.hydra_attributes = [hydra_attribute]
50
+ hydra_set.name = 'Default'
51
+ hydra_set.valid?
52
+ hydra_set.errors.should_not include(:name)
11
53
  end
12
54
 
13
- it 'should clear entity cache if assign blank collection' do
14
- hydra_set.hydra_attributes.create(name: 'one', backend_type: 'string')
15
- Product.should_receive(:clear_hydra_method_cache!)
16
- hydra_set.hydra_attributes = []
55
+ it 'should have unique name with entity_type' do
56
+ HydraAttribute::HydraSet.create(name: 'Default', entity_type: 'Product').should be_persisted
57
+ HydraAttribute::HydraSet.create(name: 'Default', entity_type: 'Product').should_not be_persisted
17
58
  end
18
59
  end
19
60
  end
@@ -0,0 +1,286 @@
1
+ require 'spec_helper'
2
+
3
+ describe HydraAttribute::HydraValue do
4
+ describe '.arel_tables' do
5
+ it 'should return hash which holds arel tables for entity table and backend type' do
6
+ arel_tables = HydraAttribute::HydraValue.arel_tables
7
+
8
+ table = arel_tables['products']['string']
9
+ table.name.should == 'hydra_string_products'
10
+ table.engine.should == ActiveRecord::Base
11
+
12
+ table = arel_tables['entity_table']['backend_type']
13
+ table.name.should == 'hydra_backend_type_entity_table'
14
+ table.engine.should == ActiveRecord::Base
15
+ end
16
+
17
+ it 'should cache result' do
18
+ arel_tables = HydraAttribute::HydraValue.arel_tables
19
+
20
+ table1 = arel_tables['product_table']['backend_type']
21
+ table2 = arel_tables['product_table']['backend_type']
22
+ table1.should be(table2)
23
+ end
24
+ end
25
+
26
+ describe '.connection' do
27
+ it 'should return the database connection' do
28
+ HydraAttribute::HydraValue.connection.should be_a_kind_of(ActiveRecord::ConnectionAdapters::AbstractAdapter)
29
+ end
30
+ end
31
+
32
+ describe '.column' do
33
+ it 'should return a column by hydra_attribute_id' do
34
+ float = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'a1', backend_type: 'float', default_value: 2.5)
35
+ string = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'a2', backend_type: 'string', default_value: 'abc')
36
+ integer = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'a3', backend_type: 'integer')
37
+
38
+ float_column = HydraAttribute::HydraValue.column(float.id)
39
+ float_column.should be_a_kind_of(::ActiveRecord::ConnectionAdapters::Column)
40
+ float_column.name.should == 'a1'
41
+ float_column.default.should == 2.5
42
+ float_column.sql_type.should == 'float'
43
+
44
+ string_column = HydraAttribute::HydraValue.column(string.id)
45
+ string_column.should be_a_kind_of(::ActiveRecord::ConnectionAdapters::Column)
46
+ string_column.name.should == 'a2'
47
+ string_column.default.should == 'abc'
48
+ string_column.sql_type.should == 'string'
49
+
50
+ integer_column = HydraAttribute::HydraValue.column(integer.id)
51
+ integer_column.should be_a_kind_of(::ActiveRecord::ConnectionAdapters::Column)
52
+ integer_column.name.should == 'a3'
53
+ integer_column.default.should be_nil
54
+ integer_column.sql_type.should == 'integer'
55
+ end
56
+ end
57
+
58
+ describe '#initialize' do
59
+ it 'should raise error when :hydra_attribute_id is not passed to initialize' do
60
+ lambda do
61
+ HydraAttribute::HydraValue.new(Product.new)
62
+ end.should raise_error(HydraAttribute::HydraValue::HydraAttributeIdIsMissedError, 'Key :hydra_attribute_id is missed')
63
+ end
64
+
65
+ it 'should not raise error when :hydra_attribute_id is passed' do
66
+ attr = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: 'float')
67
+
68
+ lambda do
69
+ HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: attr.id)
70
+ end.should_not raise_error
71
+ end
72
+ end
73
+
74
+ describe '#column' do
75
+ let(:hydra_value) { HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute_id) }
76
+ let(:hydra_attribute_id) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: backend_type).id }
77
+
78
+ describe 'for string hydra_attribute' do
79
+ let(:backend_type) { 'string' }
80
+
81
+ it 'should return string virtual column' do
82
+ hydra_value.column.should be_a_kind_of(::ActiveRecord::ConnectionAdapters::Column)
83
+ hydra_value.column.sql_type.should == 'string'
84
+ end
85
+ end
86
+
87
+ describe 'for integer hydra attribute' do
88
+ let(:backend_type) { 'integer' }
89
+
90
+ it 'should return integer virtual column' do
91
+ hydra_value.column.should be_a_kind_of(::ActiveRecord::ConnectionAdapters::Column)
92
+ hydra_value.column.sql_type.should == 'integer'
93
+ end
94
+ end
95
+ end
96
+
97
+ describe '#id' do
98
+ let(:hydra_attribute) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: 'float') }
99
+
100
+ it 'should return model ID' do
101
+ hydra_value = HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id, id: 2)
102
+ hydra_value.id.should be(2)
103
+
104
+ hydra_value = HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id)
105
+ hydra_value.id.should be_nil
106
+ end
107
+ end
108
+
109
+ describe '#value' do
110
+ it 'should return default value' do
111
+ hydra_attribute = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'string', default_value: 'abc')
112
+
113
+ hydra_value = HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id)
114
+ hydra_value.value.should == 'abc'
115
+
116
+ hydra_value = HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id, value: 'qwerty')
117
+ hydra_value.value.should == 'qwerty'
118
+ end
119
+
120
+ it 'should return type casted value' do
121
+ hydra_attribute = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'integer')
122
+
123
+ hydra_value = HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id, value: '12a')
124
+ hydra_value.value.should == 12
125
+ end
126
+ end
127
+
128
+ describe '#value=' do
129
+ it 'should change current value' do
130
+ hydra_attribute = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'string')
131
+
132
+ hydra_value = HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id, value: 'abc')
133
+ hydra_value.value = 'www'
134
+ hydra_value.value.should == 'www'
135
+ end
136
+
137
+ it 'should type cast value before assign it' do
138
+ hydra_attribute = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: 'float')
139
+
140
+ hydra_value = HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id)
141
+
142
+ hydra_value.value = '2.57a'
143
+ hydra_value.value.should == 2.57
144
+
145
+ hydra_value.value = 'a'
146
+ hydra_value.value.should == 0.0
147
+ end
148
+ end
149
+
150
+ describe '#value?' do
151
+ let(:hydra_attribute) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: backend_type) }
152
+ let(:hydra_value) { HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id) }
153
+
154
+ describe 'integer attribute' do
155
+ let(:backend_type) { 'integer' }
156
+
157
+ it 'should be true for 1' do
158
+ hydra_value.value = 1
159
+ hydra_value.value?.should be_true
160
+ end
161
+
162
+ it 'should be false for 0' do
163
+ hydra_value.value = 0
164
+ hydra_value.value?.should be_false
165
+ end
166
+
167
+ it 'should be false for nil' do
168
+ hydra_value.value = nil
169
+ hydra_value.value?.should be_false
170
+ end
171
+ end
172
+
173
+ describe 'string attribute' do
174
+ let(:backend_type) { 'string' }
175
+
176
+ it 'should be true for "abc"' do
177
+ hydra_value.value = 'abc'
178
+ hydra_value.value?.should be_true
179
+ end
180
+
181
+ it 'should be false for ""' do
182
+ hydra_value.value = ''
183
+ hydra_value.value?.should be_false
184
+ end
185
+
186
+ it 'should be false for nil' do
187
+ hydra_value.value = nil
188
+ hydra_value.value?.should be_false
189
+ end
190
+ end
191
+ end
192
+
193
+ describe '#value_before_type_cast' do
194
+ let(:hydra_attribute) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: 'float') }
195
+ let(:hydra_value) { HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id) }
196
+
197
+ it 'should return not type casted value' do
198
+ hydra_value.value = '2.0'
199
+ hydra_value.value_before_type_cast.should == '2.0'
200
+
201
+ hydra_value.value = 'aaa'
202
+ hydra_value.value_before_type_cast.should == 'aaa'
203
+ end
204
+ end
205
+
206
+ describe '#hydra_attribute' do
207
+ it 'should return hydra attribute model' do
208
+ hydra_attribute = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: 'float')
209
+
210
+ hydra_value = HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id)
211
+ hydra_value.hydra_attribute.should be(hydra_attribute)
212
+ end
213
+ end
214
+
215
+ describe '#persisted?' do
216
+ let(:hydra_attribute) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: 'float') }
217
+
218
+ it 'should return true if model has ID' do
219
+ hydra_value = HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id, id: 2)
220
+ hydra_value.should be_persisted
221
+ end
222
+
223
+ it 'should return false unless model has ID' do
224
+ hydra_value = HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id)
225
+ hydra_value.should_not be_persisted
226
+ end
227
+ end
228
+
229
+ describe '#save' do
230
+ let(:product) { Product.create! }
231
+ let(:hydra_attribute) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: 'float', default_value: 0.1) }
232
+
233
+ it 'should raise an error if entity model is not persisted' do
234
+ hydra_value = HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id)
235
+ lambda do
236
+ hydra_value.save
237
+ end.should raise_error(HydraAttribute::HydraValue::EntityModelIsNotPersistedError, 'HydraValue model cannot be saved is entity model is not persisted')
238
+ end
239
+
240
+ describe 'create' do
241
+ it 'should create model with default value' do
242
+ hydra_value = HydraAttribute::HydraValue.new(product, hydra_attribute_id: hydra_attribute.id)
243
+ hydra_value.save
244
+
245
+ value = product.connection.select_value("SELECT value FROM hydra_float_products WHERE entity_id=#{product.id} AND hydra_attribute_id=#{hydra_attribute.id}")
246
+ value.to_f.should == 0.1
247
+ end
248
+
249
+ it 'should create model with changed value' do
250
+ hydra_value = HydraAttribute::HydraValue.new(product, hydra_attribute_id: hydra_attribute.id)
251
+ hydra_value.value = 2.5
252
+ hydra_value.save
253
+
254
+ value = product.connection.select_value("SELECT value FROM hydra_float_products WHERE id=#{hydra_value.id}")
255
+ value.to_f.should == 2.5
256
+ end
257
+ end
258
+
259
+ describe 'update' do
260
+ it 'should update hydra value in database' do
261
+ hydra_value = HydraAttribute::HydraValue.new(product, hydra_attribute_id: hydra_attribute.id)
262
+ hydra_value.value = 2.5
263
+ hydra_value.save
264
+
265
+ hydra_value.value = 5.5
266
+ hydra_value.save
267
+
268
+ value = product.connection.select_value("SELECT value FROM hydra_float_products WHERE id=#{hydra_value.id}")
269
+ value.to_f.should == 5.5
270
+ end
271
+ end
272
+ end
273
+
274
+ describe 'value methods' do
275
+ let(:hydra_attribute) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'string') }
276
+
277
+ it 'should respond to dirty methods' do
278
+ hydra_value = HydraAttribute::HydraValue.new(Product.new, hydra_attribute_id: hydra_attribute.id)
279
+ hydra_value.should respond_to(:value_changed?)
280
+ hydra_value.should respond_to(:value_change)
281
+ hydra_value.should respond_to(:value_will_change!)
282
+ hydra_value.should respond_to(:value_was)
283
+ hydra_value.should respond_to(:reset_value!)
284
+ end
285
+ end
286
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe HydraAttribute::IdentityMap do
4
+ it 'acts like Hash' do
5
+ HydraAttribute::IdentityMap.should < Hash
6
+ end
7
+
8
+ describe '#cache' do
9
+ it 'should store value into cache' do
10
+ identity_map = HydraAttribute::IdentityMap.new
11
+ identity_map.cache(:abc, 1).should be(1)
12
+ identity_map[:abc].should be(1)
13
+ end
14
+
15
+ it 'should return value from cache if it exists' do
16
+ identity_map = HydraAttribute::IdentityMap.new
17
+ identity_map[:abc] = 1
18
+
19
+ identity_map.cache(:abc, 2).should be(1)
20
+ identity_map[:abc].should be(1)
21
+ end
22
+
23
+ it 'should accept block for storing value into cache' do
24
+ identity_map = HydraAttribute::IdentityMap.new
25
+
26
+ value = identity_map.cache(:abc) { 3 }
27
+ value.should be(3)
28
+ identity_map[:abc].should be(3)
29
+ end
30
+
31
+ it 'should return value from cache if it exists and block is passed' do
32
+ identity_map = HydraAttribute::IdentityMap.new
33
+ identity_map[:abc] = 1
34
+
35
+ value = identity_map.cache(:abc) { 3 }
36
+ value.should be(1)
37
+ identity_map[:abc].should be(1)
38
+ end
39
+
40
+ its 'block should have higher priority then value' do
41
+ identity_map = HydraAttribute::IdentityMap.new
42
+ value = identity_map.cache(:abc, 1) { 2 }
43
+ value.should be(2)
44
+ identity_map[:abc].should be(2)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,411 @@
1
+ require 'spec_helper'
2
+
3
+ describe HydraAttribute::Migrator do
4
+ let(:connection) { ActiveRecord::Base.connection }
5
+ let(:migrator) { HydraAttribute::Migrator.new(connection) }
6
+ let(:backend_tables) { ->(entity){ HydraAttribute::SUPPORTED_BACKEND_TYPES.map { |type| "hydra_#{type}_#{entity}" }} }
7
+
8
+ describe '#create' do
9
+ after { migrator.drop(:wheels) }
10
+
11
+ before do
12
+ migrator.create :wheels do |t|
13
+ t.string :name
14
+ t.timestamps
15
+ end
16
+ end
17
+
18
+ describe 'entity' do
19
+ let(:columns) { connection.columns(:wheels) }
20
+
21
+ it 'should have the necessary columns' do
22
+ columns.map(&:name).should =~ %w[id hydra_set_id name created_at updated_at]
23
+ end
24
+
25
+ it 'should have a correct column types' do
26
+ column = columns.find { |c| c.name == 'hydra_set_id' }
27
+ column.null.should be_true
28
+ case ENV['DB']
29
+ when 'postgresql' then column.sql_type.should == 'integer'
30
+ when 'mysql' then column.sql_type.should == 'int(11)'
31
+ when 'sqlite' then column.sql_type.should == 'integer'
32
+ else raise 'Unknown database'
33
+ end
34
+ end
35
+
36
+ it 'should have a correct indexes' do
37
+ index = connection.indexes(:wheels).find { |i| i.name == 'wheels_hydra_set_id_idx' }
38
+ index.unique.should be_false
39
+ index.columns.should == %w[hydra_set_id]
40
+ end
41
+ end
42
+
43
+ describe 'hydra_attributes' do
44
+ let(:columns) { connection.columns(:hydra_attributes) }
45
+
46
+ it 'should have the necessary columns' do
47
+ columns.map(&:name).should =~ %w[id entity_type name backend_type default_value white_list created_at updated_at]
48
+ end
49
+
50
+ it 'should have a correct column types' do
51
+ column = columns.find { |c| c.name == 'entity_type' }
52
+ column.sql_type.should == (ENV['DB'] == 'postgresql' ? 'character varying(32)' : 'varchar(32)')
53
+ column.null.should be_false
54
+
55
+ column = columns.find { |c| c.name == 'name' }
56
+ column.sql_type.should == (ENV['DB'] == 'postgresql' ? 'character varying(32)' : 'varchar(32)')
57
+ column.null.should be_false
58
+
59
+ column = columns.find { |c| c.name == 'backend_type' }
60
+ column.sql_type.should == (ENV['DB'] == 'postgresql' ? 'character varying(16)' : 'varchar(16)')
61
+ column.null.should be_false
62
+
63
+ column = columns.find { |c| c.name == 'default_value' }
64
+ column.sql_type.should == (ENV['DB'] == 'postgresql' ? 'character varying(255)' : 'varchar(255)')
65
+ column.null.should be_true
66
+
67
+ column = columns.find { |c| c.name == 'white_list' }
68
+ column.null.should be_false
69
+ column.default.should be_false
70
+ case ENV['DB']
71
+ when 'postgresql' then column.sql_type.should == 'boolean'
72
+ when 'mysql' then column.sql_type.should == 'tinyint(1)'
73
+ when 'sqlite' then column.sql_type.should == 'boolean'
74
+ else raise 'Unknown database'
75
+ end
76
+
77
+ column = columns.find { |c| c.name == 'created_at' }
78
+ column.null.should be_false
79
+ case ENV['DB']
80
+ when 'postgresql' then column.sql_type.should == 'timestamp without time zone'
81
+ when 'mysql' then column.sql_type.should == 'datetime'
82
+ when 'sqlite' then column.sql_type.should == 'datetime'
83
+ else raise 'Unknown database'
84
+ end
85
+
86
+ column = columns.find { |c| c.name == 'updated_at' }
87
+ column.null.should be_false
88
+ case ENV['DB']
89
+ when 'postgresql' then column.sql_type.should == 'timestamp without time zone'
90
+ when 'mysql' then column.sql_type.should == 'datetime'
91
+ when 'sqlite' then column.sql_type.should == 'datetime'
92
+ else raise 'Unknown database'
93
+ end
94
+ end
95
+
96
+ it 'should have a correct indexes' do
97
+ connection.indexes(:hydra_attributes).should have(1).indexes
98
+ connection.indexes(:hydra_attributes)[0].name.should == 'hydra_attributes_idx'
99
+ connection.indexes(:hydra_attributes)[0].unique.should be_true
100
+ connection.indexes(:hydra_attributes)[0].columns.should == %w[entity_type name]
101
+ end
102
+ end
103
+
104
+ describe 'hydra_sets' do
105
+ let(:columns) { connection.columns(:hydra_sets) }
106
+
107
+ it 'should have the necessary columns' do
108
+ columns.map(&:name).should =~ %w[id entity_type name created_at updated_at]
109
+ end
110
+
111
+ it 'should have a correct column types' do
112
+ column = columns.find { |c| c.name == 'entity_type' }
113
+ column.sql_type.should == (ENV['DB'] == 'postgresql' ? 'character varying(32)' : 'varchar(32)')
114
+ column.null.should be_false
115
+
116
+ column = columns.find { |c| c.name == 'name' }
117
+ column.sql_type.should == (ENV['DB'] == 'postgresql' ? 'character varying(32)' : 'varchar(32)')
118
+ column.null.should be_false
119
+
120
+ column = columns.find { |c| c.name == 'created_at' }
121
+ column.sql_type.should == (ENV['DB'] == 'postgresql' ? 'timestamp without time zone' : 'datetime')
122
+ column.null.should be_false
123
+
124
+ column = columns.find { |c| c.name == 'updated_at' }
125
+ column.sql_type.should == (ENV['DB'] == 'postgresql' ? 'timestamp without time zone' : 'datetime')
126
+ column.null.should be_false
127
+ end
128
+
129
+ it 'should have a correct indexes' do
130
+ connection.indexes(:hydra_sets).should have(1).indexes
131
+ connection.indexes(:hydra_sets)[0].name.should == 'hydra_sets_idx'
132
+ connection.indexes(:hydra_sets)[0].unique.should be_true
133
+ connection.indexes(:hydra_sets)[0].columns.should == %w[entity_type name]
134
+ end
135
+ end
136
+
137
+ describe 'hydra_attribute_sets' do
138
+ let(:columns) { connection.columns(:hydra_attribute_sets) }
139
+
140
+ it 'should have the necessary columns' do
141
+ columns.map(&:name).should =~ %w[id hydra_attribute_id hydra_set_id created_at updated_at]
142
+ end
143
+
144
+ it 'should have a correct column types' do
145
+ column = columns.find { |c| c.name == 'hydra_attribute_id' }
146
+ column.null.should be_false
147
+ case ENV['DB']
148
+ when 'postgresql' then column.sql_type.should == 'integer'
149
+ when 'mysql' then column.sql_type.should == 'int(11)'
150
+ when 'sqlite' then column.sql_type.should == 'integer'
151
+ else raise 'Unknown database'
152
+ end
153
+
154
+ column = columns.find { |c| c.name == 'hydra_set_id' }
155
+ column.null.should be_false
156
+ case ENV['DB']
157
+ when 'postgresql' then column.sql_type.should == 'integer'
158
+ when 'mysql' then column.sql_type.should == 'int(11)'
159
+ when 'sqlite' then column.sql_type.should == 'integer'
160
+ else raise 'Unknown database'
161
+ end
162
+
163
+ column = columns.find { |c| c.name == 'created_at' }
164
+ column.null.should be_false
165
+ case ENV['DB']
166
+ when 'postgresql' then column.sql_type.should == 'timestamp without time zone'
167
+ when 'mysql' then column.sql_type.should == 'datetime'
168
+ when 'sqlite' then column.sql_type.should == 'datetime'
169
+ else raise 'Unknown database'
170
+ end
171
+
172
+ column = columns.find { |c| c.name == 'updated_at' }
173
+ column.null.should be_false
174
+ case ENV['DB']
175
+ when 'postgresql' then column.sql_type.should == 'timestamp without time zone'
176
+ when 'mysql' then column.sql_type.should == 'datetime'
177
+ when 'sqlite' then column.sql_type.should == 'datetime'
178
+ else raise 'Unknown database'
179
+ end
180
+ end
181
+
182
+ it 'should have a correct indexes' do
183
+ connection.indexes(:hydra_attribute_sets).should have(1).indexes
184
+ connection.indexes(:hydra_attribute_sets)[0].name.should == 'hydra_attribute_sets_idx'
185
+ connection.indexes(:hydra_attribute_sets)[0].unique.should be_true
186
+ connection.indexes(:hydra_attribute_sets)[0].columns.should == %w[hydra_attribute_id hydra_set_id]
187
+ end
188
+ end
189
+
190
+ describe 'values' do
191
+ it 'should have the following value tables' do
192
+ connection.table_exists?('hydra_string_wheels').should be_true
193
+ connection.table_exists?('hydra_text_wheels').should be_true
194
+ connection.table_exists?('hydra_float_wheels').should be_true
195
+ connection.table_exists?('hydra_decimal_wheels').should be_true
196
+ connection.table_exists?('hydra_boolean_wheels').should be_true
197
+ connection.table_exists?('hydra_datetime_wheels').should be_true
198
+ end
199
+
200
+ it 'should have the correct column types' do
201
+ %w[hydra_string_wheels hydra_text_wheels hydra_float_wheels hydra_boolean_wheels hydra_datetime_wheels].each do |table|
202
+ column = connection.columns(table).find { |c| c.name == 'entity_id' }
203
+ column.null.should be_false
204
+ case ENV['DB']
205
+ when 'postgresql' then column.sql_type.should == 'integer'
206
+ when 'mysql' then column.sql_type.should == 'int(11)'
207
+ when 'sqlite' then column.sql_type.should == 'integer'
208
+ else raise 'Unknown database'
209
+ end
210
+
211
+ column = connection.columns(table).find { |c| c.name == 'hydra_attribute_id' }
212
+ column.null.should be_false
213
+ case ENV['DB']
214
+ when 'postgresql' then column.sql_type.should == 'integer'
215
+ when 'mysql' then column.sql_type.should == 'int(11)'
216
+ when 'sqlite' then column.sql_type.should == 'integer'
217
+ else raise 'Unknown database'
218
+ end
219
+
220
+ column = connection.columns(table).find { |c| c.name == 'created_at' }
221
+ column.null.should be_false
222
+ case ENV['DB']
223
+ when 'postgresql' then column.sql_type.should == 'timestamp without time zone'
224
+ when 'mysql' then column.sql_type.should == 'datetime'
225
+ when 'sqlite' then column.sql_type.should == 'datetime'
226
+ else raise 'Unknown database'
227
+ end
228
+
229
+ column = connection.columns(table).find { |c| c.name == 'updated_at' }
230
+ column.null.should be_false
231
+ case ENV['DB']
232
+ when 'postgresql' then column.sql_type.should == 'timestamp without time zone'
233
+ when 'mysql' then column.sql_type.should == 'datetime'
234
+ when 'sqlite' then column.sql_type.should == 'datetime'
235
+ else raise 'Unknown database'
236
+ end
237
+ end
238
+
239
+ column = connection.columns('hydra_string_wheels').find { |c| c.name == 'value' }
240
+ column.null.should be_true
241
+ case ENV['DB']
242
+ when 'postgresql' then column.sql_type.should == 'character varying(255)'
243
+ when 'mysql' then column.sql_type.should == 'varchar(255)'
244
+ when 'sqlite' then column.sql_type.should == 'varchar(255)'
245
+ else raise 'Unknown database'
246
+ end
247
+
248
+ column = connection.columns('hydra_text_wheels').find { |c| c.name == 'value' }
249
+ column.null.should be_true
250
+ column.sql_type.should == 'text'
251
+
252
+ column = connection.columns('hydra_integer_wheels').find { |c| c.name == 'value' }
253
+ column.null.should be_true
254
+ case ENV['DB']
255
+ when 'postgresql' then column.sql_type.should == 'integer'
256
+ when 'mysql' then column.sql_type.should == 'int(11)'
257
+ when 'sqlite' then column.sql_type.should == 'integer'
258
+ else raise 'Unknown database'
259
+ end
260
+
261
+ column = connection.columns('hydra_float_wheels').find { |c| c.name == 'value' }
262
+ column.null.should be_true
263
+ case ENV['DB']
264
+ when 'postgresql' then column.sql_type.should == 'double precision'
265
+ when 'mysql' then column.sql_type.should == 'float'
266
+ when 'sqlite' then column.sql_type.should == 'float'
267
+ else raise 'Unknown database'
268
+ end
269
+
270
+ column = connection.columns('hydra_decimal_wheels').find { |c| c.name == 'value' }
271
+ column.null.should be_true
272
+ column.precision.should be(10)
273
+ column.scale.should be(4)
274
+ case ENV['DB']
275
+ when 'postgresql' then column.sql_type.should == 'numeric(10,4)'
276
+ when 'mysql' then column.sql_type.should == 'decimal(10,4)'
277
+ when 'sqlite' then column.sql_type.should == 'decimal(10,4)'
278
+ else raise 'Unknown database'
279
+ end
280
+
281
+ column = connection.columns('hydra_boolean_wheels').find { |c| c.name == 'value' }
282
+ column.null.should be_true
283
+ case ENV['DB']
284
+ when 'postgresql' then column.sql_type.should == 'boolean'
285
+ when 'mysql' then column.sql_type.should == 'tinyint(1)'
286
+ when 'sqlite' then column.sql_type.should == 'boolean'
287
+ else raise 'Unknown database'
288
+ end
289
+
290
+ column = connection.columns('hydra_datetime_wheels').find { |c| c.name == 'value' }
291
+ column.null.should be_true
292
+ case ENV['DB']
293
+ when 'postgresql' then column.sql_type.should == 'timestamp without time zone'
294
+ when 'mysql' then column.sql_type.should == 'datetime'
295
+ when 'sqlite' then column.sql_type.should == 'datetime'
296
+ else raise 'Unknown database'
297
+ end
298
+ end
299
+
300
+ it 'should have a correct indexes' do
301
+ connection.indexes(:hydra_string_wheels).should have(1).indexes
302
+ connection.indexes(:hydra_string_wheels)[0].name.should == 'hydra_string_wheels_idx'
303
+ connection.indexes(:hydra_string_wheels)[0].unique.should be_true
304
+ connection.indexes(:hydra_string_wheels)[0].columns.should == %w[entity_id hydra_attribute_id]
305
+
306
+ connection.indexes(:hydra_text_wheels).should have(1).indexes
307
+ connection.indexes(:hydra_text_wheels)[0].name.should == 'hydra_text_wheels_idx'
308
+ connection.indexes(:hydra_text_wheels)[0].unique.should be_true
309
+ connection.indexes(:hydra_text_wheels)[0].columns.should == %w[entity_id hydra_attribute_id]
310
+
311
+ connection.indexes(:hydra_integer_wheels).should have(1).indexes
312
+ connection.indexes(:hydra_integer_wheels)[0].name.should == 'hydra_integer_wheels_idx'
313
+ connection.indexes(:hydra_integer_wheels)[0].unique.should be_true
314
+ connection.indexes(:hydra_integer_wheels)[0].columns.should == %w[entity_id hydra_attribute_id]
315
+
316
+ connection.indexes(:hydra_float_wheels).should have(1).indexes
317
+ connection.indexes(:hydra_float_wheels)[0].name.should == 'hydra_float_wheels_idx'
318
+ connection.indexes(:hydra_float_wheels)[0].unique.should be_true
319
+ connection.indexes(:hydra_float_wheels)[0].columns.should == %w[entity_id hydra_attribute_id]
320
+
321
+ connection.indexes(:hydra_decimal_wheels).should have(1).indexes
322
+ connection.indexes(:hydra_decimal_wheels)[0].name.should == 'hydra_decimal_wheels_idx'
323
+ connection.indexes(:hydra_decimal_wheels)[0].unique.should be_true
324
+ connection.indexes(:hydra_decimal_wheels)[0].columns.should == %w[entity_id hydra_attribute_id]
325
+
326
+ connection.indexes(:hydra_boolean_wheels).should have(1).indexes
327
+ connection.indexes(:hydra_boolean_wheels)[0].name.should == 'hydra_boolean_wheels_idx'
328
+ connection.indexes(:hydra_boolean_wheels)[0].unique.should be_true
329
+ connection.indexes(:hydra_boolean_wheels)[0].columns.should == %w[entity_id hydra_attribute_id]
330
+
331
+ connection.indexes(:hydra_datetime_wheels).should have(1).indexes
332
+ connection.indexes(:hydra_datetime_wheels)[0].name.should == 'hydra_datetime_wheels_idx'
333
+ connection.indexes(:hydra_datetime_wheels)[0].unique.should be_true
334
+ connection.indexes(:hydra_datetime_wheels)[0].columns.should == %w[entity_id hydra_attribute_id]
335
+ end
336
+ end
337
+ end
338
+
339
+ describe '#drop' do
340
+ it 'should drop entity and hydra tables' do
341
+ migrator.create :wheels
342
+ connection.table_exists?(:wheels).should be_true
343
+ connection.table_exists?(:hydra_string_wheels).should be_true
344
+ connection.table_exists?(:hydra_text_wheels).should be_true
345
+ connection.table_exists?(:hydra_integer_wheels).should be_true
346
+ connection.table_exists?(:hydra_float_wheels).should be_true
347
+ connection.table_exists?(:hydra_boolean_wheels).should be_true
348
+ connection.table_exists?(:hydra_datetime_wheels).should be_true
349
+
350
+ migrator.drop :wheels
351
+ connection.table_exists?(:wheels).should be_false
352
+ connection.table_exists?(:hydra_string_wheels).should be_false
353
+ connection.table_exists?(:hydra_text_wheels).should be_false
354
+ connection.table_exists?(:hydra_integer_wheels).should be_false
355
+ connection.table_exists?(:hydra_float_wheels).should be_false
356
+ connection.table_exists?(:hydra_boolean_wheels).should be_false
357
+ connection.table_exists?(:hydra_datetime_wheels).should be_false
358
+ end
359
+ end
360
+
361
+ describe '#migrate' do
362
+ before { connection.create_table :wheels }
363
+ after { connection.drop_table :wheels }
364
+
365
+ it 'should create hydra tables for entity' do
366
+ connection.table_exists?(:wheels).should be_true
367
+ connection.table_exists?(:hydra_string_wheels).should be_false
368
+ connection.table_exists?(:hydra_text_wheels).should be_false
369
+ connection.table_exists?(:hydra_integer_wheels).should be_false
370
+ connection.table_exists?(:hydra_float_wheels).should be_false
371
+ connection.table_exists?(:hydra_boolean_wheels).should be_false
372
+ connection.table_exists?(:hydra_datetime_wheels).should be_false
373
+
374
+ migrator.migrate :wheels
375
+ connection.table_exists?(:wheels).should be_true
376
+ connection.table_exists?(:hydra_string_wheels).should be_true
377
+ connection.table_exists?(:hydra_text_wheels).should be_true
378
+ connection.table_exists?(:hydra_integer_wheels).should be_true
379
+ connection.table_exists?(:hydra_float_wheels).should be_true
380
+ connection.table_exists?(:hydra_boolean_wheels).should be_true
381
+ connection.table_exists?(:hydra_datetime_wheels).should be_true
382
+
383
+ migrator.rollback :wheels
384
+ end
385
+ end
386
+
387
+ describe '#rollback' do
388
+ before { connection.create_table :wheels }
389
+ after { connection.drop_table :wheels }
390
+
391
+ it 'should drop hydra tables for entity' do
392
+ migrator.migrate :wheels
393
+ connection.table_exists?(:wheels).should be_true
394
+ connection.table_exists?(:hydra_string_wheels).should be_true
395
+ connection.table_exists?(:hydra_text_wheels).should be_true
396
+ connection.table_exists?(:hydra_integer_wheels).should be_true
397
+ connection.table_exists?(:hydra_float_wheels).should be_true
398
+ connection.table_exists?(:hydra_boolean_wheels).should be_true
399
+ connection.table_exists?(:hydra_datetime_wheels).should be_true
400
+
401
+ migrator.rollback :wheels
402
+ connection.table_exists?(:wheels).should be_true
403
+ connection.table_exists?(:hydra_string_wheels).should be_false
404
+ connection.table_exists?(:hydra_text_wheels).should be_false
405
+ connection.table_exists?(:hydra_integer_wheels).should be_false
406
+ connection.table_exists?(:hydra_float_wheels).should be_false
407
+ connection.table_exists?(:hydra_boolean_wheels).should be_false
408
+ connection.table_exists?(:hydra_datetime_wheels).should be_false
409
+ end
410
+ end
411
+ end