trax_model 0.0.98 → 0.0.99

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -0
  3. data/lib/trax/model.rb +6 -16
  4. data/lib/trax/model/attributes.rb +1 -1
  5. data/lib/trax/model/attributes/definitions.rb +4 -0
  6. data/lib/trax/model/attributes/{mixin.rb → dsl.rb} +2 -12
  7. data/lib/trax/model/attributes/types/boolean.rb +1 -2
  8. data/lib/trax/model/attributes/types/enum.rb +0 -2
  9. data/lib/trax/model/attributes/types/integer.rb +2 -2
  10. data/lib/trax/model/attributes/types/set.rb +67 -0
  11. data/lib/trax/model/attributes/types/string.rb +3 -3
  12. data/lib/trax/model/attributes/types/struct.rb +5 -3
  13. data/lib/trax/model/attributes/types/uuid_array.rb +0 -2
  14. data/lib/trax/model/{sti.rb → core_extensions.rb} +2 -2
  15. data/lib/trax/model/core_extensions/string.rb +17 -0
  16. data/lib/trax/model/extensions_for.rb +18 -0
  17. data/lib/trax/model/extensions_for/base.rb +31 -0
  18. data/lib/trax/model/extensions_for/boolean.rb +29 -0
  19. data/lib/trax/model/extensions_for/enumerable.rb +18 -0
  20. data/lib/trax/model/extensions_for/integer.rb +10 -0
  21. data/lib/trax/model/extensions_for/numeric.rb +46 -0
  22. data/lib/trax/model/extensions_for/set.rb +10 -0
  23. data/lib/trax/model/extensions_for/string.rb +30 -0
  24. data/lib/trax/model/extensions_for/struct.rb +191 -0
  25. data/lib/trax/model/extensions_for/struct_fields.rb +21 -0
  26. data/lib/trax/model/extensions_for/struct_fields/boolean.rb +32 -0
  27. data/lib/trax/model/extensions_for/struct_fields/enum.rb +20 -0
  28. data/lib/trax/model/extensions_for/struct_fields/float.rb +12 -0
  29. data/lib/trax/model/extensions_for/struct_fields/integer.rb +12 -0
  30. data/lib/trax/model/extensions_for/struct_fields/numeric.rb +52 -0
  31. data/lib/trax/model/extensions_for/struct_fields/string.rb +29 -0
  32. data/lib/trax/model/extensions_for/struct_fields/time.rb +54 -0
  33. data/lib/trax/model/matchable.rb +3 -10
  34. data/lib/trax/model/mixins.rb +3 -0
  35. data/lib/trax/model/mixins/freezable.rb +31 -0
  36. data/lib/trax/model/mixins/restorable.rb +63 -0
  37. data/lib/trax/model/mixins/sti_enum.rb +4 -5
  38. data/lib/trax/model/mixins/unique_id.rb +85 -0
  39. data/lib/trax/model/railtie.rb +4 -2
  40. data/lib/trax/validators/json_attribute_validator.rb +1 -0
  41. data/lib/trax_model/version.rb +1 -1
  42. data/spec/db/schema/default_tables.rb +1 -17
  43. data/spec/db/schema/pg_tables.rb +15 -0
  44. data/spec/support/models.rb +11 -16
  45. data/spec/support/pg/models.rb +31 -6
  46. data/spec/trax/model/attributes/types/set_spec.rb +68 -0
  47. data/spec/trax/model/attributes/types/struct_spec.rb +6 -0
  48. data/spec/trax/model/extensions_for/boolean_spec.rb +26 -0
  49. data/spec/trax/model/extensions_for/numeric_spec.rb +53 -0
  50. data/spec/trax/model/extensions_for/string_spec.rb +25 -0
  51. data/spec/trax/model/extensions_for/struct_spec.rb +223 -0
  52. data/spec/trax/model/extensions_for_spec.rb +0 -0
  53. data/spec/trax/model/{freezable_spec.rb → mixins/freezable_spec.rb} +1 -1
  54. data/spec/trax/model/{restorable_spec.rb → mixins/restorable_spec.rb} +1 -1
  55. data/spec/trax/model/{unique_id_spec.rb → mixins/unique_id_spec.rb} +1 -1
  56. data/trax_model.gemspec +4 -5
  57. metadata +49 -59
  58. data/lib/trax/model/enum.rb +0 -64
  59. data/lib/trax/model/freezable.rb +0 -29
  60. data/lib/trax/model/mti.rb +0 -11
  61. data/lib/trax/model/mti/abstract.rb +0 -65
  62. data/lib/trax/model/mti/entity.rb +0 -62
  63. data/lib/trax/model/mti/namespace.rb +0 -21
  64. data/lib/trax/model/restorable.rb +0 -61
  65. data/lib/trax/model/scopes.rb +0 -16
  66. data/lib/trax/model/sti/attributes.rb +0 -94
  67. data/lib/trax/model/string_extensions.rb +0 -11
  68. data/lib/trax/model/struct_extensions.rb +0 -185
  69. data/lib/trax/model/unique_id.rb +0 -83
  70. data/spec/trax/model/sti/attributes_spec.rb +0 -15
  71. data/spec/trax/model/struct_extensions_spec.rb +0 -16
