hstore_accessor 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +21 -3
- data/lib/hstore_accessor.rb +22 -16
- data/lib/hstore_accessor/version.rb +1 -1
- data/spec/hstore_accessor_spec.rb +33 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b556f080454175cefffda39846659bbc7eb676ea
|
4
|
+
data.tar.gz: c3b7cecfc960a65db15944e4f8579d941f59a708
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a96e5670fc7ff405146da7f0560bb67af29738ffbae2c209db60d6231cdea90624f8b61c2d8936d88d3c8688a7229ebbd07f6169b9e9816a8583e2a44c066a72
|
7
|
+
data.tar.gz: fde2a6addc657fe910ff609c087e90673855a88de590256481c36c3a69a797ae2dbc563b8dbf0afa2af259efb2fe53689e4336fedb86d5ed44240e911d2e3299
|
data/README.md
CHANGED
@@ -27,7 +27,7 @@ Or install it yourself as:
|
|
27
27
|
The `hstore_accessor` method accepts the name of the hstore column you'd
|
28
28
|
like to use and a hash with keys representing fields and values
|
29
29
|
indicating the type to be stored in that field. The available types
|
30
|
-
are: `string`, `integer`, `float`, `array`, and `hash`.
|
30
|
+
are: `string`, `integer`, `float`, `time`, `array`, and `hash`.
|
31
31
|
|
32
32
|
```ruby
|
33
33
|
class Product < ActiveRecord::Base
|
@@ -36,6 +36,7 @@ class Product < ActiveRecord::Base
|
|
36
36
|
color: :string,
|
37
37
|
weight: :integer,
|
38
38
|
price: :float,
|
39
|
+
built_at: :time,
|
39
40
|
tags: :array,
|
40
41
|
ratings: :hash
|
41
42
|
|
@@ -49,6 +50,7 @@ p = Product.new
|
|
49
50
|
p.color = "green"
|
50
51
|
p.weight = 34
|
51
52
|
p.price = 99.95
|
53
|
+
p.built_at = Time.now - 10.days
|
52
54
|
p.tags = ["housewares", "kitchen"]
|
53
55
|
p.ratings = { user_a: 3, user_b: 4 }
|
54
56
|
```
|
@@ -63,7 +65,9 @@ p.tags #=> ["housewares", "kitchen"]
|
|
63
65
|
### Scopes
|
64
66
|
|
65
67
|
The `hstore_accessor` macro also creates scopes for `string`, `integer`,
|
66
|
-
`float`, and `array` fields.
|
68
|
+
`float`, `time`, and `array` fields.
|
69
|
+
|
70
|
+
#### String Fields
|
67
71
|
|
68
72
|
For `string` types, a `with_<key>` scope is created which checks for
|
69
73
|
equality.
|
@@ -72,6 +76,8 @@ equality.
|
|
72
76
|
Product.with_color("green")
|
73
77
|
```
|
74
78
|
|
79
|
+
#### Integer and Float Fields
|
80
|
+
|
75
81
|
For `integer` and `float` types five scopes are created:
|
76
82
|
|
77
83
|
```ruby
|
@@ -82,6 +88,18 @@ Product.price_gte(240.00) # price greater than or equal to
|
|
82
88
|
Product.price_gt(240.00) # price greater than
|
83
89
|
```
|
84
90
|
|
91
|
+
#### Time Fields
|
92
|
+
|
93
|
+
For `time` fileds, three scopes are provided:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
Product.built_at_before(Time.now) # built before the given time
|
97
|
+
Product.built_at_eq(Time.now - 10.days) # built at an exact time
|
98
|
+
Product.built_at_after(Time.now - 4.days) # built after the given time
|
99
|
+
```
|
100
|
+
|
101
|
+
#### Array Fields
|
102
|
+
|
85
103
|
For `array` types, two scopes are created:
|
86
104
|
|
87
105
|
```ruby
|
@@ -120,7 +138,7 @@ And for our models:
|
|
120
138
|
|
121
139
|
```ruby
|
122
140
|
# app/models/vehicle.rb
|
123
|
-
class
|
141
|
+
class Vehicle < ActiveRecord::Base
|
124
142
|
end
|
125
143
|
|
126
144
|
# app/models/vehicles/automobile.rb
|
data/lib/hstore_accessor.rb
CHANGED
@@ -6,23 +6,25 @@ module HstoreAccessor
|
|
6
6
|
|
7
7
|
InvalidDataTypeError = Class.new(StandardError)
|
8
8
|
|
9
|
-
VALID_TYPES = [:string, :integer, :float, :array, :hash]
|
9
|
+
VALID_TYPES = [:string, :integer, :float, :time, :array, :hash]
|
10
10
|
|
11
11
|
SEPARATOR = ";|;"
|
12
12
|
|
13
|
-
DEFAULT_SERIALIZER = ->(
|
14
|
-
DEFAULT_DESERIALIZER = ->(
|
13
|
+
DEFAULT_SERIALIZER = ->(value) { value.to_s }
|
14
|
+
DEFAULT_DESERIALIZER = ->(value) { value.to_s }
|
15
15
|
|
16
16
|
SERIALIZERS = {
|
17
|
-
:array => ->(
|
18
|
-
:hash => ->(
|
17
|
+
:array => ->(value) { value.join(SEPARATOR) },
|
18
|
+
:hash => ->(value) { value.to_json },
|
19
|
+
:time => ->(value) { value.to_i }
|
19
20
|
}
|
20
21
|
|
21
22
|
DESERIALIZERS = {
|
22
|
-
:array => ->(
|
23
|
-
:hash => ->(
|
24
|
-
:integer => ->(
|
25
|
-
:float => ->(
|
23
|
+
:array => ->(value) { value.split(SEPARATOR) },
|
24
|
+
:hash => ->(value) { JSON.parse(value) },
|
25
|
+
:integer => ->(value) { value.to_i },
|
26
|
+
:float => ->(value) { value.to_f },
|
27
|
+
:time => ->(value) { Time.at(value.to_i) }
|
26
28
|
}
|
27
29
|
|
28
30
|
def self.included(base)
|
@@ -59,15 +61,19 @@ module HstoreAccessor
|
|
59
61
|
|
60
62
|
case type
|
61
63
|
when :string
|
62
|
-
send(:scope, "with_#{key}", -> value { where("#{hstore_attribute} -> '#{key}' = ?", value.to_s)})
|
64
|
+
send(:scope, "with_#{key}", -> value { where("#{hstore_attribute} -> '#{key}' = ?", value.to_s) })
|
63
65
|
when :integer, :float
|
64
|
-
send(:scope, "#{key}_lt", -> value { where("#{hstore_attribute} -> '#{key}' < ?", value.to_s)})
|
65
|
-
send(:scope, "#{key}_lte", -> value { where("#{hstore_attribute} -> '#{key}' <= ?", value.to_s)})
|
66
|
-
send(:scope, "#{key}_eq", -> value { where("#{hstore_attribute} -> '#{key}' = ?", value.to_s)})
|
67
|
-
send(:scope, "#{key}_gte", -> value { where("#{hstore_attribute} -> '#{key}' >= ?", value.to_s)})
|
68
|
-
send(:scope, "#{key}_gt", -> value { where("#{hstore_attribute} -> '#{key}' > ?", value.to_s)})
|
66
|
+
send(:scope, "#{key}_lt", -> value { where("#{hstore_attribute} -> '#{key}' < ?", value.to_s) })
|
67
|
+
send(:scope, "#{key}_lte", -> value { where("#{hstore_attribute} -> '#{key}' <= ?", value.to_s) })
|
68
|
+
send(:scope, "#{key}_eq", -> value { where("#{hstore_attribute} -> '#{key}' = ?", value.to_s) })
|
69
|
+
send(:scope, "#{key}_gte", -> value { where("#{hstore_attribute} -> '#{key}' >= ?", value.to_s) })
|
70
|
+
send(:scope, "#{key}_gt", -> value { where("#{hstore_attribute} -> '#{key}' > ?", value.to_s) })
|
71
|
+
when :time
|
72
|
+
send(:scope, "#{key}_before", -> value { where("to_number(#{hstore_attribute} -> '#{key}', '99999999999') < ?", value.to_i) })
|
73
|
+
send(:scope, "#{key}_eq", -> value { where("to_number(#{hstore_attribute} -> '#{key}', '99999999999') = ?", value.to_i) })
|
74
|
+
send(:scope, "#{key}_after", -> value { where("to_number(#{hstore_attribute} -> '#{key}', '99999999999') > ?", value.to_i) })
|
69
75
|
when :array
|
70
|
-
send(:scope, "#{key}_eq", -> value { where("#{hstore_attribute} -> '#{key}' = ?", value.join(SEPARATOR))})
|
76
|
+
send(:scope, "#{key}_eq", -> value { where("#{hstore_attribute} -> '#{key}' = ?", value.join(SEPARATOR)) })
|
71
77
|
send(:scope, "#{key}_contains", -> value do
|
72
78
|
where("string_to_array(#{hstore_attribute} -> '#{key}', '#{SEPARATOR}') @> string_to_array(?, '#{SEPARATOR}')", Array[value].flatten)
|
73
79
|
end)
|
@@ -7,7 +7,8 @@ class Product < ActiveRecord::Base
|
|
7
7
|
price: :integer,
|
8
8
|
weight: :float,
|
9
9
|
tags: :array,
|
10
|
-
reviews: :hash
|
10
|
+
reviews: :hash,
|
11
|
+
build_timestamp: :time
|
11
12
|
end
|
12
13
|
|
13
14
|
describe HstoreAccessor do
|
@@ -41,9 +42,10 @@ describe HstoreAccessor do
|
|
41
42
|
|
42
43
|
describe "scopes" do
|
43
44
|
|
44
|
-
let!(:
|
45
|
-
let!(:
|
46
|
-
let!(:
|
45
|
+
let!(:timestamp) { Time.now }
|
46
|
+
let!(:product_a) { Product.create(color: "green", price: 10, weight: 10.1, tags: ["tag1", "tag2", "tag3"], build_timestamp: (timestamp - 10.days)) }
|
47
|
+
let!(:product_b) { Product.create(color: "orange", price: 20, weight: 20.2, tags: ["tag2", "tag3", "tag4"], build_timestamp: (timestamp - 5.days)) }
|
48
|
+
let!(:product_c) { Product.create(color: "blue", price: 30, weight: 30.3, tags: ["tag3", "tag4", "tag5"], build_timestamp: timestamp) }
|
47
49
|
|
48
50
|
context "for string fields support" do
|
49
51
|
|
@@ -77,7 +79,7 @@ describe HstoreAccessor do
|
|
77
79
|
|
78
80
|
end
|
79
81
|
|
80
|
-
context "for float fields" do
|
82
|
+
context "for float fields support" do
|
81
83
|
|
82
84
|
it "less than" do
|
83
85
|
expect(Product.weight_lt(20.0).to_a).to eq [product_a]
|
@@ -101,7 +103,7 @@ describe HstoreAccessor do
|
|
101
103
|
|
102
104
|
end
|
103
105
|
|
104
|
-
context "for array fields" do
|
106
|
+
context "for array fields support" do
|
105
107
|
|
106
108
|
it "equality" do
|
107
109
|
expect(Product.tags_eq(["tag1", "tag2", "tag3"]).to_a).to eq [product_a]
|
@@ -112,7 +114,23 @@ describe HstoreAccessor do
|
|
112
114
|
expect(Product.tags_contains(["tag2", "tag3"]).to_a).to eq [product_a, product_b]
|
113
115
|
end
|
114
116
|
|
115
|
-
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "for time fields support" do
|
120
|
+
|
121
|
+
it "before" do
|
122
|
+
expect(Product.build_timestamp_before(timestamp)).to eq [product_a, product_b]
|
123
|
+
end
|
124
|
+
|
125
|
+
it "equality" do
|
126
|
+
expect(Product.build_timestamp_eq(timestamp)).to eq [product_c]
|
127
|
+
end
|
128
|
+
|
129
|
+
it "after" do
|
130
|
+
expect(Product.build_timestamp_after(timestamp - 6.days)).to eq [product_b, product_c]
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
116
134
|
|
117
135
|
end
|
118
136
|
|
@@ -155,6 +173,14 @@ describe HstoreAccessor do
|
|
155
173
|
expect(product.reviews).to eq({ "user_123" => "4 stars", "user_994" => "3 stars" })
|
156
174
|
end
|
157
175
|
|
176
|
+
it "correctly stores time values" do
|
177
|
+
timestamp = Time.now - 10.days
|
178
|
+
product.build_timestamp = timestamp
|
179
|
+
product.save
|
180
|
+
product.reload
|
181
|
+
expect(product.build_timestamp.to_i).to eq timestamp.to_i
|
182
|
+
end
|
183
|
+
|
158
184
|
it "setters call the _will_change! method of the store attribute" do
|
159
185
|
product.should_receive(:options_will_change!)
|
160
186
|
product.color = "green"
|
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: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joe Hirn
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-06-
|
13
|
+
date: 2013-06-11 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: pg
|