couchbase-orm 3.0.3 → 3.1.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/lib/couchbase-orm/n1ql.rb +10 -5
- data/lib/couchbase-orm/relation.rb +46 -28
- data/lib/couchbase-orm/utilities/has_many.rb +3 -1
- data/lib/couchbase-orm/utilities/query_helper.rb +52 -25
- data/lib/couchbase-orm/version.rb +1 -1
- data/spec/n1ql_spec.rb +12 -3
- data/spec/relation_spec.rb +49 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9ece6e35ae742239bedb003f5865293f86164ba2899801d8f9b18efe93266e09
|
|
4
|
+
data.tar.gz: 85f84fa26a635d3fa319e2c5726eb429b52e576689690e61c50ace5b79333551
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: beea3033581402385e821e1d4512d0a3ae9f76df5ebd571c8907c67a216bf0680a065c1276387160208ca2a49e99310f88b7fd3b2e2147b1b5b1c92e1b4b6fba
|
|
7
|
+
data.tar.gz: 9dffa58a606270a0a0c7775b91f6af34cceb0c1bca77ac37f5eec94784e217c9e8322beed82b42e33366cae50e32b65175bb4dc1c5ea9290a305bdaa777578fc
|
data/lib/couchbase-orm/n1ql.rb
CHANGED
|
@@ -95,10 +95,10 @@ module CouchbaseOrm
|
|
|
95
95
|
end
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
-
def build_where(keys, values)
|
|
98
|
+
def build_where(keys, values, params: nil)
|
|
99
99
|
where = values == NO_VALUE ? '' : keys.zip(Array.wrap(values))
|
|
100
100
|
.reject { |key, value| key.nil? && value.nil? }
|
|
101
|
-
.map { |key, value| build_match(key, value) }
|
|
101
|
+
.map { |key, value| build_match(key, value, params: params) }
|
|
102
102
|
.join(" AND ")
|
|
103
103
|
"type=\"#{design_document}\" #{"AND " + where unless where.blank?}"
|
|
104
104
|
end
|
|
@@ -119,12 +119,17 @@ module CouchbaseOrm
|
|
|
119
119
|
N1qlProxy.new(query_fn.call(bucket, values, Couchbase::Options::Query.new(**options)))
|
|
120
120
|
else
|
|
121
121
|
bucket_name = bucket.name
|
|
122
|
-
|
|
122
|
+
params = []
|
|
123
|
+
where = build_where(keys, values, params: params)
|
|
123
124
|
order = custom_order || build_order(keys, descending)
|
|
124
125
|
limit = build_limit(limit)
|
|
125
126
|
n1ql_query = "select raw meta().id from `#{bucket_name}` where #{where} order by #{order} #{limit}"
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
|
|
128
|
+
query_options = options.merge(positional_parameters: params)
|
|
129
|
+
result = cluster.query(n1ql_query, Couchbase::Options::Query.new(**query_options))
|
|
130
|
+
CouchbaseOrm.logger.debug {
|
|
131
|
+
"N1QL query: #{n1ql_query} params: #{params.inspect} return #{result.rows.to_a.length} rows with scan_consistency: #{options[:scan_consistency]}"
|
|
132
|
+
}
|
|
128
133
|
N1qlProxy.new(result)
|
|
129
134
|
end
|
|
130
135
|
end
|
|
@@ -21,31 +21,41 @@ module CouchbaseOrm
|
|
|
21
21
|
|
|
22
22
|
def to_n1ql
|
|
23
23
|
bucket_name = @model.bucket.name
|
|
24
|
-
where =
|
|
24
|
+
where = build_where_with_params(nil)
|
|
25
25
|
order = build_order
|
|
26
26
|
limit = build_limit
|
|
27
27
|
"select raw meta().id from `#{bucket_name}` where #{where} order by #{order} #{limit}"
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
def
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
def to_n1ql_with_params
|
|
31
|
+
bucket_name = @model.bucket.name
|
|
32
|
+
params = []
|
|
33
|
+
where = build_where_with_params(params)
|
|
34
|
+
order = build_order
|
|
35
|
+
limit = build_limit
|
|
36
|
+
["select raw meta().id from `#{bucket_name}` where #{where} order by #{order} #{limit}", params]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def execute(n1ql_query, params = [])
|
|
40
|
+
result = @model.cluster.query(n1ql_query, build_query_options(positional_parameters: params))
|
|
41
|
+
CouchbaseOrm.logger.debug { "Relation query: #{n1ql_query} params: #{params.inspect} return #{result.rows.to_a.length} rows" }
|
|
33
42
|
N1qlProxy.new(result)
|
|
34
43
|
end
|
|
35
44
|
|
|
36
45
|
def query
|
|
37
46
|
CouchbaseOrm::logger.debug("Query: #{self}")
|
|
38
|
-
n1ql_query =
|
|
39
|
-
execute(n1ql_query)
|
|
47
|
+
n1ql_query, params = to_n1ql_with_params
|
|
48
|
+
execute(n1ql_query, params)
|
|
40
49
|
end
|
|
41
|
-
|
|
50
|
+
|
|
42
51
|
def update_all(**cond)
|
|
43
52
|
bucket_name = @model.bucket.name
|
|
44
|
-
|
|
53
|
+
params = []
|
|
54
|
+
where = build_where_with_params(params)
|
|
45
55
|
limit = build_limit
|
|
46
|
-
update =
|
|
56
|
+
update = build_update_with_params(params, **cond)
|
|
47
57
|
n1ql_query = "update `#{bucket_name}` set #{update} where #{where} #{limit}"
|
|
48
|
-
execute(n1ql_query)
|
|
58
|
+
execute(n1ql_query, params)
|
|
49
59
|
end
|
|
50
60
|
|
|
51
61
|
def ids
|
|
@@ -61,14 +71,16 @@ module CouchbaseOrm
|
|
|
61
71
|
end
|
|
62
72
|
|
|
63
73
|
def first
|
|
64
|
-
|
|
74
|
+
n1ql_query, params = self.limit(1).to_n1ql_with_params
|
|
75
|
+
result = @model.cluster.query(n1ql_query, build_query_options(positional_parameters: params))
|
|
65
76
|
return unless (first_id = result.rows.to_a.first)
|
|
66
77
|
|
|
67
78
|
@model.find(first_id, with_strict_loading: @strict_loading)
|
|
68
79
|
end
|
|
69
80
|
|
|
70
81
|
def last
|
|
71
|
-
|
|
82
|
+
n1ql_query, params = to_n1ql_with_params
|
|
83
|
+
result = @model.cluster.query(n1ql_query, build_query_options(positional_parameters: params))
|
|
72
84
|
last_id = result.rows.to_a.last
|
|
73
85
|
@model.find(last_id, with_strict_loading: @strict_loading) if last_id
|
|
74
86
|
end
|
|
@@ -166,7 +178,7 @@ module CouchbaseOrm
|
|
|
166
178
|
.merge(Array.wrap(lorder).map{ |o| [o, :asc] }.to_h)
|
|
167
179
|
.merge(horder)
|
|
168
180
|
end
|
|
169
|
-
|
|
181
|
+
|
|
170
182
|
def merge_where(conds, _not = false)
|
|
171
183
|
@where + (_not ? conds.to_a.map{|k,v|[k,v,:not]} : conds.to_a)
|
|
172
184
|
end
|
|
@@ -183,48 +195,54 @@ module CouchbaseOrm
|
|
|
183
195
|
end.join(", ")
|
|
184
196
|
order.empty? ? "meta().id" : order
|
|
185
197
|
end
|
|
186
|
-
|
|
187
|
-
def
|
|
188
|
-
|
|
198
|
+
|
|
199
|
+
def build_where_with_params(params)
|
|
200
|
+
build_conds_with_params([[nil, "type = #{@model.quote(@model.design_document)}"]] + @where, params)
|
|
189
201
|
end
|
|
190
202
|
|
|
191
|
-
def
|
|
203
|
+
def build_conds_with_params(conds, params)
|
|
192
204
|
conds.map do |key, value, opt|
|
|
193
205
|
if key
|
|
194
|
-
opt == :not ?
|
|
195
|
-
@model.build_not_match(key, value) :
|
|
196
|
-
@model.build_match(key, value)
|
|
206
|
+
opt == :not ?
|
|
207
|
+
@model.build_not_match(key, value, params: params) :
|
|
208
|
+
@model.build_match(key, value, params: params)
|
|
197
209
|
else
|
|
198
210
|
value
|
|
199
211
|
end
|
|
200
212
|
end.join(" AND ")
|
|
201
213
|
end
|
|
202
214
|
|
|
203
|
-
def
|
|
215
|
+
def build_update_with_params(params, **cond)
|
|
204
216
|
cond.map do |key, value|
|
|
205
|
-
for_clause=""
|
|
217
|
+
for_clause = ""
|
|
206
218
|
if value.is_a?(Hash) && value[:_for]
|
|
207
219
|
path_clause = value.delete(:_for)
|
|
208
220
|
var_clause = path_clause.to_s.split(".").last.singularize
|
|
209
|
-
|
|
221
|
+
|
|
210
222
|
_when = value.delete(:_when)
|
|
211
|
-
when_clause = _when ?
|
|
212
|
-
|
|
213
|
-
_set = value.delete(:_set)
|
|
223
|
+
when_clause = _when ? build_conds_with_params(_when.to_a, params) : ""
|
|
224
|
+
|
|
225
|
+
_set = value.delete(:_set)
|
|
214
226
|
value = _set if _set
|
|
215
227
|
|
|
216
228
|
for_clause = " for #{var_clause} in #{path_clause} when #{when_clause} end"
|
|
217
229
|
end
|
|
218
230
|
if value.is_a?(Hash)
|
|
219
231
|
value.map do |k, v|
|
|
220
|
-
"#{key}.#{k} = #{@model.
|
|
232
|
+
"#{key}.#{k} = #{v.nil? ? 'NULL' : @model.bind(v, params)}"
|
|
221
233
|
end.join(", ") + for_clause
|
|
222
234
|
else
|
|
223
|
-
"#{key} = #{@model.
|
|
235
|
+
"#{key} = #{value.nil? ? 'NULL' : @model.bind(value, params)}#{for_clause}"
|
|
224
236
|
end
|
|
225
237
|
end.join(", ")
|
|
226
238
|
end
|
|
227
239
|
|
|
240
|
+
def build_query_options(positional_parameters: [])
|
|
241
|
+
opts = { scan_consistency: CouchbaseOrm::N1ql.config[:scan_consistency] }
|
|
242
|
+
opts[:positional_parameters] = positional_parameters unless positional_parameters.empty?
|
|
243
|
+
Couchbase::Options::Query.new(**opts)
|
|
244
|
+
end
|
|
245
|
+
|
|
228
246
|
def method_missing(method, *args, &block)
|
|
229
247
|
if @model.respond_to?(method)
|
|
230
248
|
scoping {
|
|
@@ -96,7 +96,9 @@ module CouchbaseOrm
|
|
|
96
96
|
klass.class_eval do
|
|
97
97
|
n1ql remote_method, emit_key: 'id', query_fn: proc { |bucket, values, options|
|
|
98
98
|
raise ArgumentError, "values[0] must not be blank" if values[0].blank?
|
|
99
|
-
|
|
99
|
+
n1ql_query = "SELECT raw #{through_key} FROM `#{bucket.name}` where type = \"#{design_document}\" and #{foreign_key} = $1"
|
|
100
|
+
options.positional_parameters([values[0]])
|
|
101
|
+
cluster.query(n1ql_query, options)
|
|
100
102
|
}
|
|
101
103
|
end
|
|
102
104
|
else
|
|
@@ -4,7 +4,34 @@ module CouchbaseOrm
|
|
|
4
4
|
|
|
5
5
|
module ClassMethods
|
|
6
6
|
|
|
7
|
-
def
|
|
7
|
+
def serialize_for_binding(value)
|
|
8
|
+
if value.is_a?(Array)
|
|
9
|
+
value.map { |v| serialize_for_binding(v) }
|
|
10
|
+
elsif [DateTime, Time].any? { |clazz| value.is_a?(clazz) } || (value.respond_to?(:acts_like?) && value.acts_like?(:time))
|
|
11
|
+
value.iso8601(@precision || 0)
|
|
12
|
+
elsif value.is_a?(Date)
|
|
13
|
+
value.to_s
|
|
14
|
+
else
|
|
15
|
+
value
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def bind(value, params)
|
|
20
|
+
if value.nil?
|
|
21
|
+
nil
|
|
22
|
+
else
|
|
23
|
+
params << serialize_for_binding(value)
|
|
24
|
+
"$#{params.length}"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Renders a value either as a positional parameter (when +params+ is
|
|
29
|
+
# provided) or as an inline quoted literal (when it is nil).
|
|
30
|
+
def resolve_value(value, params)
|
|
31
|
+
params ? bind(value, params) : quote(value)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def build_match(key, value, params: nil)
|
|
8
35
|
use_is_null = self.properties_always_exists_in_document
|
|
9
36
|
key = "meta().id" if key.to_s == "id"
|
|
10
37
|
case
|
|
@@ -13,35 +40,35 @@ module CouchbaseOrm
|
|
|
13
40
|
when value.nil? && !use_is_null
|
|
14
41
|
"#{key} IS NOT VALUED"
|
|
15
42
|
when value.is_a?(Hash) && attribute_types[key.to_s].is_a?(CouchbaseOrm::Types::Array)
|
|
16
|
-
"any #{key.to_s.singularize} in #{key} satisfies (#{build_match_hash("#{key.to_s.singularize}", value)}) end"
|
|
43
|
+
"any #{key.to_s.singularize} in #{key} satisfies (#{build_match_hash("#{key.to_s.singularize}", value, params: params)}) end"
|
|
17
44
|
when value.is_a?(Hash) && !attribute_types[key.to_s].is_a?(CouchbaseOrm::Types::Array)
|
|
18
|
-
build_match_hash(key, value)
|
|
45
|
+
build_match_hash(key, value, params: params)
|
|
19
46
|
when value.is_a?(Array) && value.include?(nil)
|
|
20
|
-
"(#{build_match(key, nil)} OR #{build_match(key, value.compact)})"
|
|
47
|
+
"(#{build_match(key, nil, params: params)} OR #{build_match(key, value.compact, params: params)})"
|
|
21
48
|
when value.is_a?(Array)
|
|
22
|
-
"#{key} IN #{
|
|
49
|
+
"#{key} IN #{resolve_value(value, params)}"
|
|
23
50
|
when value.is_a?(Range)
|
|
24
|
-
build_match_range(key, value)
|
|
51
|
+
build_match_range(key, value, params: params)
|
|
25
52
|
else
|
|
26
|
-
"#{key} = #{
|
|
53
|
+
"#{key} = #{resolve_value(value, params)}"
|
|
27
54
|
end
|
|
28
55
|
end
|
|
29
56
|
|
|
30
|
-
def build_match_hash(key, value)
|
|
57
|
+
def build_match_hash(key, value, params: nil)
|
|
31
58
|
matches = []
|
|
32
59
|
value.each do |k, v|
|
|
33
60
|
case k
|
|
34
61
|
when :_gt
|
|
35
|
-
matches << "#{key} > #{
|
|
62
|
+
matches << "#{key} > #{resolve_value(v, params)}"
|
|
36
63
|
when :_gte
|
|
37
|
-
matches << "#{key} >= #{
|
|
64
|
+
matches << "#{key} >= #{resolve_value(v, params)}"
|
|
38
65
|
when :_lt
|
|
39
|
-
matches << "#{key} < #{
|
|
66
|
+
matches << "#{key} < #{resolve_value(v, params)}"
|
|
40
67
|
when :_lte
|
|
41
|
-
matches << "#{key} <= #{
|
|
68
|
+
matches << "#{key} <= #{resolve_value(v, params)}"
|
|
42
69
|
when :_ne
|
|
43
|
-
matches << "#{key} != #{
|
|
44
|
-
|
|
70
|
+
matches << "#{key} != #{resolve_value(v, params)}"
|
|
71
|
+
|
|
45
72
|
# TODO v2
|
|
46
73
|
# when :_in
|
|
47
74
|
# matches << "#{key} IN #{quote(v)}"
|
|
@@ -65,7 +92,7 @@ module CouchbaseOrm
|
|
|
65
92
|
# matches << "#{key} MATCH #{quote(v)}"
|
|
66
93
|
# when :_nmatch
|
|
67
94
|
# matches << "#{key} NOT MATCH #{quote(v)}"
|
|
68
|
-
|
|
95
|
+
|
|
69
96
|
# TODO v3
|
|
70
97
|
# when :_any
|
|
71
98
|
# matches << "#{key} ANY #{quote(v)}"
|
|
@@ -80,26 +107,26 @@ module CouchbaseOrm
|
|
|
80
107
|
#when :_nwithin
|
|
81
108
|
# matches << "#{key} NOT WITHIN #{quote(v)}"
|
|
82
109
|
else
|
|
83
|
-
matches << build_match("#{key}.#{k}", v)
|
|
110
|
+
matches << build_match("#{key}.#{k}", v, params: params)
|
|
84
111
|
end
|
|
85
112
|
end
|
|
86
|
-
|
|
113
|
+
|
|
87
114
|
matches.join(" AND ")
|
|
88
115
|
end
|
|
89
116
|
|
|
90
|
-
def build_match_range(key, value)
|
|
117
|
+
def build_match_range(key, value, params: nil)
|
|
91
118
|
matches = []
|
|
92
|
-
matches << "#{key} >= #{
|
|
119
|
+
matches << "#{key} >= #{resolve_value(value.begin, params)}"
|
|
93
120
|
if value.exclude_end?
|
|
94
|
-
matches << "#{key} < #{
|
|
121
|
+
matches << "#{key} < #{resolve_value(value.end, params)}"
|
|
95
122
|
else
|
|
96
|
-
matches << "#{key} <= #{
|
|
123
|
+
matches << "#{key} <= #{resolve_value(value.end, params)}"
|
|
97
124
|
end
|
|
98
125
|
matches.join(" AND ")
|
|
99
126
|
end
|
|
100
127
|
|
|
101
128
|
|
|
102
|
-
def build_not_match(key, value)
|
|
129
|
+
def build_not_match(key, value, params: nil)
|
|
103
130
|
use_is_null = self.properties_always_exists_in_document
|
|
104
131
|
key = "meta().id" if key.to_s == "id"
|
|
105
132
|
case
|
|
@@ -108,11 +135,11 @@ module CouchbaseOrm
|
|
|
108
135
|
when value.nil? && !use_is_null
|
|
109
136
|
"#{key} IS VALUED"
|
|
110
137
|
when value.is_a?(Array) && value.include?(nil)
|
|
111
|
-
"(#{build_not_match(key, nil)} AND #{build_not_match(key, value.compact)})"
|
|
138
|
+
"(#{build_not_match(key, nil, params: params)} AND #{build_not_match(key, value.compact, params: params)})"
|
|
112
139
|
when value.is_a?(Array)
|
|
113
|
-
"#{key} NOT IN #{
|
|
140
|
+
"#{key} NOT IN #{resolve_value(value, params)}"
|
|
114
141
|
else
|
|
115
|
-
"#{key} != #{
|
|
142
|
+
"#{key} != #{resolve_value(value, params)}"
|
|
116
143
|
end
|
|
117
144
|
end
|
|
118
145
|
|
data/spec/n1ql_spec.rb
CHANGED
|
@@ -172,7 +172,10 @@ describe CouchbaseOrm::N1ql do
|
|
|
172
172
|
it "should log the default scan_consistency when n1ql query is executed" do
|
|
173
173
|
allow(CouchbaseOrm.logger).to receive(:debug)
|
|
174
174
|
N1QLTest.by_rating_reverse()
|
|
175
|
-
expect(CouchbaseOrm.logger).to have_received(:debug).at_least(:once)
|
|
175
|
+
expect(CouchbaseOrm.logger).to have_received(:debug).at_least(:once) do |&block|
|
|
176
|
+
msg = block ? block.call : nil
|
|
177
|
+
msg == "N1QL query: select raw meta().id from `#{CouchbaseOrm::Connection.bucket.name}` where type=\"n1_ql_test\" order by name DESC params: [] return 0 rows with scan_consistency: #{described_class::DEFAULT_SCAN_CONSISTENCY}"
|
|
178
|
+
end
|
|
176
179
|
end
|
|
177
180
|
|
|
178
181
|
it "should log the set scan_consistency when n1ql query is executed with a specific scan_consistency" do
|
|
@@ -180,11 +183,17 @@ describe CouchbaseOrm::N1ql do
|
|
|
180
183
|
default_n1ql_config = CouchbaseOrm::N1ql.config
|
|
181
184
|
CouchbaseOrm::N1ql.config({ scan_consistency: :not_bounded })
|
|
182
185
|
N1QLTest.by_rating_reverse()
|
|
183
|
-
expect(CouchbaseOrm.logger).to have_received(:debug).at_least(:once)
|
|
186
|
+
expect(CouchbaseOrm.logger).to have_received(:debug).at_least(:once) do |&block|
|
|
187
|
+
msg = block ? block.call : nil
|
|
188
|
+
msg == "N1QL query: select raw meta().id from `#{CouchbaseOrm::Connection.bucket.name}` where type=\"n1_ql_test\" order by name DESC params: [] return 0 rows with scan_consistency: not_bounded"
|
|
189
|
+
end
|
|
184
190
|
|
|
185
191
|
CouchbaseOrm::N1ql.config(default_n1ql_config)
|
|
186
192
|
N1QLTest.by_rating_reverse()
|
|
187
|
-
expect(CouchbaseOrm.logger).to have_received(:debug).at_least(:once)
|
|
193
|
+
expect(CouchbaseOrm.logger).to have_received(:debug).at_least(:once) do |&block|
|
|
194
|
+
msg = block ? block.call : nil
|
|
195
|
+
msg == "N1QL query: select raw meta().id from `#{CouchbaseOrm::Connection.bucket.name}` where type=\"n1_ql_test\" order by name DESC params: [] return 0 rows with scan_consistency: #{described_class::DEFAULT_SCAN_CONSISTENCY}"
|
|
196
|
+
end
|
|
188
197
|
end
|
|
189
198
|
|
|
190
199
|
after(:all) do
|
data/spec/relation_spec.rb
CHANGED
|
@@ -310,6 +310,55 @@ describe CouchbaseOrm::Relation do
|
|
|
310
310
|
expect(RelationModel.empty?).to eq(false)
|
|
311
311
|
end
|
|
312
312
|
|
|
313
|
+
describe "parameterized queries" do
|
|
314
|
+
it "should return parameterized query with to_n1ql_with_params" do
|
|
315
|
+
relation = RelationModel.where(active: true, name: "Jane")
|
|
316
|
+
n1ql, params = relation.send(:to_n1ql_with_params)
|
|
317
|
+
expect(n1ql).to include("type = 'relation_model'")
|
|
318
|
+
expect(n1ql).to include("active = $1")
|
|
319
|
+
expect(n1ql).to include("name = $2")
|
|
320
|
+
expect(n1ql).not_to include("'Jane'")
|
|
321
|
+
expect(params).to eq([true, "Jane"])
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
it "should parameterize NOT conditions" do
|
|
325
|
+
relation = RelationModel.not(active: true)
|
|
326
|
+
n1ql, params = relation.send(:to_n1ql_with_params)
|
|
327
|
+
expect(n1ql).to include("active != $1")
|
|
328
|
+
expect(params).to eq([true])
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
it "should parameterize range conditions" do
|
|
332
|
+
relation = RelationModel.where(age: 10..30)
|
|
333
|
+
n1ql, params = relation.send(:to_n1ql_with_params)
|
|
334
|
+
expect(n1ql).to include("age >= $1")
|
|
335
|
+
expect(n1ql).to include("age <= $2")
|
|
336
|
+
expect(params).to eq([10, 30])
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
it "should parameterize hash operator conditions" do
|
|
340
|
+
relation = RelationModel.where(age: { _gte: 18, _lt: 65 })
|
|
341
|
+
n1ql, params = relation.send(:to_n1ql_with_params)
|
|
342
|
+
expect(n1ql).to include("age >= $1")
|
|
343
|
+
expect(n1ql).to include("age < $2")
|
|
344
|
+
expect(params).to eq([18, 65])
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
it "should pass through string conditions without parameterization" do
|
|
348
|
+
relation = RelationModel.where("active = true")
|
|
349
|
+
n1ql, params = relation.send(:to_n1ql_with_params)
|
|
350
|
+
expect(n1ql).to include("(active = true)")
|
|
351
|
+
expect(params).to eq([])
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
it "should parameterize array IN conditions" do
|
|
355
|
+
relation = RelationModel.where(name: ["Alice", "Bob"])
|
|
356
|
+
n1ql, params = relation.send(:to_n1ql_with_params)
|
|
357
|
+
expect(n1ql).to include("name IN $1")
|
|
358
|
+
expect(params).to eq([["Alice", "Bob"]])
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
313
362
|
describe "operators" do
|
|
314
363
|
it "should query by gte and lte" do
|
|
315
364
|
_m1 = RelationModel.create!(age: 10)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: couchbase-orm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0
|
|
4
|
+
version: 3.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stephen von Takach
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date: 2026-06-
|
|
14
|
+
date: 2026-06-30 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: activemodel
|