@@ -3,14 +3,14 @@ module Ecommerce
3
3
  self.table_name = "ecommerce_product_attribute_sets"
4
4
 
5
5
  include ::Trax::Model
6
- include ::Trax::Model::Attributes::Mixin
6
+ include ::Trax::Model::Attributes::Dsl
7
7
 
8
8
  mixins :unique_id => { :uuid_prefix => "c2" }
9
9
  end
10
10
 
11
11
  class ShippingAttributes < ::Ecommerce::ProductAttributeSet
12
12
  include ::Trax::Model
13
- include ::Trax::Model::Attributes::Mixin
13
+ include ::Trax::Model::Attributes::Dsl
14
14
 
15
15
  define_attributes do
16
16
  struct :specifics, :model_accessors => true, :validate => true do
@@ -42,11 +42,34 @@ module Ecommerce
42
42
  end
43
43
  end
44
44
 
45
+ class User < ::ActiveRecord::Base
46
+ self.table_name = "ecommerce_users"
47
+
48
+ include ::Trax::Model
49
+ include ::Trax::Model::Attributes::Dsl
50
+
51
+ mixins :unique_id => { :uuid_prefix => "9b" }
52
+ end
53
+
54
+ class Vote < ::ActiveRecord::Base
55
+ self.table_name = "ecommerce_votes"
56
+
57
+ include ::Trax::Model
58
+ include ::Trax::Model::Attributes::Dsl
59
+
60
+ mixins :unique_id => { :uuid_prefix => "9d" }
61
+
62
+ define_attributes do
63
+ set :upvoter_ids
64
+ set :downvoter_ids
65
+ end
66
+ end
67
+
45
68
  class Product < ::ActiveRecord::Base
46
69
  self.table_name = "ecommerce_products"
47
70
 
48
71
  include ::Trax::Model
49
- include ::Trax::Model::Attributes::Mixin
72
+ include ::Trax::Model::Attributes::Dsl
50
73
 
51
74
  mixins :unique_id => { :uuid_prefix => "9a" }
52
75
 
@@ -66,10 +89,12 @@ module Ecommerce
66
89
 
67
90
  struct :custom_fields do
68
91
  integer :cost
69
- integer :price
70
92
  integer :in_stock_quantity, :default => 0
71
93
  integer :number_of_sales, :default => 0
94
+ float :price
72
95
  time :last_received_at
96
+ string :slug
97
+ string :display_name
73
98
 
74
99
  define_model_scope_for :in_stock_quantity, :as => :by_quantity_in_stock
75
100
  define_model_scope_for :last_received_at, :as => :by_last_received_at
@@ -80,7 +105,7 @@ module Ecommerce
80
105
  module Products
81
106
  class Shoes < ::Ecommerce::Product
82
107
  include ::Trax::Model
83
- include ::Trax::Model::Attributes::Mixin
108
+ include ::Trax::Model::Attributes::Dsl
84
109
 
85
110
  define_attributes do
86
111
  end
@@ -88,7 +113,7 @@ module Ecommerce
88
113
 
89
114
  class MensShoes < ::Ecommerce::Products::Shoes
90
115
  include ::Trax::Model
91
- include ::Trax::Model::Attributes::Mixin
116
+ include ::Trax::Model::Attributes::Dsl
92
117
 
