mongoid 5.2.0 → 5.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mongoid/extensions.rb +1 -0
- data/lib/mongoid/extensions/origin/regexp_raw.rb +43 -0
- data/lib/mongoid/matchable.rb +8 -1
- data/lib/mongoid/matchable/regexp.rb +27 -0
- data/lib/mongoid/version.rb +1 -1
- data/spec/mongoid/criteria_spec.rb +11 -0
- data/spec/mongoid/extensions/origin/regexp_raw_spec.rb +89 -0
- data/spec/mongoid/matchable/regexp_spec.rb +59 -0
- data/spec/mongoid/matchable_spec.rb +51 -1
- metadata +10 -26
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5ae2a3a33da11eae20a6d6b268ad3e69d601a13
|
4
|
+
data.tar.gz: 661ff308d0402ab14a5a3920534a1a88f879e3ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a910a280572a11c133f8f3900f878fdb719c548998381bb38c08714c911cbfc1ebfd508ffb84621489cdd8806a8e054cbb55aa041a189267f1fdb30d322d8895
|
7
|
+
data.tar.gz: 0bfeada8b1bc927fde4414f1accdfe30037b36d56776c5f9b904b041e5356bd4df7a202fbb69e40edda9c165d84a78cdc0f4971ebb7afcad021bd7526d9e6cf0
|
data/lib/mongoid/extensions.rb
CHANGED
@@ -39,6 +39,7 @@ require "mongoid/extensions/module"
|
|
39
39
|
require "mongoid/extensions/nil_class"
|
40
40
|
require "mongoid/extensions/object"
|
41
41
|
require "mongoid/extensions/object_id"
|
42
|
+
require "mongoid/extensions/origin/regexp_raw"
|
42
43
|
require "mongoid/extensions/range"
|
43
44
|
require "mongoid/extensions/regexp"
|
44
45
|
require "mongoid/extensions/set"
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Origin
|
2
|
+
module Extensions
|
3
|
+
|
4
|
+
# This module contains additional bson raw regex behaviour.
|
5
|
+
module Regexp
|
6
|
+
|
7
|
+
module Raw
|
8
|
+
|
9
|
+
# Is the object a regexp?
|
10
|
+
#
|
11
|
+
# @example Is the object a regex?
|
12
|
+
# bson_raw_regexp.regexp?
|
13
|
+
#
|
14
|
+
# @return [ true ] Always true.
|
15
|
+
#
|
16
|
+
# @since 5.2.1
|
17
|
+
def regexp?; true; end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
|
21
|
+
# Evolve the object into a raw bson regex.
|
22
|
+
#
|
23
|
+
# @example Evolve the object to a regex.
|
24
|
+
# BSON::Regexp::Raw.evolve("^[123]")
|
25
|
+
#
|
26
|
+
# @param [ BSON::Regexp::Raw, String ] object The object to evolve.
|
27
|
+
#
|
28
|
+
# @return [ BSON::Regexp::Raw ] The evolved raw regex.
|
29
|
+
#
|
30
|
+
# @since 5.2.1
|
31
|
+
def evolve(object)
|
32
|
+
__evolve__(object) do |obj|
|
33
|
+
obj.is_a?(String) ? BSON::Regexp::Raw.new(obj) : obj
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
BSON::Regexp::Raw.__send__(:include, Origin::Extensions::Regexp::Raw)
|
43
|
+
BSON::Regexp::Raw.__send__(:extend, Origin::Extensions::Regexp::Raw::ClassMethods)
|
data/lib/mongoid/matchable.rb
CHANGED
@@ -12,6 +12,7 @@ require "mongoid/matchable/ne"
|
|
12
12
|
require "mongoid/matchable/nin"
|
13
13
|
require "mongoid/matchable/or"
|
14
14
|
require "mongoid/matchable/size"
|
15
|
+
require "mongoid/matchable/regexp"
|
15
16
|
|
16
17
|
module Mongoid
|
17
18
|
|
@@ -115,6 +116,8 @@ module Mongoid
|
|
115
116
|
else
|
116
117
|
Default.new(extract_attribute(document, key))
|
117
118
|
end
|
119
|
+
elsif value.regexp?
|
120
|
+
Regexp.new(extract_attribute(document, key))
|
118
121
|
else
|
119
122
|
case key.to_s
|
120
123
|
when "$or" then Or.new(value, document)
|
@@ -143,7 +146,11 @@ module Mongoid
|
|
143
146
|
if (key_string = key.to_s) =~ /.+\..+/
|
144
147
|
key_string.split('.').inject(document.as_document) do |_attribs, _key|
|
145
148
|
if _attribs.is_a?(::Array)
|
146
|
-
_attribs.
|
149
|
+
if _key =~ /\A\d+\z/ && _attribs.none? {|doc| doc.is_a?(Hash)}
|
150
|
+
_attribs.try(:[], _key.to_i)
|
151
|
+
else
|
152
|
+
_attribs.map { |doc| doc.try(:[], _key) }
|
153
|
+
end
|
147
154
|
else
|
148
155
|
_attribs.try(:[], _key)
|
149
156
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Matchable
|
3
|
+
|
4
|
+
# Defines behavior for handling regular expressions in embedded documents.
|
5
|
+
class Regexp < Default
|
6
|
+
|
7
|
+
# Does the supplied query match the attribute?
|
8
|
+
#
|
9
|
+
# @example Does this match?
|
10
|
+
# matcher.matches?(/^Em/)
|
11
|
+
# matcher.matches?(BSON::Regex::Raw.new("^Em"))
|
12
|
+
#
|
13
|
+
# @param [ BSON::Regexp::Raw, Regexp ] regexp The regular expression object.
|
14
|
+
#
|
15
|
+
# @return [ true, false ] True if matches, false if not.
|
16
|
+
#
|
17
|
+
# @since 5.2.1
|
18
|
+
def matches?(regexp)
|
19
|
+
if native_regexp = regexp.try(:compile)
|
20
|
+
super(native_regexp)
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/mongoid/version.rb
CHANGED
@@ -3314,6 +3314,17 @@ describe Mongoid::Criteria do
|
|
3314
3314
|
end
|
3315
3315
|
end
|
3316
3316
|
|
3317
|
+
context 'when the criteria contains a BSON::Regexp::Raw' do
|
3318
|
+
|
3319
|
+
let(:criteria) do
|
3320
|
+
Band.where(name: BSON::Regexp::Raw.new("^Depeche"))
|
3321
|
+
end
|
3322
|
+
|
3323
|
+
it "returns the matching documents" do
|
3324
|
+
expect(criteria).to eq([ match ])
|
3325
|
+
end
|
3326
|
+
end
|
3327
|
+
|
3317
3328
|
context "when the criteria is an exact fk array match" do
|
3318
3329
|
|
3319
3330
|
let(:id_one) do
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Origin::Extensions::Regexp::Raw do
|
4
|
+
|
5
|
+
describe ".evolve" do
|
6
|
+
|
7
|
+
context "when provided a bson raw regexp" do
|
8
|
+
|
9
|
+
let(:regexp) do
|
10
|
+
BSON::Regexp::Raw.new("^[123]")
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:evolved) do
|
14
|
+
BSON::Regexp::Raw.evolve(regexp)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns the regexp" do
|
18
|
+
expect(evolved).to be(regexp)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when providing a string" do
|
23
|
+
|
24
|
+
let(:regexp_string) do
|
25
|
+
'^[123]'
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:evolved) do
|
29
|
+
BSON::Regexp::Raw.evolve(regexp_string)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "returns the converted raw regexp" do
|
33
|
+
expect(evolved).to eq(BSON::Regexp::Raw.new(regexp_string))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when provided an array" do
|
38
|
+
|
39
|
+
context "when the elements are bson raw regexps" do
|
40
|
+
|
41
|
+
let(:regexp) do
|
42
|
+
BSON::Regexp::Raw.new("^[123]")
|
43
|
+
end
|
44
|
+
|
45
|
+
let(:array) do
|
46
|
+
[ regexp ]
|
47
|
+
end
|
48
|
+
|
49
|
+
let(:evolved) do
|
50
|
+
BSON::Regexp::Raw.evolve(array)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "returns the array containing raw regexps" do
|
54
|
+
expect(evolved).to eq([ regexp ])
|
55
|
+
end
|
56
|
+
|
57
|
+
it "does not evolve in place" do
|
58
|
+
expect(evolved).to_not equal(array)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when the elements are strings" do
|
63
|
+
|
64
|
+
let(:regexp_string) do
|
65
|
+
"^[123]"
|
66
|
+
end
|
67
|
+
|
68
|
+
let(:evolved) do
|
69
|
+
BSON::Regexp::Raw.evolve([ regexp_string ])
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns the regexps" do
|
73
|
+
expect(evolved).to eq([ BSON::Regexp::Raw.new(regexp_string) ])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#regexp?" do
|
80
|
+
|
81
|
+
let(:regexp) do
|
82
|
+
BSON::Regexp::Raw.new('^[123]')
|
83
|
+
end
|
84
|
+
|
85
|
+
it "returns true" do
|
86
|
+
expect(regexp).to be_regexp
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Matchable::Regexp do
|
4
|
+
|
5
|
+
let(:matcher) do
|
6
|
+
described_class.new(attribute)
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:attribute) do
|
10
|
+
'Emily'
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#matches?' do
|
14
|
+
|
15
|
+
context 'when a BSON::Regexp::Raw object is passed' do
|
16
|
+
|
17
|
+
let(:regexp) do
|
18
|
+
BSON::Regexp::Raw.new('^Em')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'compiles the regexp object to a native regexp for the matching' do
|
22
|
+
expect(matcher.matches?(regexp)).to be(true)
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when the value does not match the attribute' do
|
26
|
+
|
27
|
+
let(:attribute) do
|
28
|
+
'ily'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'compiles the regexp object to a native regexp for the matching' do
|
32
|
+
expect(matcher.matches?(regexp)).to be(false)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when a native Regexp object is passed' do
|
38
|
+
|
39
|
+
let(:regexp) do
|
40
|
+
/^Em/
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'calls super with the native regexp' do
|
44
|
+
expect(matcher.matches?(regexp)).to be(true)
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when the value does not match the attribute' do
|
48
|
+
|
49
|
+
let(:attribute) do
|
50
|
+
'ily'
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'compiles the regexp object to a native regexp for the matching' do
|
54
|
+
expect(matcher.matches?(regexp)).to be(false)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -9,12 +9,13 @@ describe Mongoid::Matchable do
|
|
9
9
|
let(:document) do
|
10
10
|
Address.new(street: "Clarkenwell Road")
|
11
11
|
end
|
12
|
+
let(:occupants){[{'name' => 'Tim'}]}
|
12
13
|
|
13
14
|
before do
|
14
15
|
document.locations << Location.new(
|
15
16
|
name: 'No.1',
|
16
17
|
info: { 'door' => 'Red'},
|
17
|
-
occupants:
|
18
|
+
occupants: occupants
|
18
19
|
)
|
19
20
|
end
|
20
21
|
|
@@ -76,6 +77,33 @@ describe Mongoid::Matchable do
|
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
80
|
+
context "when matching index of an array" do
|
81
|
+
|
82
|
+
let(:occupants){["Tim","Logan"]}
|
83
|
+
|
84
|
+
context "when the contents match" do
|
85
|
+
|
86
|
+
let(:selector) do
|
87
|
+
{ "occupants.0" => "Tim" }
|
88
|
+
end
|
89
|
+
|
90
|
+
it "returns true" do
|
91
|
+
expect(document.locations.first.matches?(selector)).to be true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "when the contents do not match" do
|
96
|
+
|
97
|
+
let(:selector) do
|
98
|
+
{ "occupants.0" => "Logan" }
|
99
|
+
end
|
100
|
+
|
101
|
+
it "returns false" do
|
102
|
+
expect(document.locations.first.matches?(selector)).to be false
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
79
107
|
context "when matching values of multiple embedded hashes" do
|
80
108
|
|
81
109
|
context "when the contents match" do
|
@@ -141,6 +169,28 @@ describe Mongoid::Matchable do
|
|
141
169
|
expect(document.matches?(selector)).to be false
|
142
170
|
end
|
143
171
|
end
|
172
|
+
|
173
|
+
context 'when a BSON::Regexp::Raw object is used' do
|
174
|
+
|
175
|
+
let(:selector) do
|
176
|
+
{ street: BSON::Regexp::Raw.new("^Clarkenwell") }
|
177
|
+
end
|
178
|
+
|
179
|
+
it "returns true" do
|
180
|
+
expect(document.matches?(selector)).to be true
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context 'when a native Regexp object is used' do
|
185
|
+
|
186
|
+
let(:selector) do
|
187
|
+
{ street: /^Clarkenwell/ }
|
188
|
+
end
|
189
|
+
|
190
|
+
it "returns true" do
|
191
|
+
expect(document.matches?(selector)).to be true
|
192
|
+
end
|
193
|
+
end
|
144
194
|
end
|
145
195
|
|
146
196
|
context "when performing complex matching" do
|
metadata
CHANGED
@@ -1,36 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.2.
|
4
|
+
version: 5.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Durran Jordan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
|
-
cert_chain:
|
11
|
-
-
|
12
|
-
-----BEGIN CERTIFICATE-----
|
13
|
-
MIIDfDCCAmSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBCMRQwEgYDVQQDDAtkcml2
|
14
|
-
ZXItcnVieTEVMBMGCgmSJomT8ixkARkWBTEwZ2VuMRMwEQYKCZImiZPyLGQBGRYD
|
15
|
-
Y29tMB4XDTE2MTIwMTE0MDcxMloXDTE3MTIwMTE0MDcxMlowQjEUMBIGA1UEAwwL
|
16
|
-
ZHJpdmVyLXJ1YnkxFTATBgoJkiaJk/IsZAEZFgUxMGdlbjETMBEGCgmSJomT8ixk
|
17
|
-
ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFdSAa8fRm1
|
18
|
-
bAM9za6Z0fAH4g02bqM1NGnw8zJQrE/PFrFfY6IFCT2AsLfOwr1maVm7iU1+kdVI
|
19
|
-
IQ+iI/9+E+ArJ+rbGV3dDPQ+SLl3mLT+vXjfjcxMqI2IW6UuVtt2U3Rxd4QU0kdT
|
20
|
-
JxmcPYs5fDN6BgYc6XXgUjy3m+Kwha2pGctdciUOwEfOZ4RmNRlEZKCMLRHdFP8j
|
21
|
-
4WTnJSGfXDiuoXICJb5yOPOZPuaapPSNXp93QkUdsqdKC32I+KMpKKYGBQ6yisfA
|
22
|
-
5MyVPPCzLR1lP5qXVGJPnOqUAkvEUfCahg7EP9tI20qxiXrR6TSEraYhIFXL0EGY
|
23
|
-
u8KAcPHm5KkCAwEAAaN9MHswCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
|
24
|
-
BBYEFFt3WbF+9JpUjAoj62cQBgNb8HzXMCAGA1UdEQQZMBeBFWRyaXZlci1ydWJ5
|
25
|
-
QDEwZ2VuLmNvbTAgBgNVHRIEGTAXgRVkcml2ZXItcnVieUAxMGdlbi5jb20wDQYJ
|
26
|
-
KoZIhvcNAQEFBQADggEBAKBDaVkycCUC1zMfpAkXIgWtji2Nr2ZygYQR53AgxOaE
|
27
|
-
7nqxdh5Lh8pnfwa71/ucrZFJt+g/mEhen9lFNmcizvpP43Hh4rYf8j6T8Y+mQ6tr
|
28
|
-
sp5xWiv93DlLXGmas0hv9VRYDvV1vLFaG05FHOAZKdo6pD2t6jNyMSAn4fMHKctw
|
29
|
-
UoYN5FLt84jacRQF5nhy9gBhfgvA19LcjeMLQC11x3fykDLzCXF2wEe5Q5iYaWvb
|
30
|
-
cGiNQIiHBj/9/xHfOyOthBPUevTiVnuffarDr434z/LGLwYzgaG5EcJFvZqpvUpP
|
31
|
-
fGcAPtAZUMGLXwcOB1BJEFkDxUQIJiEpSmf4YzzZhEM=
|
32
|
-
-----END CERTIFICATE-----
|
33
|
-
date: 2017-01-26 00:00:00.000000000 Z
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-04-05 00:00:00.000000000 Z
|
34
12
|
dependencies:
|
35
13
|
- !ruby/object:Gem::Dependency
|
36
14
|
name: activemodel
|
@@ -218,6 +196,7 @@ files:
|
|
218
196
|
- lib/mongoid/extensions/nil_class.rb
|
219
197
|
- lib/mongoid/extensions/object.rb
|
220
198
|
- lib/mongoid/extensions/object_id.rb
|
199
|
+
- lib/mongoid/extensions/origin/regexp_raw.rb
|
221
200
|
- lib/mongoid/extensions/range.rb
|
222
201
|
- lib/mongoid/extensions/regexp.rb
|
223
202
|
- lib/mongoid/extensions/set.rb
|
@@ -253,6 +232,7 @@ files:
|
|
253
232
|
- lib/mongoid/matchable/ne.rb
|
254
233
|
- lib/mongoid/matchable/nin.rb
|
255
234
|
- lib/mongoid/matchable/or.rb
|
235
|
+
- lib/mongoid/matchable/regexp.rb
|
256
236
|
- lib/mongoid/matchable/size.rb
|
257
237
|
- lib/mongoid/persistable.rb
|
258
238
|
- lib/mongoid/persistable/creatable.rb
|
@@ -668,6 +648,7 @@ files:
|
|
668
648
|
- spec/mongoid/extensions/nil_class_spec.rb
|
669
649
|
- spec/mongoid/extensions/object_id_spec.rb
|
670
650
|
- spec/mongoid/extensions/object_spec.rb
|
651
|
+
- spec/mongoid/extensions/origin/regexp_raw_spec.rb
|
671
652
|
- spec/mongoid/extensions/range_spec.rb
|
672
653
|
- spec/mongoid/extensions/regexp_spec.rb
|
673
654
|
- spec/mongoid/extensions/set_spec.rb
|
@@ -702,6 +683,7 @@ files:
|
|
702
683
|
- spec/mongoid/matchable/ne_spec.rb
|
703
684
|
- spec/mongoid/matchable/nin_spec.rb
|
704
685
|
- spec/mongoid/matchable/or_spec.rb
|
686
|
+
- spec/mongoid/matchable/regexp_spec.rb
|
705
687
|
- spec/mongoid/matchable/size_spec.rb
|
706
688
|
- spec/mongoid/matchable_spec.rb
|
707
689
|
- spec/mongoid/persistable/creatable_spec.rb
|
@@ -821,7 +803,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
821
803
|
version: 1.3.6
|
822
804
|
requirements: []
|
823
805
|
rubyforge_project: mongoid
|
824
|
-
rubygems_version: 2.
|
806
|
+
rubygems_version: 2.6.11
|
825
807
|
signing_key:
|
826
808
|
specification_version: 4
|
827
809
|
summary: Elegant Persistence in Ruby for MongoDB.
|
@@ -1125,6 +1107,7 @@ test_files:
|
|
1125
1107
|
- spec/mongoid/extensions/nil_class_spec.rb
|
1126
1108
|
- spec/mongoid/extensions/object_id_spec.rb
|
1127
1109
|
- spec/mongoid/extensions/object_spec.rb
|
1110
|
+
- spec/mongoid/extensions/origin/regexp_raw_spec.rb
|
1128
1111
|
- spec/mongoid/extensions/range_spec.rb
|
1129
1112
|
- spec/mongoid/extensions/regexp_spec.rb
|
1130
1113
|
- spec/mongoid/extensions/set_spec.rb
|
@@ -1159,6 +1142,7 @@ test_files:
|
|
1159
1142
|
- spec/mongoid/matchable/ne_spec.rb
|
1160
1143
|
- spec/mongoid/matchable/nin_spec.rb
|
1161
1144
|
- spec/mongoid/matchable/or_spec.rb
|
1145
|
+
- spec/mongoid/matchable/regexp_spec.rb
|
1162
1146
|
- spec/mongoid/matchable/size_spec.rb
|
1163
1147
|
- spec/mongoid/matchable_spec.rb
|
1164
1148
|
- spec/mongoid/persistable/creatable_spec.rb
|
checksums.yaml.gz.sig
DELETED
Binary file
|
data.tar.gz.sig
DELETED
Binary file
|
metadata.gz.sig
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
�N�H��vb�E?���|%��wH�7ùq��({*4 �\!��?�R9��w#D��ٍ��� ����9�ݒ(�s��+l�N�'������ǿ:=}%4'��3\Q����Q_¼{A�J�$�H
|