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
@@ -0,0 +1,40 @@
1
+ module HydraAttribute
2
+ module Model
3
+ module Validations
4
+ extend ActiveSupport::Concern
5
+ include ActiveModel::Validations
6
+
7
+ class UniqueValidator < ActiveModel::EachValidator
8
+ def validate_each(record, attribute, value)
9
+ klass = record.class
10
+ table = record.class.arel_table
11
+ arel = record.class.select_manager
12
+
13
+ where = comparison(table, attribute, value, klass.column(attribute.to_s).text?)
14
+
15
+ if options[:scope]
16
+ where = Array(options[:scope]).inject(where) do |query, field|
17
+ query.and(comparison(table, field, record.send(field), klass.column(field.to_s).text?))
18
+ end
19
+ end
20
+
21
+ where = where.and(table[:id].not_eq(record.id)) if record.persisted?
22
+ arel.where(where).project(table[:id])
23
+
24
+ if record.class.connection.select_value(arel).present?
25
+ record.errors.add(attribute, :taken, value: value)
26
+ end
27
+ end
28
+
29
+ private
30
+ def comparison(table, field, value, insensitive = true)
31
+ if insensitive
32
+ table[field].lower.eq(table.lower(value))
33
+ else
34
+ table[field].eq(value)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,3 +1,3 @@
1
1
  module HydraAttribute
2
- VERSION = '0.4.2'
2
+ VERSION = '0.5.0.rc1'
3
3
  end
@@ -0,0 +1,23 @@
1
+ config = {
2
+ :adapter => 'mysql2',
3
+ :host => ENV['DB_HOST'] || 'localhost',
4
+ :database => ENV['DB_NAME'] || 'hydra_attribute_test',
5
+ :username => ENV['DB_USERNAME'] || 'root',
6
+ :password => ENV['DB_PASSWORD'],
7
+ :encoding => 'utf8'
8
+ }
9
+
10
+ ActiveRecord::Base.establish_connection(config.merge(database: nil))
11
+ ActiveRecord::Base.connection.drop_database(config[:database])
12
+ ActiveRecord::Base.connection.create_database(config[:database], charset: 'utf8', collation: 'utf8_unicode_ci')
13
+ ActiveRecord::Base.establish_connection(config)
14
+
15
+ RSpec.configure do |spec|
16
+ spec.after do
17
+ ActiveRecord::Base.connection_pool.connections.each do |connection|
18
+ connection.tables.each do |table_name|
19
+ connection.execute("TRUNCATE TABLE `#{table_name}`")
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ config = {
2
+ :adapter => 'postgresql',
3
+ :host => ENV['DB_HOST'] || 'localhost',
4
+ :database => ENV['DB_NAME'] || 'hydra_attribute_test',
5
+ :username => ENV['DB_USERNAME'] || 'postgres',
6
+ :password => ENV['DB_PASSWORD'],
7
+ :encoding => 'utf8'
8
+ }
9
+
10
+ ActiveRecord::Base.establish_connection(config.merge(database: 'postgres', schema_search_path: 'public'))
11
+ ActiveRecord::Base.connection.drop_database(config[:database])
12
+ ActiveRecord::Base.connection.create_database(config[:database], config)
13
+ ActiveRecord::Base.establish_connection(config)
14
+
15
+ RSpec.configure do |spec|
16
+ spec.after do
17
+ ActiveRecord::Base.connection_pool.connections.each do |connection|
18
+ connection.tables.each do |table_name|
19
+ connection.execute("TRUNCATE #{table_name}")
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
2
+
3
+ RSpec.configure do |spec|
4
+ spec.after do
5
+ ActiveRecord::Base.connection_pool.connections.each do |connection|
6
+ connection.tables.each do |table_name|
7
+ connection.execute("DELETE FROM #{table_name}")
8
+ connection.execute("DELETE FROM sqlite_sequence WHERE name='#{table_name}'")
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ HydraAttribute::Migrator.new(ActiveRecord::Base.connection).create :categories do |t|
2
+ t.string :name
3
+ t.timestamps
4
+ end
5
+
6
+ class Category < ActiveRecord::Base
7
+ include HydraAttribute::ActiveRecord
8
+ end
@@ -0,0 +1,8 @@
1
+ HydraAttribute::Migrator.new(ActiveRecord::Base.connection).create :products do |t|
2
+ t.string :name
3
+ t.timestamps
4
+ end
5
+
6
+ class Product < ActiveRecord::Base
7
+ include HydraAttribute::ActiveRecord
8
+ end
@@ -0,0 +1,13 @@
1
+ HydraAttribute::Migrator.new(ActiveRecord::Base.connection).create :product_black_lists do |t|
2
+ t.string :name
3
+ t.string :title
4
+ t.timestamps
5
+ end
6
+
7
+ class ProductBlackList < ActiveRecord::Base
8
+ include HydraAttribute::ActiveRecord
9
+
10
+ attr_protected :name
11
+
12
+ self.mass_assignment_sanitizer = :logger
13
+ end
@@ -0,0 +1,13 @@
1
+ HydraAttribute::Migrator.new(ActiveRecord::Base.connection).create :product_white_lists do |t|
2
+ t.string :name
3
+ t.string :title
4
+ t.timestamps
5
+ end
6
+
7
+ class ProductWhiteList < ActiveRecord::Base
8
+ include HydraAttribute::ActiveRecord
9
+
10
+ attr_accessible :name
11
+
12
+ self.mass_assignment_sanitizer = :logger
13
+ end
@@ -1,39 +1,34 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe HydraAttribute::ActiveRecord::AttributeMethods do
4
- describe '::ClassMethods' do
5
- describe '#define_hydra_attribute_method' do
6
- it 'should throw MissingAttributeInHydraSetError if we call generated hydra attribute method which does not exist in hydra set' do
7
- Product.hydra_attributes.create(name: 'color', backend_type: 'string')
8
- hydra_set = Product.hydra_sets.create(name: 'Default')
9
- product = Product.new(hydra_set_id: hydra_set.id)
4
+ describe '#read_attribute' do
5
+ before do
6
+ Product.hydra_attributes.create(name: 'code', backend_type: 'string', default_value: 'abc')
7
+ end
8
+
9
+ let(:product) { Product.new }
10
10
 