93
118
  define_attributes do
94
119
  string :name, :default => "Some Shoe Name"
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Trax::Model::Attributes::Types::Set, :postgres => true do
4
+ subject{ ::Ecommerce::Vote.new(:upvoter_ids => [1, 2], :downvoter_ids => [3, 4, 5] )}
5
+
6
+ it { expect(subject.upvoter_ids.__getobj__).to be_a(::Set) }
7
+ it { expect(subject.upvoter_ids).to include(1) }
8
+
9
+ context "attribute definition" do
10
+ subject { ::Ecommerce::Vote::Fields::UpvoterIds.new }
11
+ it { expect(subject.__getobj__).to be_a(::Set) }
12
+ end
13
+
14
+ context "loading from database" do
15
+ it {
16
+ subject.save
17
+ test_subject = subject.reload
18
+ expect(test_subject.upvoter_ids).to include(1)
19
+ }
20
+ end
21
+
22
+ context "does not allow duplicate values" do
23
+ it {
24
+ subject.upvoter_ids << 1
25
+ expect(subject.upvoter_ids.length).to eq 2
26
+ }
27
+ end
28
+
29
+ context "dirty tracking" do
30
+ it {
31
+ subject.save
32
+ subject.upvoter_ids = [2,3]
33
+ expect(subject.upvoter_ids_was).to eq ::Set.new([1,2])
34
+ }
35
+ end
36
+
37
+ #note: only supports string values for scopes at the moment
38
+ #also note: I think this is the ideal api for the future.
39
+ #I.e. define a scope on the model, by referencing the field directly.
40
+ context "relations" do
41
+ let!(:record_one) {
42
+ ::Ecommerce::Vote.create(:upvoter_ids => ['1', '2'], :downvoter_ids => ['3', '4', '5'] )
43
+ }
44
+ let!(:record_two) {
45
+ ::Ecommerce::Vote.create(:upvoter_ids => ['3', '4'], :downvoter_ids => ['6', '7', '8'] )
46
+ }
47
+ it {
48
+ expect(
49
+ ::Ecommerce::Vote::Fields::UpvoterIds.contains("1")
50
+ ).to include record_one
51
+ }
52
+ it {
53
+ expect(
54
+ ::Ecommerce::Vote::Fields::UpvoterIds.contains("1")
55
+ ).to_not include record_two
56
+ }
57
+ it {
58
+ expect(
59
+ ::Ecommerce::Vote::Fields::UpvoterIds.contains("4")
60
+ ).to include record_two
61
+ }
62
+ it {
63
+ expect(
64
+ ::Ecommerce::Vote::Fields::UpvoterIds.contains("4")
65
+ ).to_not include record_one
66
+ }
67
+ end
68
+ end
@@ -16,6 +16,12 @@ describe ::Trax::Model::Attributes::Types::Struct, :postgres => true do
16
16
  end
17
17
  }
18
18
 
19
+ it {
20
+ ::Ecommerce::ShippingAttributes.fields[:specifics].properties.each do |_property|
21
+ expect(subject.class.attribute_names).to include(_property.to_s)
22
+ end
23
+ }
24
+
19
25
  context "initializing model and setting delegated attributes directly", :delegated_attributes => { :cost => 5, :tax => 5, :delivery_time => "5 days" } do
20
26
  self::DELEGATED_ATTRIBUTES = { :cost => 5, :tax => 5, :delivery_time => "5 days" }
