hstore_accessor 0.9.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/hstore_accessor.gemspec +1 -1
- data/lib/hstore_accessor.rb +2 -2
- data/lib/hstore_accessor/active_record_4.2/type_helpers.rb +1 -1
- data/lib/hstore_accessor/{active_record_pre_4.2 → active_record_<_4.2}/time_helper.rb +0 -0
- data/lib/hstore_accessor/{active_record_pre_4.2 → active_record_<_4.2}/type_helpers.rb +1 -1
- data/lib/hstore_accessor/macro.rb +3 -6
- data/lib/hstore_accessor/serialization.rb +0 -8
- data/lib/hstore_accessor/version.rb +1 -1
- data/spec/hstore_accessor_spec.rb +6 -104
- data/spec/spec_helper.rb +0 -8
- metadata +6 -7
- data/.ruby-version +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3b755ac2d804d78400da381e4cad63a68647145
|
4
|
+
data.tar.gz: 7737c2ce560de5ab95fd750234bd7293386b1ab6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 099b5d22584a1734c72760a026dd42898be87ed7d0df5bd2abc0be60d742df11efa341cb6596c3618524db9bf6d0fd5358a98d1d29fed9429d5fb47c2b5da2e2
|
7
|
+
data.tar.gz: eb978d8c446b53413fd04737a920e7961d61481687cf2de0235c588fc22469c0db949ee4e55e901ef1e388fec2baf8e16d7ae7a96d149696ede082027189e6e6
|
data/hstore_accessor.gemspec
CHANGED
@@ -31,5 +31,5 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_development_dependency "rubocop"
|
32
32
|
spec.add_development_dependency "shoulda-matchers"
|
33
33
|
|
34
|
-
spec.post_install_message = "Please note that the `array` and `hash` types
|
34
|
+
spec.post_install_message = "Please note that the `array` and `hash` types are no longer supported in version 1.0.0"
|
35
35
|
end
|
data/lib/hstore_accessor.rb
CHANGED
@@ -5,8 +5,8 @@ require "hstore_accessor/version"
|
|
5
5
|
if ::ActiveRecord::VERSION::STRING.to_f >= 4.2
|
6
6
|
require "hstore_accessor/active_record_4.2/type_helpers"
|
7
7
|
else
|
8
|
-
require "hstore_accessor/
|
9
|
-
require "hstore_accessor/
|
8
|
+
require "hstore_accessor/active_record_<_4.2/type_helpers"
|
9
|
+
require "hstore_accessor/active_record_<_4.2/time_helper"
|
10
10
|
end
|
11
11
|
|
12
12
|
require "hstore_accessor/serialization"
|
File without changes
|
@@ -92,7 +92,7 @@ module HstoreAccessor
|
|
92
92
|
hstore_changes = send("#{hstore_attribute}_change")
|
93
93
|
return if hstore_changes.nil?
|
94
94
|
attribute_changes = hstore_changes.map { |change| change.try(:[], store_key.to_s) }
|
95
|
-
attribute_changes.
|
95
|
+
attribute_changes.compact.present? ? attribute_changes : nil
|
96
96
|
end
|
97
97
|
|
98
98
|
define_method("restore_#{key}!") do
|
@@ -115,8 +115,8 @@ module HstoreAccessor
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
-
query_field = "#{
|
119
|
-
eq_query_field = "#{
|
118
|
+
query_field = "#{hstore_attribute} -> '#{store_key}'"
|
119
|
+
eq_query_field = "#{hstore_attribute} @> hstore('#{store_key}', ?)"
|
120
120
|
|
121
121
|
case data_type
|
122
122
|
when :string
|
@@ -144,9 +144,6 @@ module HstoreAccessor
|
|
144
144
|
when :boolean
|
145
145
|
send(:scope, "is_#{key}", -> { where(eq_query_field, "true") })
|
146
146
|
send(:scope, "not_#{key}", -> { where(eq_query_field, "false") })
|
147
|
-
when :array
|
148
|
-
send(:scope, "#{key}_eq", -> value { where("#{query_field} = ?", value.join(Serialization::SEPARATOR)) })
|
149
|
-
send(:scope, "#{key}_contains", -> value { where("string_to_array(#{query_field}, '#{Serialization::SEPARATOR}') @> string_to_array(?, '#{Serialization::SEPARATOR}')", Array[value].flatten.join(Serialization::SEPARATOR)) })
|
150
147
|
end
|
151
148
|
end
|
152
149
|
|
@@ -3,13 +3,11 @@ module HstoreAccessor
|
|
3
3
|
InvalidDataTypeError = Class.new(StandardError)
|
4
4
|
|
5
5
|
VALID_TYPES = [
|
6
|
-
:array,
|
7
6
|
:boolean,
|
8
7
|
:date,
|
9
8
|
:datetime,
|
10
9
|
:decimal,
|
11
10
|
:float,
|
12
|
-
:hash,
|
13
11
|
:integer,
|
14
12
|
:string
|
15
13
|
]
|
@@ -17,24 +15,18 @@ module HstoreAccessor
|
|
17
15
|
DEFAULT_SERIALIZER = ->(value) { value.to_s }
|
18
16
|
DEFAULT_DESERIALIZER = DEFAULT_SERIALIZER
|
19
17
|
|
20
|
-
SEPARATOR = "||;||"
|
21
|
-
|
22
18
|
SERIALIZERS = {
|
23
|
-
array: -> value { (value && value.join(SEPARATOR)) || nil },
|
24
19
|
boolean: -> value { (value.to_s == "true").to_s },
|
25
20
|
date: -> value { value && value.to_s },
|
26
|
-
hash: -> value { (value && value.to_json) || nil },
|
27
21
|
datetime: -> value { value && value.to_i }
|
28
22
|
}
|
29
23
|
SERIALIZERS.default = DEFAULT_SERIALIZER
|
30
24
|
|
31
25
|
DESERIALIZERS = {
|
32
|
-
array: -> value { (value && value.split(SEPARATOR)) || nil },
|
33
26
|
boolean: -> value { TypeHelpers.cast(:boolean, value) },
|
34
27
|
date: -> value { value && Date.parse(value) },
|
35
28
|
decimal: -> value { value && BigDecimal.new(value) },
|
36
29
|
float: -> value { value && value.to_f },
|
37
|
-
hash: -> value { (value && JSON.parse(value)) || nil },
|
38
30
|
integer: -> value { value && value.to_i },
|
39
31
|
datetime: -> value { value && Time.at(value.to_i).in_time_zone }
|
40
32
|
}
|
@@ -2,17 +2,13 @@ require "spec_helper"
|
|
2
2
|
require "active_support/all"
|
3
3
|
|
4
4
|
FIELDS = {
|
5
|
-
name: :string,
|
6
5
|
color: :string,
|
7
6
|
price: :integer,
|
8
7
|
published: { data_type: :boolean, store_key: "p" },
|
9
8
|
weight: { data_type: :float, store_key: "w" },
|
10
9
|
popular: :boolean,
|
11
10
|
build_timestamp: :datetime,
|
12
|
-
tags: :array,
|
13
|
-
reviews: :hash,
|
14
11
|
released_at: :date,
|
15
|
-
likes: :integer,
|
16
12
|
miles: :decimal
|
17
13
|
}
|
18
14
|
|
@@ -20,15 +16,9 @@ DATA_FIELDS = {
|
|
20
16
|
color_data: :string
|
21
17
|
}
|
22
18
|
|
23
|
-
class ProductCategory < ActiveRecord::Base
|
24
|
-
hstore_accessor :options, name: :string, likes: :integer
|
25
|
-
has_many :products
|
26
|
-
end
|
27
|
-
|
28
19
|
class Product < ActiveRecord::Base
|
29
20
|
hstore_accessor :options, FIELDS
|
30
21
|
hstore_accessor :data, DATA_FIELDS
|
31
|
-
belongs_to :product_category
|
32
22
|
end
|
33
23
|
|
34
24
|
class SuperProduct < Product
|
@@ -85,7 +75,7 @@ describe HstoreAccessor do
|
|
85
75
|
let!(:timestamp) { Time.now }
|
86
76
|
let!(:datestamp) { Date.today }
|
87
77
|
let(:product) { Product.new }
|
88
|
-
let(:persisted_product) { Product.create!(color: "green", price: 10, weight: 10.1,
|
78
|
+
let(:persisted_product) { Product.create!(color: "green", price: 10, weight: 10.1, popular: true, build_timestamp: (timestamp - 10.days), released_at: (datestamp - 8.days), miles: BigDecimal.new("9.133790001")) }
|
89
79
|
|
90
80
|
FIELDS.keys.each do |field|
|
91
81
|
it "responds with nil when #{field} is not set" do
|
@@ -155,35 +145,9 @@ describe HstoreAccessor do
|
|
155
145
|
describe "scopes" do
|
156
146
|
let!(:timestamp) { Time.now }
|
157
147
|
let!(:datestamp) { Date.today }
|
158
|
-
let!(:product_a) { Product.create(
|
159
|
-
let!(:product_b) { Product.create(color: "orange", price: 20, weight: 20.2,
|
160
|
-
let!(:product_c) { Product.create(color: "blue", price: 30, weight: 30.3,
|
161
|
-
|
162
|
-
context "ambiguous column names" do
|
163
|
-
let!(:product_category) { ProductCategory.create!(name: "widget", likes: 2) }
|
164
|
-
|
165
|
-
before do
|
166
|
-
Product.all.to_a.each do |product|
|
167
|
-
product_category.products << product
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
context "eq query" do
|
172
|
-
let!(:query) { Product.all.joins(:product_category).merge(ProductCategory.with_name("widget")).with_name("widget") }
|
173
|
-
|
174
|
-
it "qualifies the table name to prevent ambiguous column name references" do
|
175
|
-
expect { query.to_a }.to_not raise_error
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
context "query" do
|
180
|
-
let!(:query) { Product.all.joins(:product_category).merge(ProductCategory.likes_lt(4)).likes_lt(4) }
|
181
|
-
|
182
|
-
it "qualifies the table name to prevent ambiguous column name references" do
|
183
|
-
expect { query.to_a }.to_not raise_error
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
148
|
+
let!(:product_a) { Product.create(color: "green", price: 10, weight: 10.1, popular: true, build_timestamp: (timestamp - 10.days), released_at: (datestamp - 8.days), miles: BigDecimal.new("10.113379001")) }
|
149
|
+
let!(:product_b) { Product.create(color: "orange", price: 20, weight: 20.2, popular: false, build_timestamp: (timestamp - 5.days), released_at: (datestamp - 4.days), miles: BigDecimal.new("20.213379001")) }
|
150
|
+
let!(:product_c) { Product.create(color: "blue", price: 30, weight: 30.3, popular: true, build_timestamp: timestamp, released_at: datestamp, miles: BigDecimal.new("30.313379001")) }
|
187
151
|
|
188
152
|
context "for string fields support" do
|
189
153
|
it "equality" do
|
@@ -257,20 +221,7 @@ describe HstoreAccessor do
|
|
257
221
|
end
|
258
222
|
end
|
259
223
|
|
260
|
-
context "for
|
261
|
-
it "equality" do
|
262
|
-
expect(Product.tags_eq(%w(tag1 tag2 tag3)).to_a).to eq [product_a]
|
263
|
-
end
|
264
|
-
|
265
|
-
it "contains" do
|
266
|
-
expect(Product.tags_contains("tag2").to_a).to eq [product_a, product_b]
|
267
|
-
expect(Product.tags_contains(%w(tag2 tag3)).to_a).to eq [product_a, product_b]
|
268
|
-
expect(Product.tags_contains(%w(tag1 tag2 tag3)).to_a).to eq [product_a]
|
269
|
-
expect(Product.tags_contains(%w(tag1 tag2 tag3 tag4)).to_a).to eq []
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
context "for time fields support" do
|
224
|
+
context "for datetime fields support" do
|
274
225
|
it "before" do
|
275
226
|
expect(Product.build_timestamp_before(timestamp)).to eq [product_a, product_b]
|
276
227
|
end
|
@@ -357,8 +308,6 @@ describe HstoreAccessor do
|
|
357
308
|
it_returns_the_properly_typed_column :datetime, :build_timestamp, ActiveRecord::Type::DateTime
|
358
309
|
it_returns_the_properly_typed_column :date, :released_at, ActiveRecord::Type::Date
|
359
310
|
it_returns_the_properly_typed_column :decimal, :miles, ActiveRecord::Type::Decimal
|
360
|
-
it_returns_the_properly_typed_column :array, :tags, ActiveRecord::Type::Value
|
361
|
-
it_returns_the_properly_typed_column :hash, :reviews, ActiveRecord::Type::Value
|
362
311
|
else
|
363
312
|
def self.it_returns_the_properly_typed_column(hstore_type, attribute_name, active_record_type)
|
364
313
|
context "#{hstore_type}" do
|
@@ -422,39 +371,6 @@ describe HstoreAccessor do
|
|
422
371
|
expect(product.weight).to eq 93.45
|
423
372
|
end
|
424
373
|
|
425
|
-
context "array values" do
|
426
|
-
it "correctly stores nothing" do
|
427
|
-
product.tags = nil
|
428
|
-
product.save
|
429
|
-
product.reload
|
430
|
-
expect(product.tags).to be_nil
|
431
|
-
end
|
432
|
-
|
433
|
-
it "correctly stores strings" do
|
434
|
-
product.tags = ["household", "living room", "kitchen"]
|
435
|
-
product.save
|
436
|
-
product.reload
|
437
|
-
expect(product.tags).to eq ["household", "living room", "kitchen"]
|
438
|
-
end
|
439
|
-
end
|
440
|
-
|
441
|
-
context "hash values" do
|
442
|
-
it "correctly stores nothing" do
|
443
|
-
product.reviews = nil
|
444
|
-
product.save
|
445
|
-
product.reload
|
446
|
-
expect(product.reviews).to be_nil
|
447
|
-
end
|
448
|
-
|
449
|
-
it "correctly stores hash values as json" do
|
450
|
-
hash = product.reviews = { "user_123" => "4 stars", "user_994" => "3 stars" }
|
451
|
-
product.save
|
452
|
-
product.reload
|
453
|
-
expect(product.reviews).to eq("user_123" => "4 stars", "user_994" => "3 stars")
|
454
|
-
expect(product.options["reviews"]).to eq(hash.to_json)
|
455
|
-
end
|
456
|
-
end
|
457
|
-
|
458
374
|
context "multipart values" do
|
459
375
|
it "stores multipart dates correctly" do
|
460
376
|
product.update_attributes!(
|
@@ -493,7 +409,7 @@ describe HstoreAccessor do
|
|
493
409
|
product.save!
|
494
410
|
product.reload
|
495
411
|
Time.use_zone(new_york_timezone) do
|
496
|
-
expect(product.build_timestamp.
|
412
|
+
expect(product.build_timestamp.utc_offset).to eq new_york_timezone.utc_offset
|
497
413
|
end
|
498
414
|
end
|
499
415
|
end
|
@@ -676,14 +592,12 @@ describe HstoreAccessor do
|
|
676
592
|
product.color = "GREEN"
|
677
593
|
expect(product.color_change).to eq %w(ORANGE GREEN)
|
678
594
|
end
|
679
|
-
|
680
595
|
context "when store_key differs from key" do
|
681
596
|
it "returns the old and new values" do
|
682
597
|
product.weight = 100.01
|
683
598
|
expect(product.weight_change[1]).to eq "100.01"
|
684
599
|
end
|
685
600
|
end
|
686
|
-
|
687
601
|
context "hstore attribute was nil" do
|
688
602
|
it "returns old and new values" do
|
689
603
|
product.options = nil
|
@@ -700,18 +614,6 @@ describe HstoreAccessor do
|
|
700
614
|
product.price = 6
|
701
615
|
expect(product.color_change).to be_nil
|
702
616
|
end
|
703
|
-
|
704
|
-
it "returns nil when other attributes were changed" do
|
705
|
-
product.price = 5
|
706
|
-
product.save!
|
707
|
-
product = Product.first
|
708
|
-
|
709
|
-
expect(product.price_change).to be_nil
|
710
|
-
|
711
|
-
product.color = "red"
|
712
|
-
|
713
|
-
expect(product.price_change).to be_nil
|
714
|
-
end
|
715
617
|
end
|
716
618
|
|
717
619
|
context "not persisted" do
|
data/spec/spec_helper.rb
CHANGED
@@ -26,7 +26,6 @@ def create_database
|
|
26
26
|
|
27
27
|
ActiveRecord::Base.connection.execute("CREATE EXTENSION hstore;") rescue ActiveRecord::StatementInvalid
|
28
28
|
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS products;")
|
29
|
-
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS product_categories;")
|
30
29
|
|
31
30
|
ActiveRecord::Base.connection.create_table(:products) do |t|
|
32
31
|
t.hstore :options
|
@@ -34,18 +33,11 @@ def create_database
|
|
34
33
|
|
35
34
|
t.string :string_type
|
36
35
|
t.integer :integer_type
|
37
|
-
t.integer :product_category_id
|
38
36
|
t.boolean :boolean_type
|
39
37
|
t.float :float_type
|
40
38
|
t.time :time_type
|
41
|
-
t.string :array_type, array: true
|
42
39
|
t.date :date_type
|
43
40
|
t.datetime :datetime_type
|
44
41
|
t.decimal :decimal_type
|
45
|
-
t.hstore :hash_type
|
46
|
-
end
|
47
|
-
|
48
|
-
ActiveRecord::Base.connection.create_table(:product_categories) do |t|
|
49
|
-
t.hstore :options
|
50
42
|
end
|
51
43
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hstore_accessor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joe Hirn
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2015-
|
15
|
+
date: 2015-02-10 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: activerecord
|
@@ -181,7 +181,6 @@ extra_rdoc_files: []
|
|
181
181
|
files:
|
182
182
|
- ".gitignore"
|
183
183
|
- ".rubocop.yml"
|
184
|
-
- ".ruby-version"
|
185
184
|
- Appraisals
|
186
185
|
- Gemfile
|
187
186
|
- LICENSE.txt
|
@@ -193,8 +192,8 @@ files:
|
|
193
192
|
- hstore_accessor.gemspec
|
194
193
|
- lib/hstore_accessor.rb
|
195
194
|
- lib/hstore_accessor/active_record_4.2/type_helpers.rb
|
196
|
-
- lib/hstore_accessor/
|
197
|
-
- lib/hstore_accessor/
|
195
|
+
- lib/hstore_accessor/active_record_<_4.2/time_helper.rb
|
196
|
+
- lib/hstore_accessor/active_record_<_4.2/type_helpers.rb
|
198
197
|
- lib/hstore_accessor/macro.rb
|
199
198
|
- lib/hstore_accessor/serialization.rb
|
200
199
|
- lib/hstore_accessor/version.rb
|
@@ -204,8 +203,8 @@ homepage: http://github.com/devmynd/hstore_accessor
|
|
204
203
|
licenses:
|
205
204
|
- MIT
|
206
205
|
metadata: {}
|
207
|
-
post_install_message: Please note that the `array` and `hash` types
|
208
|
-
|
206
|
+
post_install_message: Please note that the `array` and `hash` types are no longer
|
207
|
+
supported in version 1.0.0
|
209
208
|
rdoc_options: []
|
210
209
|
require_paths:
|
211
210
|
- lib
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.1.5
|