11
- lambda do
12
- product.color
13
- end.should raise_error(HydraAttribute::MissingAttributeInHydraSetError, %(Hydra attribute "color" does not exist in hydra set "Default"))
14
- end
11
+ it 'should return value of static attribute' do
12
+ product.name = 'one'
13
+ product.read_attribute(:name).should == 'one'
14
+ end
15
15
 
16
- it 'should not throw error when new sub class instance is created' do
17
- Product.hydra_attributes.create(name: 'color', backend_type: 'string')
18
- Product.reset_hydra_attribute_methods!
16
+ it 'should return default hydra attribute value' do
17
+ product.read_attribute(:code).should == 'abc'
18
+ end
19
19
 
20
- sub_class = Class.new(Product)
21
- lambda do
22
- sub_class.new.color
23
- end.should_not raise_error
24
- end
20
+ it 'should return the value of hydra attribute' do
21
+ product.code = 'second'
22
+ product.read_attribute(:code).should == 'second'
23
+ end
25
24
 
26
- it 'should allow access to attributes from base model and its sub model' do
27
- Product.hydra_attributes.create(name: 'color', backend_type: 'string')
28
- Product.reset_hydra_attribute_methods!
29
- Product.send(:remove_instance_variable, :@generated_hydra_attribute_methods)
25
+ it 'should return nil for unknown attribute' do
26
+ product.read_attribute(:unknown).should be_nil
27
+ end
30
28
 
31
- sub_class = Class.new(Product)
32
- lambda do
33
- sub_class.new.color
34
- Product.new.color
35
- end.should_not raise_error
36
- end
29
+ it 'should return nil if hydra attribute does not exist in hydra set' do
30
+ product.hydra_set_id = Product.hydra_sets.create(name: 'default').id
31
+ product.read_attribute(:name).should be_nil
37
32
  end
38
33
  end
39
34
  end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ module HydraAttribute::ActiveRecord::MassAssignmentSecurity