21
27
 
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Trax::Model::ExtensionsFor::Boolean do
4
+ subject{ ::Product }
5
+
6
+ let!(:product_one) {
7
+ ::Product.create(:name => "DC Villan Size 6", :active => true)
8
+ }
9
+ let!(:product_two) {
10
+ ::Product.create(:name => "DC Villan Size 7", :active => false)
11
+ }
12
+
13
+ context ".eq" do
14
+ it { expect(subject.fields[:active].eq(true, false)).to include(product_one, product_two) }
15
+ end
16
+
17
+ context ".is_true" do
18
+ it { expect(subject.fields[:active].is_true).to include(product_one) }
19
+ it { expect(subject.fields[:active].is_true).to_not include(product_two) }
20
+ end
21
+
22
+ context ".is_false" do
23
+ it { expect(subject.fields[:active].is_false).to_not include(product_one) }
24
+ it { expect(subject.fields[:active].is_false).to include(product_two) }
25
+ end
26
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Trax::Model::ExtensionsFor::Numeric do
4
+ subject{ ::Product }
5
+
6
+ let!(:product_one) {
7
+ ::Product.create(:name => "DC Villan Size 6", :in_stock_quantity => 5)
8
+ }
9
+ let!(:product_two) {
10
+ ::Product.create(:name => "DC Villan Size 7", :in_stock_quantity => 9)
11
+ }
12
+
13
+ context "Integer" do
14
+ context ".between" do
15
+ it { expect(subject.fields[:in_stock_quantity].between(5, 10)).to include(product_two) }
16
+ it { expect(subject.fields[:in_stock_quantity].between(5, 10)).to_not include(product_one) }
17
+ end
18
+
19
+ context ".eq" do
20
+ it { expect(subject.fields[:in_stock_quantity].eq(5)).to include(product_one) }
21
+ it { expect(subject.fields[:in_stock_quantity].eq(5)).to_not include(product_two) }
22
+ it { expect(subject.fields[:in_stock_quantity].eq(5,9)).to include(product_two, product_one) }
23
+ end
24
+
25
+ context ".gt" do
26
+ it { expect(subject.fields[:in_stock_quantity].gt(5)).to include(product_two) }
27
+ it { expect(subject.fields[:in_stock_quantity].gt(5)).to_not include(product_one) }
28
+ end
29
+
30
+ context ".lt" do
31
+ it { expect(subject.fields[:in_stock_quantity].lt(9)).to include(product_one) }
32
+ it { expect(subject.fields[:in_stock_quantity].lt(5)).to_not include(product_two) }
33
+ end
34
+ end
35
+
36
+ # context "Integer" do
37
+ # context ".eq" do
38
+ # it { expect(subject.fields[:in_stock_quantity].eq(5)).to include(product_one) }
39
+ # it { expect(subject.fields[:in_stock_quantity].eq(5)).to_not include(product_two) }
40
+ # it { expect(subject.fields[:in_stock_quantity].eq(5,9)).to include(product_two, product_one) }
41
+ # end
42
+ #
43
+ # context ".gt" do
44
+ # it { expect(subject.fields[:in_stock_quantity].gt(5)).to include(product_two) }
45
+ # it { expect(subject.fields[:in_stock_quantity].gt(5)).to_not include(product_one) }
46
+ # end
47
+ #
48
+ # context ".lt" do
49
+ # it { expect(subject.fields[:in_stock_quantity].lt(9)).to include(product_one) }
50
+ # it { expect(subject.fields[:in_stock_quantity].lt(5)).to_not include(product_two) }
51
+ # end
52
+ # end
53
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Trax::Model::ExtensionsFor::String do
4
+ subject{ ::Product }
5
+
6
+ let!(:product_one) {
7
+ ::Product.create(:name => "DC Villan Size 6")
8
+ }
9
+ let!(:product_two) {
10
+ ::Product.create(:name => "DC Villan Size 7")
11
+ }
12
+
13
+ context ".eq" do
14
+ it { expect(subject.fields[:name].eq("DC Villan Size 6")).to include(product_one) }
15
+ it { expect(subject.fields[:name].eq("DC Villan Size 7")).to_not include(product_one) }
16
+ end
17
+
18
+ context ".eq_lower" do
19
+ it { expect(subject.fields[:name].eq_lower("dc Villan Size 6")).to include(product_one) }
20
+ end
21
+
22
+ context ".matches", :postgres => true do
23
+ it { expect(subject.fields[:name].matches("dc")).to include(product_one, product_two) }
24
+ end
25
+ end
@@ -0,0 +1,223 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Trax::Model::ExtensionsFor::Struct, :postgres => true do
4
+ subject{ ::Ecommerce::Products::MensShoes }
5
+
6
+ let(:product_one_last_received_at) { ::Time.now - 10.days }
7
+ let(:product_two_last_received_at) { ::Time.now - 5.days }
8
+ let(:product_one_size) { :mens_6 }
9
+ let(:product_two_size) { :mens_7 }
10
+
11
+ let!(:product_one) {
12
+ ::Ecommerce::Products::MensShoes.create(
13
+ "name" => "DC Villan Size 6",
14
+ "custom_fields" => {
15
+ "size" => product_one_size,
16
+ "slug" => "dc-villan-size-6",
17
+ "has_shoelaces" => true,
18
+ "display_name" => "DC Villan Mens Shoes Size 6",
19
+ "last_received_at" => product_one_last_received_at,
20
+ "cost" => 15,
21
+ "price" => 29.99
22
+ }
23
+ )
24
+ }
25
+
26
+ let!(:product_two) {
27
+ ::Ecommerce::Products::MensShoes.create(
28
+ "name" => "DC Villan Size 7",
29
+ "custom_fields" => {
30
+ "size" => product_two_size,
31
+ "slug" => "dc-villan-size-7",
32
+ "has_shoelaces" => false,
33
+ "display_name" => "DC Villan Mens Shoes Size 7",
34
+ "last_received_at" => product_two_last_received_at,
35
+ "cost" => 20,
36
+ "price" => 39.99
37
+ }
38
+ )
39
+ }
40
+
41
+ context "boolean" do
42
+ context "eq" do
43
+ it {
44
+ expect(subject.fields[:custom_fields][:has_shoelaces].eq(true, false)).to include(product_one, product_two)
45
+ }
46
+ end
47
+
48
+ context "is_true" do
49
+ it {
50
+ expect(subject.fields[:custom_fields][:has_shoelaces].is_true).to include(product_one)
51
+ }
52
+ it {
53
+ expect(subject.fields[:custom_fields][:has_shoelaces].is_true).to_not include(product_two)
54
+ }
55
+ end
56
+
57
+ context "is_false" do
58
+ it {
59
+ expect(subject.fields[:custom_fields][:has_shoelaces].is_false).to include(product_two)
60
+ }
61
+ it {
62
+ expect(subject.fields[:custom_fields][:has_shoelaces].is_false).to_not include(product_one)
63
+ }
64
+ end
65
+
66
+ context "is_nil" do
67
+ it {
68
+ expect(subject.fields[:custom_fields][:has_shoelaces].is_nil).to_not include(product_one, product_two)
69
+ }
70
+ end
71
+ end
72
+
73
+ context "enum" do
74
+ context "eq" do
75
+ it {
76
+ expect(subject.fields[:custom_fields][:size].eq(product_two_size)).to include(product_two)
77
+ }
78
+ it {
79
+ expect(subject.fields[:custom_fields][:size].eq(product_two_size)).to_not include(product_one)
80
+ }
81
+ it {
82
+ expect(subject.fields[:custom_fields][:size].eq(product_two_size, product_one_size)).to include(product_one, product_two)
83
+ }
84
+ it {
85
+ expect(subject.fields[:custom_fields][:size].eq(1,2)).to include(product_one, product_two)
86
+ }
87
+ end
88
+ end
89
+
90
+ context "string" do
91
+ context "eq" do
92
+ it {
93
+ expect(subject.fields[:custom_fields].fields[:slug].eq("dc-villan-size-6")).to include(product_one)
94
+ }
95
+ it {
96
+ expect(subject.fields[:custom_fields].fields[:slug].eq("dc-villan-size-6")).to_not include(product_two)
97
+ }
98
+ it {
99
+ expect(subject.fields[:custom_fields].fields[:slug].eq("dc-villan-size-6", "dc-villan-size-7")).to include(product_two, product_one)
100
+ }
101
+ end
102
+
103
+ context "eq_lower" do
104
+ it {
105
+ expect(subject.fields[:custom_fields].fields[:display_name].eq_lower("dc villan mens shoes size 6")).to include(product_one)
106
+ }
107
+ it {
108
+ expect(subject.fields[:custom_fields].fields[:display_name].eq_lower("DC Villan Mens Shoes Size 6", "DC Villan Mens Shoes Size 7")).to include(product_one, product_two)
109
+ }
110
+ it {
111
+ expect(subject.fields[:custom_fields].fields[:display_name].eq_lower("DC Villan Mens Shoes Size 7")).to_not include(product_one)
112
+ }
113
+ end
114
+
115
+ context "matches" do
116
+ it {
117
+ expect(subject.fields[:custom_fields].fields[:slug].matches("dc-villan-size")).to include(product_one, product_two)
118
+ }
119
+ it {
120
+ expect(subject.fields[:custom_fields].fields[:slug].matches("blah")).to_not include(product_one, product_two)
121
+ }
122
+ end
123
+ end
124
+
125
+ context "time" do
126
+ context "after" do
127
+ it {
128
+ expect(subject.fields[:custom_fields].fields[:last_received_at].after(::Time.now - 6.days)).to include(product_two)
129
+ }
130
+ it {
131
+ expect(subject.fields[:custom_fields].fields[:last_received_at].after(::Time.now - 6.days)).to_not include(product_one)
132
+ }
133
+ end
134
+
135
+ context "before" do
136
+ it {
137
+ expect(subject.fields[:custom_fields].fields[:last_received_at].before(::Time.now - 6.days)).to include(product_one)
138
+ }
139
+ it {
140
+ expect(subject.fields[:custom_fields].fields[:last_received_at].before(::Time.now - 6.days)).to_not include(product_two)
141
+ }
142
+ end
143
+
144
+ context "between" do
145
+ let(:start_time) { ::Time.now - 6.days}
146
+ let(:end_time) { ::Time.now - 4.days }
147
+ it {
148
+ expect(subject.fields[:custom_fields].fields[:last_received_at].between(start_time, end_time)).to include(product_two)
149
+ }
150
+ it {
151
+ expect(subject.fields[:custom_fields].fields[:last_received_at].between(start_time, end_time)).to_not include(product_one)
152
+ }
153
+ end
154
+ end
155
+
156
+ context "float" do
157
+ context "eq" do
158
+ it {
159
+ expect(subject.fields[:custom_fields].fields[:price].eq(29.99)).to include(product_one)
160
+ }
161
+ it {
162
+ expect(subject.fields[:custom_fields].fields[:price].eq(29.99)).to_not include(product_two)
163
+ }
164
+ it {
165
+ expect(subject.fields[:custom_fields].fields[:price].eq(29.99, 39.99)).to include(product_two)
166
+ }
167
+ end
168
+
169
+ context "gt" do
170
+ it {
171
+ expect(subject.fields[:custom_fields].fields[:price].gt(29.99)).to include(product_two)
172
+ }
173
+ it {
174
+ expect(subject.fields[:custom_fields].fields[:price].gt(29.99)).to_not include(product_one)
175
+ }
176
+ it {
177
+ expect(subject.fields[:custom_fields].fields[:price].gt(29.99)).to_not include(product_one)
178
+ }
179
+ end
180
+
181
+ context "gte" do
182
+ it {
183
+ expect(subject.fields[:custom_fields].fields[:price].gte(39.99)).to include(product_two)
184
+ }
185
+ it {
186
+ expect(subject.fields[:custom_fields].fields[:price].gte(39.99)).to_not include(product_one)
187
+ }
188
+ end
189
+
190
+ context "lt" do
191
+ it {
192
+ expect(subject.fields[:custom_fields].fields[:price].lt(39.99)).to include(product_one)
193
+ }
194
+ it {
195
+ expect(subject.fields[:custom_fields].fields[:price].gt(39.99)).to_not include(product_two)
196
+ }
197
+ end
198
+
199
+ context "lte" do
200
+ it {
201
+ expect(subject.fields[:custom_fields].fields[:price].lte(29.99)).to include(product_one)
202
+ }
203
+ it {
204
+ expect(subject.fields[:custom_fields].fields[:price].lte(29.99)).to_not include(product_two)
205
+ }
206
+ end
207
+
208
+ context "between" do
209
+ it {
210
+ expect(subject.fields[:custom_fields].fields[:price].between(28.99, 30.00)).to include(product_one)
211
+ }
212
+ it {
213
+ expect(subject.fields[:custom_fields].fields[:price].between(29.99, 30.00)).to_not include(product_one)
214
+ }
215
+ end
216
+
217
+ context "in_range" do
218
+ it {
219
+ expect(subject.fields[:custom_fields].fields[:price].in_range(29.99, 30.00)).to include(product_one)
220
+ }
221
+ end
222
+ end
223
+ end