hstore_accessor 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|