4
+ describe 'WhiteList' do
5
+ before do
6
+ ProductWhiteList.hydra_attributes.create(name: 'color', backend_type: 'string', white_list: true)
7
+ ProductWhiteList.hydra_attributes.create(name: 'code', backend_type: 'string', white_list: false)
8
+ end
9
+
10
+ let(:product) { ProductWhiteList.new(name: 'name', title: 'title', color: 'green', code: 'abc') }
11
+
12
+ it 'should assign only hydra attributes which are in white list' do
13
+ product.color.should == 'green'
14
+ product.code.should be_nil
15
+ end
16
+
17
+ it 'should not break default behavior for static attributes' do
18
+ product.name.should == 'name'
19
+ product.title.should be_nil
20
+ end
21
+ end
22
+
23
+ describe 'BlackList' do
24
+ before do
25
+ ProductBlackList.hydra_attributes.create(name: 'color', backend_type: 'string', white_list: true)
26
+ ProductBlackList.hydra_attributes.create(name: 'code', backend_type: 'string', white_list: false)
27
+ end
28
+
29
+ let(:product) { ProductBlackList.new(name: 'name', title: 'title', color: 'green', code: 'abc') }
30
+
31
+ it 'should assign only hydra attributes which are in white list' do
32
+ product.color.should == 'green'
33
+ product.code.should be_nil
34
+ end
35
+
36
+ it 'should not break default behavior for static attributes' do
37
+ product.name.should be_nil
38
+ product.title.should == 'title'
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,577 @@
1
+ require 'spec_helper'
2
+
3
+ describe HydraAttribute::ActiveRecord do
4
+ describe '.inspect' do
5
+ before do
6
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'string', white_list: true)
7
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: 'decimal', white_list: true)
8
+ end
9
+
10
+ it 'should include hydra attributes in inspection string too' do
11
+ Product.inspect.should == 'Product(id: integer, hydra_set_id: integer, name: string, created_at: datetime, updated_at: datetime, code: string, price: decimal)'
12
+ end
13
+ end
14
+
15
+ describe '.new' do
16
+ let!(:attr1) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'string', default_value: nil, white_list: true) }
17
+ let!(:attr2) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'info', backend_type: 'string', default_value: '', white_list: true) }
18
+ let!(:attr3) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'total', backend_type: 'integer', default_value: 0, white_list: true) }
19
+ let!(:attr4) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: 'float', default_value: 0, white_list: true) }
20
+ let!(:attr5) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'active', backend_type: 'boolean', default_value: 0, white_list: true) }
21
+ let!(:attr6) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'started', backend_type: 'datetime', default_value: '2013-01-01', white_list: true) }
22
+
23
+ let(:product) { Product.new(attributes) }
24
+
25
+ describe 'without any attributes' do
26
+ let(:attributes) { {} }
27
+
28
+ it 'should return default values' do
29
+ product.code.should be_nil
30
+ product.info.should == ''
31
+ product.total.should be(0)
32
+ product.price.should == 0.0
33
+ product.active.should be_false
34
+ product.started.should == Time.utc('2013-01-01')
35
+ end
36
+ end
37
+
38
+ describe 'with "code", "info" and "price" attributes' do
39
+ let(:attributes) { {code: 'a', info: nil, price: nil} }
40
+
41
+ it 'should save these attributes into database' do
42
+ product.code.should == 'a'
43
+ product.info.should be_nil
44
+ product.total.should be(0)
45
+ product.price.should == nil
46
+ product.active.should be_false
47
+ product.started.should == Time.utc('2013-01-01')
48
+ end
49
+ end
50
+
51
+ describe 'with all attributes' do
52
+ let(:attributes) { {code: 'a', info: 'b', total: 3, price: 4.3, active: true, started: Time.utc('2013-02-03')} }
53
+
54
+ it 'should save all these attributes into database' do
55
+ product.code.should == 'a'
56
+ product.info.should == 'b'
57
+ product.total.should == 3
58
+ product.price.should == 4.3
59
+ product.active.should be_true
60
+ product.started.should == Time.utc('2013-02-03')
61
+ end
62
+ end
63
+
64
+ describe 'with all attributes and hydra_set_id' do
65
+ let(:hydra_set_id) { HydraAttribute::HydraSet.create(entity_type: 'Product', name: 'default').id }
66
+ let(:attributes) { {code: 'a', info: 'b', total: 3, price: 4.3, active: true, started: Time.utc('2013-02-03'), hydra_set_id: hydra_set_id} }
67
+
68
+ before do
69
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: hydra_set_id, hydra_attribute_id: attr1.id)
70
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: hydra_set_id, hydra_attribute_id: attr3.id)
71
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: hydra_set_id, hydra_attribute_id: attr5.id)
72
+ end
73
+
74
+ it 'should save only attributes from this hydra set' do
75
+ product.code.should == 'a'
76
+ lambda { product.info }.should raise_error HydraAttribute::HydraSet::MissingAttributeInHydraSetError, "Attribute ID #{attr2.id} is missed in Set ID #{hydra_set_id}"
77
+ product.total.should == 3
78
+ lambda { product.price }.should raise_error HydraAttribute::HydraSet::MissingAttributeInHydraSetError, "Attribute ID #{attr4.id} is missed in Set ID #{hydra_set_id}"
79
+ product.active.should be_true
80
+ lambda { product.started }.should raise_error HydraAttribute::HydraSet::MissingAttributeInHydraSetError, "Attribute ID #{attr6.id} is missed in Set ID #{hydra_set_id}"
81
+ end
82
+
83
+ it 'should not raise an error when missing attribute in set was passed' do
84
+ lambda do
85
+ Product.new(
86
+ :hydra_set_id => hydra_set_id,
87
+ attr1.name => 1,
88
+ attr2.name => 2,
89
+ attr3.name => 3,
90
+ attr4.name => 4,
91
+ attr5.name => 5,
92
+ attr6.name => 5)
93
+ end.should_not raise_error
94
+ end
95
+ end
96
+ end
97
+
98
+ describe '.create' do
99
+ let!(:attr1) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'string', default_value: nil, white_list: true) }
100
+ let!(:attr2) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'info', backend_type: 'string', default_value: '', white_list: true) }
101
+ let!(:attr3) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'total', backend_type: 'integer', default_value: 0, white_list: true) }
102
+ let!(:attr4) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: 'float', default_value: 0, white_list: true) }
103
+ let!(:attr5) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'active', backend_type: 'boolean', default_value: 0, white_list: true) }
104
+ let!(:attr6) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'started', backend_type: 'datetime', default_value: '2013-01-01', white_list: true) }
105
+
106
+ let(:product) { Product.find(Product.create(attributes).id) }
107
+
108
+ describe 'without any attributes' do
109
+ let(:attributes) { {} }
110
+
111
+ it 'should have default values' do
112
+ product.code.should be_nil
113
+ product.info.should == ''
114
+ product.total.should be(0)
115
+ product.price.should == 0.0
116
+ product.active.should be_false
117
+ product.started.should == Time.utc('2013-01-01')
118
+ end
119
+ end
120
+
121
+ describe 'with "code", "info" and "price" attributes' do
122
+ let(:attributes) { {code: 'a', info: nil, price: nil} }
123
+
124
+ it 'should save these attributes into database' do
125
+ product.code.should == 'a'
126
+ product.info.should be_nil
127
+ product.total.should be(0)
128
+ product.price.should == nil
129
+ product.active.should be_false
130
+ product.started.should == Time.utc('2013-01-01')
131
+ end
132
+ end
133
+
134
+ describe 'with all attributes' do
135
+ let(:attributes) { {code: 'a', info: 'b', total: 3, price: 4.3, active: true, started: Time.utc('2013-02-03')} }
136
+
137
+ it 'should save all these attributes into database' do
138
+ product.code.should == 'a'
139
+ product.info.should == 'b'
140
+ product.total.should == 3
141
+ product.price.should == 4.3
142
+ product.active.should be_true
143
+ product.started.should == Time.utc('2013-02-03')
144
+ end
145
+ end
146
+
147
+ describe 'with all attributes and hydra_set_id' do
148
+ let(:hydra_set_id) { HydraAttribute::HydraSet.create(entity_type: 'Product', name: 'default').id }
149
+ let(:attributes) { {code: 'a', info: 'b', total: 3, price: 4.3, active: true, started: Time.utc('2013-02-03'), hydra_set_id: hydra_set_id} }
150
+
151
+ before do
152
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: hydra_set_id, hydra_attribute_id: attr1.id)
153
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: hydra_set_id, hydra_attribute_id: attr3.id)
154
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: hydra_set_id, hydra_attribute_id: attr5.id)
155
+ end
156
+
157
+ let(:value) { ->(entity, attr) { ActiveRecord::Base.connection.select_value("SELECT value FROM hydra_#{attr.backend_type}_#{entity.class.table_name} WHERE entity_id = #{entity.id} AND hydra_attribute_id = #{attr.id}") } }
158
+
159
+ it 'should save only attributes from this hydra set' do
160
+ value.(product, attr1).should == 'a'
161
+ value.(product, attr2).should be_nil
162
+ value.(product, attr3).to_i.should == 3
163
+ value.(product, attr4).should be_nil
164
+ ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.should include(value.(product, attr5))
165
+ value.(product, attr6).should be_nil
166
+ end
167
+ end
168
+ end
169
+
170
+ describe '.find' do
171
+ before do
172
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'title', backend_type: 'string', white_list: true)
173
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'integer', white_list: true)
174
+ end
175
+
176
+ it 'should have hydra attributes' do
177
+ product = Product.create(name: 'one', title: 'wow', code: 42)
178
+ product = Product.find(product.id)
179
+ product.name.should == 'one'
180
+ product.title.should == 'wow'
181
+ product.code.should == 42
182
+ end
183
+ end
184
+
185
+ describe '.count' do
186
+ before do
187
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'title', backend_type: 'string', white_list: true)
188
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'integer', white_list: true)
189
+ Product.create(name: 'one', title: 'abc', code: 42)
190
+ Product.create(name: 'two', title: 'qwe', code: 52)
191
+ end
192
+
193
+ it 'should correct count the number of records' do
194
+ Product.count.should be(2)
195
+ end
196
+ end
197
+
198
+ describe '.group' do
199
+ before do
200
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'integer', white_list: true)
201
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'title', backend_type: 'string', white_list: true)
202
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'total', backend_type: 'integer', white_list: true)
203
+
204
+ Product.create(name: 'a', code: 1, title: 'q', total: 5)
205
+ Product.create(name: 'b', code: 2, title: 'w', total: 5)
206
+ Product.create(name: 'b', code: 3, title: 'w')
207
+ Product.create(name: 'c', code: 4, title: 'e')
208
+ end
209
+
210
+ describe 'without where condition' do
211
+ it 'should be able to group by hydra and by static attributes' do
212
+ Product.group(:name).count.stringify_keys.should == {'a'=>1, 'b'=>2, 'c'=>1}
213
+ Product.group(:code).count.stringify_keys.should == {'1'=>1, '2'=>1, '3'=>1, '4'=>1}
214
+ Product.group(:total).count.stringify_keys.should == {'5'=>2, ''=>2}
215
+ Product.group(:name, :title).count.should == {%w[a q]=>1, %w[b w]=>2, %w[c e]=>1}
216
+ end
217
+ end
218
+
219
+ describe 'with where condition' do
220
+ it 'should be able to group by hydra and by static attributes' do
221
+ Product.where(title: 'w').group(:name).count.stringify_keys.should == {'b'=>2}
222
+ Product.where(title: 'w').group(:code).count.stringify_keys.should == {'2'=>1, '3'=>1}
223
+ Product.where(title: 'w').group(:total).count.stringify_keys.should == {'5'=>1, ''=>1}
224
+ Product.where(total: nil).group(:name, :title).count.should == {%w[b w]=>1, %w[c e]=>1}
225
+ end
226
+ end
227
+ end
228
+
229
+ describe '.order' do
230
+ before do
231
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'state', backend_type: 'integer', white_list: true)
232
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'title', backend_type: 'string', white_list: true)
233
+
234
+ Product.create(name: 'a', state: 3, title: 'c')
235
+ Product.create(name: 'b', state: 2, title: 'b')
236
+ Product.create(name: 'c', state: 1, title: 'b')
237
+ end
238
+
239
+ it 'should order by one field' do
240
+ Product.order(:name).map(&:name).should == %w[a b c]
241
+ Product.order(:state).map(&:name).should == %w[c b a]
242
+ end
243
+
244
+ it 'should order by two fields' do
245
+ Product.order(:title, :state).map(&:name).should == %w[c b a]
246
+ Product.order(:title, :name).map(&:name).should == %w[b c a]
247
+ end
248
+
249
+ it 'should order by field with with filter' do
250
+ Product.where(name: %w[a b]).order(:title).map(&:name).should == %w[b a]
251
+ Product.where(title: 'b').order(:state).map(&:name).should == %w[c b]
252
+ end
253
+ end
254
+
255
+ describe '.reverse_order' do
256
+ before do
257
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'state', backend_type: 'integer', white_list: true)
258
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'title', backend_type: 'string', white_list: true)
259
+
260
+ Product.create(name: 'a', state: 3, title: 'c')
261
+ Product.create(name: 'b', state: 2, title: 'b')
262
+ Product.create(name: 'c', state: 1, title: 'b')
263
+ end
264
+
265
+ it 'should order by one field and reorder list' do
266
+ Product.order(:name).reverse_order.map(&:name).should == %w[c b a]
267
+ Product.order(:state).reverse_order.map(&:name).should == %w[a b c]
268
+ end
269
+
270
+ it 'should order by two fields and reorder list' do
271
+ Product.order(:title, :state).reverse_order.map(&:name).should == %w[a b c]
272
+ Product.order(:title, :name).reverse_order.map(&:name).should == %w[a c b]
273
+ end
274
+
275
+ it 'should order by field with with filter and reorder list' do
276
+ Product.where(name: %w[a b]).order(:title).reverse_order.map(&:name).should == %w[a b]
277
+ Product.where(title: 'b').order(:state).reverse_order.map(&:name).should == %w[b c]
278
+ end
279
+ end
280
+
281
+ describe '.reorder' do
282
+ before do
283
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'state', backend_type: 'integer', white_list: true)
284
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'title', backend_type: 'string', white_list: true)
285
+
286
+ Product.create(name: 'a', state: 3, title: 'c')
287
+ Product.create(name: 'b', state: 2, title: 'b')
288
+ Product.create(name: 'c', state: 1, title: 'b')
289
+ end
290
+
291
+ it 'should order by one field' do
292
+ Product.order(:name).reorder(:state).map(&:name).should == %w[c b a]
293
+ Product.order(:state).reorder(:name).map(&:name).should == %w[a b c]
294
+ end
295
+
296
+ it 'should order by two fields' do
297
+ Product.order(:title, :state).reorder(:title, :name).map(&:name).should == %w[b c a]
298
+ Product.order(:title, :name).reorder(:title, :state).map(&:name).should == %w[c b a]
299
+ end
300
+
301
+ it 'should order by field with with filter' do
302
+ Product.where(name: %w[b c]).order(:title).reorder(:state).map(&:name).should == %w[c b]
303
+ Product.where(title: %w[b c]).order(:name).reorder(:state).map(&:name).should == %w[c b a]
304
+ end
305
+ end
306
+
307
+ describe '.where' do
308
+ let!(:attr1) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'info', backend_type: 'string', white_list: true) }
309
+ let!(:attr2) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'total', backend_type: 'integer', white_list: true) }
310
+ let!(:attr3) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: 'float', white_list: true) }
311
+ let!(:attr4) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'active', backend_type: 'boolean', white_list: true) }
312
+ let!(:attr5) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'started', backend_type: 'datetime', white_list: true) }
313
+
314
+ describe 'without attribute sets' do
315
+ before do
316
+ Product.create(name: 'a', info: 'a', total: 2, price: 3.5, active: true, started: '2013-01-01')
317
+ Product.create(name: 'b', info: 'a', total: 3, price: nil, active: false, started: '2013-01-02')
318
+ Product.create(name: 'c' ,info: 'b', total: nil, price: nil, active: nil, started: '2013-01-01')
319
+ Product.create(name: 'd', info: nil, total: 3, price: 3.5, active: true, started: nil)
320
+ end
321
+
322
+ it 'should filter by one attribute' do
323
+ Product.where(info: 'a').map(&:name).should =~ %w[a b]
324
+ Product.where(info: nil).map(&:name).should =~ %w[d]
325
+ Product.where(total: 3).map(&:name).should =~ %w[b d]
326
+ Product.where(total: nil).map(&:name).should =~ %w[c]
327
+ Product.where(price: 3.5).map(&:name).should =~ %w[a d]
328
+ Product.where(price: nil).map(&:name).should =~ %w[b c]
329
+ Product.where(active: true).map(&:name).should =~ %w[a d]
330
+ Product.where(active: false).map(&:name).should =~ %w[b]
331
+ Product.where(active: nil).map(&:name).should =~ %w[c]
332
+ Product.where(started: Time.utc('2013-01-01')).map(&:name).should =~ %w[a c]
333
+ Product.where(started: nil).map(&:name).should =~ %w[d]
334
+ end
335
+
336
+ it 'should filter by several attributes' do
337
+ Product.where(info: %w[a b], name: %w[b c]).map(&:name).should =~ %w[b c]
338
+ Product.where(info: %w[a b], price: nil).map(&:name).should =~ %w[b c]
339
+ Product.where(active: nil, started: Time.utc('2013-01-01')).map(&:name).should =~ %w[c]
340
+ Product.where(price: 3.5, started: nil).map(&:name).should =~ %w[d]
341
+ Product.where(total: 3, active: true).map(&:name).should =~ %w[d]
342
+ end
343
+ end
344
+
345
+ describe 'with attribute sets' do
346
+ before do
347
+ set1 = HydraAttribute::HydraSet.create(entity_type: 'Product', name: 'default')
348
+ set2 = HydraAttribute::HydraSet.create(entity_type: 'Product', name: 'second')
349
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: set1.id, hydra_attribute_id: attr1.id)
350
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: set2.id, hydra_attribute_id: attr2.id)
351
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: set1.id, hydra_attribute_id: attr3.id)
352
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: set2.id, hydra_attribute_id: attr4.id)
353
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: set1.id, hydra_attribute_id: attr5.id)
354
+
355
+ p1 = Product.create(name: 'a', info: 'a', total: 2, price: 3.5, active: true, started: '2013-01-01')
356
+ p2 = Product.create(name: 'b', info: 'a', total: 3, price: nil, active: false, started: '2013-01-02')
357
+ p3 = Product.create(name: 'c' ,info: 'b', total: nil, price: nil, active: nil, started: '2013-01-01')
358
+ p4 = Product.create(name: 'd', info: nil, total: 3, price: 3.5, active: true, started: nil)
359
+ p5 = Product.create(name: 'e', info: 'c', total: 7, price: 4.2, active: false, started: '2013-01-03')
360
+ p6 = Product.create(name: 'f', info: 'c', total: 5, price: 4.2, active: false, started: '2013-01-03')
361
+ p7 = Product.create(name: 'g', info: nil, total: 7, price: 5.5, active: nil, started: nil)
362
+ p1.hydra_set_id = nil
363
+ p2.hydra_set_id = set1.id
364
+ p3.hydra_set_id = set2.id
365
+ p4.hydra_set_id = set2.id
366
+ p5.hydra_set_id = set1.id
367
+ p6.hydra_set_id = set1.id
368
+ p7.hydra_set_id = nil
369
+ [p1, p2, p3, p4, p5, p6, p7].each(&:save)
370
+ end
371
+
372
+ it 'should filter by one attribute' do
373
+ Product.where(info: 'a').map(&:name).should =~ %w[a b]
374
+ Product.where(info: nil).map(&:name).should =~ %w[g]
375
+ Product.where(total: 3).map(&:name).should =~ %w[d]
376
+ Product.where(total: nil).map(&:name).should =~ %w[c]
377
+ Product.where(price: 3.5).map(&:name).should =~ %w[a]
378
+ Product.where(price: nil).map(&:name).should =~ %w[b]
379
+ Product.where(active: true).map(&:name).should =~ %w[a d]
380
+ Product.where(active: false).map(&:name).should == []
381
+ Product.where(active: nil).map(&:name).should =~ %w[c g]
382
+ Product.where(started: Time.utc('2013-01-01')).map(&:name).should =~ %w[a]
383
+ Product.where(started: nil).map(&:name).should =~ %w[g]
384
+ end
385
+
386
+ it 'should filter by several attributes' do
387
+ Product.where(info: ['a', 'b', 'c', nil], name: %w[a b c d e f g]).map(&:name).should =~ %w[a b e f g]
388
+ Product.where(info: %w[a b], price: nil).map(&:name).should =~ %w[b]
389
+ Product.where(active: nil, started: Time.utc('2013-01-01')).map(&:name).should == []
390
+ Product.where(price: 3.5, started: Time.utc('2013-01-01')).map(&:name).should =~ %w[a]
391
+ Product.where(total: [3, 5, 7], active: [true, false]).map(&:name).should =~ %w[d]
392
+ end
393
+ end
394
+ end
395
+
396
+ describe '.select' do
397
+ let!(:attr1) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'string', white_list: true) }
398
+ let!(:attr2) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'quantity', backend_type: 'integer', white_list: true) }
399
+ let!(:attr3) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'title', backend_type: 'string', white_list: true) }
400
+ let!(:attr4) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'active', backend_type: 'boolean', white_list: true) }
401
+ let!(:set1) { HydraAttribute::HydraSet.create(entity_type: 'Product', name: 'default') }
402
+ let!(:set2) { HydraAttribute::HydraSet.create(entity_type: 'Product', name: 'second') }
403
+
404
+ before do
405
+ HydraAttribute::HydraAttributeSet.create(hydra_attribute_id: attr1.id, hydra_set_id: set1.id)
406
+ HydraAttribute::HydraAttributeSet.create(hydra_attribute_id: attr2.id, hydra_set_id: set2.id)
407
+ HydraAttribute::HydraAttributeSet.create(hydra_attribute_id: attr3.id, hydra_set_id: set1.id)
408
+ HydraAttribute::HydraAttributeSet.create(hydra_attribute_id: attr4.id, hydra_set_id: set2.id)
409
+
410
+ Product.create(name: 'name1', code: 'code1', quantity: 1, title: 'title1', active: true, hydra_set_id: nil)
411
+ Product.create(name: 'name2', code: 'code2', quantity: 2, title: 'title2', active: false, hydra_set_id: set1.id)
412
+ Product.create(name: 'name3', code: 'code3', quantity: 3, title: 'title3', active: true, hydra_set_id: set2.id)
413
+ Product.create(name: 'name4', code: 'code4', quantity: 4, title: 'title4', active: false, hydra_set_id: set1.id)
414
+ end
415
+
416
+ it 'should select only specific attributes and return models which have all these attributes in the attribute set' do
417
+ relation = Product.select([:name, :code])
418
+ relation.map(&:name).should =~ %w[name1 name2 name4]
419
+ relation.map(&:code).should =~ %w[code1 code2 code4]
420
+
421
+ entity_without_set, entity_with_set = relation.partition { |entity| entity.hydra_set_id.nil? }
422
+ entity_without_set.should have(1).item
423
+ entity_with_set.should have(2).items
424
+
425
+ lambda { entity_without_set.map(&:quantity) }.should raise_error(HydraAttribute::HydraEntityAttributeAssociation::AttributeWasNotSelectedError, "Attribute ID #{attr2.id} was not selected from DB")
426
+ lambda { entity_without_set.map(&:title) }.should raise_error(HydraAttribute::HydraEntityAttributeAssociation::AttributeWasNotSelectedError, "Attribute ID #{attr3.id} was not selected from DB")
427
+ lambda { entity_without_set.map(&:active) }.should raise_error(HydraAttribute::HydraEntityAttributeAssociation::AttributeWasNotSelectedError, "Attribute ID #{attr4.id} was not selected from DB")
428
+
429
+ entity_with_set.each do |entity|
430
+ lambda { entity.quantity }.should raise_error(HydraAttribute::HydraSet::MissingAttributeInHydraSetError, "Attribute ID #{attr2.id} is missed in Set ID #{set1.id}")
431
+ lambda { entity.title }.should raise_error(HydraAttribute::HydraEntityAttributeAssociation::AttributeWasNotSelectedError, "Attribute ID #{attr3.id} was not selected from DB")
432
+ lambda { entity.active }.should raise_error(HydraAttribute::HydraSet::MissingAttributeInHydraSetError, "Attribute ID #{attr4.id} is missed in Set ID #{set1.id}")
433
+ end
434
+
435
+ relation = Product.select([:name, :quantity])
436
+ relation.map(&:name).should =~ %w[name1 name3]
437
+ relation.map(&:quantity).should =~ [1, 3]
438
+
439
+ entity_without_set, entity_with_set = relation.partition { |entity| entity.hydra_set_id.nil? }
440
+ entity_without_set.should have(1).item
441
+ entity_with_set.should have(1).item
442
+
443
+ lambda { entity_without_set.map(&:code) }.should raise_error(HydraAttribute::HydraEntityAttributeAssociation::AttributeWasNotSelectedError, "Attribute ID #{attr1.id} was not selected from DB")
444
+ lambda { entity_without_set.map(&:title) }.should raise_error(HydraAttribute::HydraEntityAttributeAssociation::AttributeWasNotSelectedError, "Attribute ID #{attr3.id} was not selected from DB")
445
+ lambda { entity_without_set.map(&:active) }.should raise_error(HydraAttribute::HydraEntityAttributeAssociation::AttributeWasNotSelectedError, "Attribute ID #{attr4.id} was not selected from DB")
446
+
447
+ lambda { entity_with_set.map(&:code) }.should raise_error(HydraAttribute::HydraSet::MissingAttributeInHydraSetError, "Attribute ID #{attr1.id} is missed in Set ID #{set2.id}")
448
+ lambda { entity_with_set.map(&:title) }.should raise_error(HydraAttribute::HydraSet::MissingAttributeInHydraSetError, "Attribute ID #{attr3.id} is missed in Set ID #{set2.id}")
449
+ lambda { entity_with_set.map(&:active) }.should raise_error(HydraAttribute::HydraEntityAttributeAssociation::AttributeWasNotSelectedError, "Attribute ID #{attr4.id} was not selected from DB")
450
+ end
451
+
452
+ it 'should be able to apply filter condition' do
453
+ relation = Product.select([:name, :code]).where(code: %w[code2 code3 code4])
454
+ relation.map(&:name).should =~ %w[name2 name4]
455
+ relation.map(&:code).should =~ %w[code2 code4]
456
+ end
457
+
458
+ it 'select attributes which were created after entities and their values should be always nil' do
459
+ attr = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'color', backend_type: 'string', default_value: 'red')
460
+ HydraAttribute::HydraAttributeSet.create(hydra_attribute_id: attr.id, hydra_set_id: set1.id)
461
+
462
+ relation = Product.select([:name, :color])
463
+ relation.map(&:name).should =~ %w[name1 name2 name4]
464
+ relation.map(&:color).should == [nil, nil, nil]
465
+ end
466
+ end
467
+
468
+ describe '#save' do
469
+ let!(:attr_id) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'string', default_value: 'abc').id.to_i }
470
+
471
+ describe 'new model' do
472
+ let(:product) { Product.new }
473
+
474
+ it 'should save with default attribute values' do
475
+ product.save
476
+ value = ::ActiveRecord::Base.connection.select_value("SELECT value FROM hydra_string_products WHERE entity_id = #{product.id} AND hydra_attribute_id = #{attr_id}")
477
+ value.should == 'abc'
478
+ end
479
+
480
+ it 'should save changed attribute value' do
481
+ product.code = 'qwe'
482
+ product.save
483
+ value = ::ActiveRecord::Base.connection.select_value("SELECT value FROM hydra_string_products WHERE entity_id = #{product.id} AND hydra_attribute_id = #{attr_id}")
484
+ value.should == 'qwe'
485
+ end
486
+
487
+ it 'should save only attributes which are belong to hydra set' do
488
+ attr_id2 = HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'color', backend_type: 'string', white_list: true).id
489
+ set_id = HydraAttribute::HydraSet.create(entity_type: 'Product', name: 'default').id
490
+ HydraAttribute::HydraAttributeSet.create(hydra_set_id: set_id, hydra_attribute_id: attr_id2)
491
+
492
+ product.code = 'qwerty'
493
+ product.color = 'green'
494
+ product.hydra_set_id = set_id
495
+ product.save
496
+
497
+ attr1 = ::ActiveRecord::Base.connection.select_value("SELECT value FROM hydra_string_products WHERE entity_id = #{product.id} AND hydra_attribute_id = #{attr_id}")
498
+ attr1.should be_nil
499
+
500
+ attr2 = ::ActiveRecord::Base.connection.select_value("SELECT value FROM hydra_string_products WHERE entity_id = #{product.id} AND hydra_attribute_id = #{attr_id2}")
501
+ attr2.should == 'green'
502
+ end
503
+ end
504
+
505
+ describe 'persisted model' do
506
+ let(:product) { Product.create }
507
+
508
+ it 'should not touch entity if hydra attributes were not changed' do
509
+ updated_at = product.updated_at
510
+ product.save
511
+ product.updated_at.should == updated_at
512
+ end
513
+
514
+ it 'should touch entity if hydra attributes were changed' do
515
+ updated_at = product.updated_at
516
+ product.code = 'qwe'
517
+ product.save
518
+ product.updated_at.should > updated_at
519
+ end
520
+ end
521
+ end
522
+
523
+ describe '#destroy' do
524
+ let!(:attr1) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'title', backend_type: 'string', white_list: true) }
525
+ let!(:attr2) { HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'integer', white_list: true) }
526
+
527
+ let(:find_query) { ->(entity_id, attr) { "SELECT value FROM hydra_#{attr.backend_type}_products WHERE entity_id = #{entity_id} AND hydra_attribute_id = #{attr.id}" } }
528
+ let(:find_value) { ->(entity_id, attr) { ::ActiveRecord::Base.connection.select_value(find_query.(entity_id, attr)) } }
529
+
530
+ it 'should destroy all saved attributes for current entity' do
531
+ product1 = Product.create(title: 'abc', code: 42)
532
+ product2 = Product.create(title: 'qwe', code: 55)
533
+
534
+ find_value.(product1.id, attr1).should == 'abc'
535
+ find_value.(product1.id, attr2).to_i.should == 42
536
+ find_value.(product2.id, attr1).should == 'qwe'
537
+ find_value.(product2.id, attr2).to_i.should == 55
538
+ product1.destroy
539
+ find_value.(product1.id, attr1).should be_nil
540
+ find_value.(product1.id, attr2).should be_nil
541
+ find_value.(product2.id, attr1).should == 'qwe'
542
+ find_value.(product2.id, attr2).to_i.should == 55
543
+ end
544
+ end
545
+
546
+ describe '#attributes' do
547
+ it 'should return entity attributes with its hydra attributes' do
548
+ product = Product.new
549
+ product.attributes.should == {'id'=>nil, 'hydra_set_id'=>nil, 'name'=>nil, 'created_at'=>nil, 'updated_at'=>nil}
550
+
551
+ a1 = Product.hydra_attributes.create(name: 'total', backend_type: 'decimal', default_value: 5)
552
+ a2 = Product.hydra_attributes.create(name: 'title', backend_type: 'string', default_value: 'one')
553
+
554
+ product = Product.new
555
+ product.attributes.should == {'id'=>nil, 'hydra_set_id'=>nil, 'name'=>nil, 'created_at'=>nil, 'updated_at'=>nil, 'total'=>5, 'title'=>'one'}
556
+
557
+ set = Product.hydra_sets.create(name: 'default')
558
+ HydraAttribute::HydraAttributeSet.create(hydra_attribute_id: a1.id, hydra_set_id: set.id)
559
+
560
+ product.hydra_set_id = set.id
561
+ product.attributes.should == {'id'=>nil, 'hydra_set_id'=>set.id, 'name'=>nil, 'created_at'=>nil, 'updated_at'=>nil, 'total'=>5}
562
+ end
563
+ end
564
+
565
+ describe '#inspect' do
566
+ before do
567
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'code', backend_type: 'string', default_value: 'one')
568
+ HydraAttribute::HydraAttribute.create(entity_type: 'Product', name: 'price', backend_type: 'float', default_value: 5)
569
+ end
570
+
571
+ let(:product) { Product.new }
572
+
573
+ it 'should include hydra attributes in inspection string too' do
574
+ product.inspect.should == '#<Product id: nil, hydra_set_id: nil, name: nil, created_at: nil, updated_at: nil, code: "one", price: 5.0>'
575
+ end
576
+ end
577
+ end