groovy 0.6.8 → 0.7.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/groovy/model.rb +127 -35
- data/lib/groovy/query.rb +10 -4
- data/lib/groovy/schema.rb +23 -13
- data/lib/groovy/version.rb +1 -1
- data/spec/callbacks_spec.rb +2 -4
- data/spec/model_spec.rb +0 -4
- data/spec/schema_spec.rb +74 -0
- data/spec/search_spec.rb +22 -1
- data/spec/vector_spec.rb +7 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc2860dffbf2ed0ba7df5db1d728766f8da5cd2ddd0e5bf4a07268307c54b6bb
|
4
|
+
data.tar.gz: 5175d60fd1e3ad3f78e9d87e08fd10ba90845e7d29e4e73e6214e2326bb92c2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57a8880213de3b723057090d0928068716ecbe8ff89b3e19867d485febcfb9af2efd998fcee011cce9e3a30cac164f6ad8612312f5824a6b962ccbd7d12e6fec
|
7
|
+
data.tar.gz: 70fce1c4f7152dbe6630d39ffe9286bf767ce1dad244636d5e8d9284b12f6c4cb31af15714c94b7da38439e3ce3404cab94543e2f8740162b199516da6115492
|
data/lib/groovy/model.rb
CHANGED
@@ -17,6 +17,31 @@ module Groovy
|
|
17
17
|
@models ||= {}
|
18
18
|
end
|
19
19
|
|
20
|
+
module Utils
|
21
|
+
def self.singularize(str)
|
22
|
+
str.to_s.sub(/ies$/, 'y').sub(/s$/, '')
|
23
|
+
end
|
24
|
+
|
25
|
+
# category -> categories
|
26
|
+
# product -> products
|
27
|
+
def self.pluralize(str)
|
28
|
+
return str if str[-1] == 's' # already ends with s, assume already plural
|
29
|
+
str.to_s.sub(/y$/, 'ie') + 's'
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.pluralize_and_classify(str)
|
33
|
+
classify(pluralize(str))
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.underscore(str)
|
37
|
+
str.gsub(/([A-Z])/) { |x| "_#{x.downcase}" }.sub(/^_/, '')
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.classify(str)
|
41
|
+
str.to_s.gsub(/([A-Z])/, '_\1').split('_').collect! { |w| w.capitalize }.join
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
20
45
|
module Model
|
21
46
|
|
22
47
|
def self.initialize_from_record(obj)
|
@@ -30,23 +55,21 @@ module Groovy
|
|
30
55
|
# end
|
31
56
|
|
32
57
|
def self.model_from_table(table_name)
|
33
|
-
get_class(
|
58
|
+
get_class(Utils.singularize(table_name))
|
34
59
|
end
|
35
60
|
|
36
61
|
def self.included(base)
|
37
62
|
base.extend(ClassMethods)
|
38
63
|
base.include(Forwardable)
|
39
|
-
base.table_name = base.name
|
64
|
+
base.table_name = Utils.pluralize(base.name)
|
40
65
|
|
41
66
|
# add to global model list
|
42
67
|
# Groovy.models[base.name] = base
|
43
68
|
Groovy.models[base.table_name] = base
|
44
69
|
end
|
45
70
|
|
46
|
-
def self.get_class(
|
47
|
-
|
48
|
-
classified = table_name.gsub(/([A-Z])/, '_\1').split('_').collect! { |w| w.capitalize }.join
|
49
|
-
Kernel.const_get(classified)
|
71
|
+
def self.get_class(klass_name)
|
72
|
+
Kernel.const_get(Utils.classify(klass_name))
|
50
73
|
end
|
51
74
|
|
52
75
|
module ClassMethods
|
@@ -63,11 +86,15 @@ module Groovy
|
|
63
86
|
end
|
64
87
|
|
65
88
|
def underscore_name
|
66
|
-
|
89
|
+
Utils.underscore(name)
|
67
90
|
end
|
68
91
|
|
69
92
|
def attribute_names
|
70
|
-
|
93
|
+
schema.attribute_columns
|
94
|
+
end
|
95
|
+
|
96
|
+
def reference_names
|
97
|
+
schema.singular_references + schema.plural_references
|
71
98
|
end
|
72
99
|
|
73
100
|
# def singular_refs
|
@@ -87,11 +114,13 @@ module Groovy
|
|
87
114
|
self.context_name = options[:context] || Groovy.first_context_name
|
88
115
|
self.table_name = options[:table_name] if options[:table_name]
|
89
116
|
|
90
|
-
s = Schema.new(db_context, table_name,
|
117
|
+
s = Schema.new(db_context, table_name, options)
|
91
118
|
yield s if block
|
92
119
|
s.sync
|
93
120
|
|
94
|
-
|
121
|
+
include(HashTable) if table.is_a?(Groonga::Hash)
|
122
|
+
include(PatriciaTrieTable) if table.is_a?(Groonga::PatriciaTrie)
|
123
|
+
|
95
124
|
s.column_names.each { |col| add_accessors_for(col, s) }
|
96
125
|
s
|
97
126
|
end
|
@@ -118,7 +147,7 @@ module Groovy
|
|
118
147
|
elsif s.plural_references.include?(col)
|
119
148
|
add_vector_accessors(col)
|
120
149
|
else
|
121
|
-
|
150
|
+
raise "Unknown column type: #{col}"
|
122
151
|
end
|
123
152
|
end
|
124
153
|
|
@@ -147,13 +176,13 @@ module Groovy
|
|
147
176
|
end
|
148
177
|
end
|
149
178
|
|
150
|
-
def create(attributes
|
151
|
-
obj = new(attributes
|
179
|
+
def create(attributes)
|
180
|
+
obj = new(attributes)
|
152
181
|
obj.save ? obj : false
|
153
182
|
end
|
154
183
|
|
155
|
-
def create!(attributes
|
156
|
-
create(attributes
|
184
|
+
def create!(attributes)
|
185
|
+
create(attributes) or raise Error, "Invalid"
|
157
186
|
end
|
158
187
|
|
159
188
|
def update_all(attrs)
|
@@ -174,6 +203,12 @@ module Groovy
|
|
174
203
|
# Groonga["#{table_name}.#{name}"] # .search, .similar_search, etc
|
175
204
|
# end
|
176
205
|
|
206
|
+
def search_table
|
207
|
+
schema.search_table
|
208
|
+
end
|
209
|
+
|
210
|
+
def_instance_delegators :search_table, :prefix_search, :each_with_prefix # just these two for now
|
211
|
+
|
177
212
|
def index_search(column, query, options = {}, &block)
|
178
213
|
results = table.select { |rec| rec[column].match(query) }
|
179
214
|
render_results(results, &block)
|
@@ -230,6 +265,10 @@ module Groovy
|
|
230
265
|
query.where(*args, &block)
|
231
266
|
end
|
232
267
|
|
268
|
+
def find_or_create_by(attributes)
|
269
|
+
find_by(**attributes) || create(**attributes)
|
270
|
+
end
|
271
|
+
|
233
272
|
[:first, :last, :select, :find_by, :search, :not, :sort_by, :in_batches, :limit, :offset, :paginate].each do |scope_method|
|
234
273
|
define_method scope_method do |**args, &block|
|
235
274
|
query.public_send(scope_method, **args, &block)
|
@@ -308,21 +347,80 @@ module Groovy
|
|
308
347
|
end
|
309
348
|
end
|
310
349
|
|
311
|
-
module
|
312
|
-
|
313
|
-
|
350
|
+
module PatriciaTrieTable
|
351
|
+
def self.included(base)
|
352
|
+
base.extend(ClassMethods)
|
353
|
+
end
|
354
|
+
|
355
|
+
module ClassMethods
|
356
|
+
extend Forwardable
|
357
|
+
def_instance_delegators :table, :scan, :prefix_search, :open_prefix_cursor, \
|
358
|
+
:suffix_search, :open_near_cursor, :tag_keys
|
359
|
+
|
360
|
+
def each_with_prefix(prefix, options = {}, &block)
|
361
|
+
table.open_prefix_cursor(prefix, options) do |cursor|
|
362
|
+
cursor.each { |r| yield r }
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
def each_near(str, options = {}, &block)
|
367
|
+
table.open_near_cursor(str, options) do |cursor|
|
368
|
+
cursor.each { |r| yield r }
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
module HashTable
|
375
|
+
def self.included(base)
|
376
|
+
base.extend(ClassMethods)
|
377
|
+
end
|
378
|
+
|
379
|
+
module ClassMethods
|
380
|
+
def find(key)
|
381
|
+
if record = table[key.to_s] and record.record_id
|
382
|
+
new_from_record(record)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
def new_from_record(record)
|
387
|
+
# new(record.attributes, record)
|
388
|
+
new(record._key, nil, record)
|
389
|
+
end
|
390
|
+
|
391
|
+
def create(key, attributes)
|
392
|
+
obj = new(key, attributes)
|
393
|
+
obj.save ? obj : false
|
394
|
+
end
|
314
395
|
|
315
|
-
|
316
|
-
|
317
|
-
cursor.each { |r| yield r }
|
396
|
+
def create!(key, attributes)
|
397
|
+
create(key, attributes) or raise Error, "Invalid"
|
318
398
|
end
|
319
399
|
end
|
400
|
+
|
401
|
+
def initialize(key, attrs = nil, record = nil)
|
402
|
+
@key = key
|
403
|
+
super(attrs, record)
|
404
|
+
end
|
405
|
+
|
406
|
+
def load_record
|
407
|
+
self.class.table[key]
|
408
|
+
end
|
409
|
+
|
410
|
+
# def new_record?
|
411
|
+
# key.nil?
|
412
|
+
# end
|
413
|
+
|
414
|
+
def key
|
415
|
+
@key || (record ? record._key : nil)
|
416
|
+
end
|
417
|
+
|
320
418
|
end
|
321
419
|
|
322
420
|
attr_reader :id, :record, :changes
|
323
421
|
|
324
|
-
def initialize(attrs = nil, record = nil
|
325
|
-
@attributes, @vectors
|
422
|
+
def initialize(attrs = nil, record = nil)
|
423
|
+
@attributes, @vectors = {}, {}
|
326
424
|
@foreign_refs_to_update = {}
|
327
425
|
|
328
426
|
if set_record(record)
|
@@ -344,9 +442,9 @@ module Groovy
|
|
344
442
|
|
345
443
|
# get reference to the actual record in the Groonga table,
|
346
444
|
# not the temporary one we get as part of a search result.
|
347
|
-
|
348
|
-
|
349
|
-
|
445
|
+
def load_record
|
446
|
+
self.class.table[id]
|
447
|
+
end
|
350
448
|
|
351
449
|
def attributes
|
352
450
|
load_attributes_from_record # populate missing
|
@@ -356,7 +454,7 @@ module Groovy
|
|
356
454
|
alias_method :attrs, :attributes
|
357
455
|
|
358
456
|
def inspect
|
359
|
-
"#<#{self.class.name} id:#{id.inspect} attributes:[#{self.class.attribute_names.join(', ')}]>"
|
457
|
+
"#<#{self.class.name} id:#{id.inspect} attributes:[#{self.class.attribute_names.join(', ')}] references:[#{self.class.reference_names.join(', ')}]>"
|
360
458
|
end
|
361
459
|
|
362
460
|
def dump
|
@@ -365,7 +463,6 @@ module Groovy
|
|
365
463
|
|
366
464
|
def new_record?
|
367
465
|
id.nil?
|
368
|
-
# _key.nil?
|
369
466
|
end
|
370
467
|
|
371
468
|
def persisted?
|
@@ -455,7 +552,7 @@ module Groovy
|
|
455
552
|
unless new_record?
|
456
553
|
# raise RecordNotPersisted if id.nil?
|
457
554
|
# ensure_persisted!
|
458
|
-
rec =
|
555
|
+
rec = load_record
|
459
556
|
set_record(rec)
|
460
557
|
# load_attributes_from_record
|
461
558
|
end
|
@@ -494,11 +591,6 @@ module Groovy
|
|
494
591
|
return val.to_i == 0 ? nil : val
|
495
592
|
end
|
496
593
|
|
497
|
-
# def _key
|
498
|
-
# return unless record
|
499
|
-
# record.respond_to?(:_key) ? record._key : id
|
500
|
-
# end
|
501
|
-
|
502
594
|
def load_attributes_from_record
|
503
595
|
self.class.attribute_names.each do |col|
|
504
596
|
public_send("#{col}=", get_record_attribute(col)) unless @attributes.key?(col)
|
@@ -545,7 +637,7 @@ module Groovy
|
|
545
637
|
|
546
638
|
def create
|
547
639
|
fire_callbacks(:before_create)
|
548
|
-
set_record(self.class.insert(@attributes, @
|
640
|
+
set_record(self.class.insert(@attributes, @key))
|
549
641
|
update_foreign_refs
|
550
642
|
fire_callbacks(:after_create)
|
551
643
|
self
|
data/lib/groovy/query.rb
CHANGED
@@ -80,20 +80,26 @@ module Groovy
|
|
80
80
|
add_param(AND + "(#{map_operator(handle_timestamps(conditions))})")
|
81
81
|
when Hash # { foo: 'bar' } or { views: 1..100 }
|
82
82
|
conditions.each do |key, val|
|
83
|
-
|
83
|
+
case val
|
84
|
+
when Model
|
85
|
+
raise "Object not persisted yet!" unless val.persisted?
|
86
|
+
str = "#{key}:#{val.id}"
|
87
|
+
add_param(AND + str)
|
88
|
+
|
89
|
+
when Range
|
84
90
|
add_param(AND + [key, val.min].join(':>=')) if val.min # lte
|
85
91
|
add_param(AND + [key, val.max].join(':<=')) if val.max # gte
|
86
92
|
|
87
|
-
|
93
|
+
when Regexp
|
88
94
|
str = val.source.gsub('/', '_slash_').gsub('(', '_openp_').gsub(')', '_closep_').gsub(REMOVE_INVALID_CHARS_REGEX, '')
|
89
95
|
param = val.source[0] == '^' ? ':^' : val.source[-1] == '$' ? ':$' : ':~' # starts with or regexp
|
90
96
|
add_param(AND + [key, str.downcase].join(param)) # regex must be downcase
|
91
97
|
|
92
|
-
|
98
|
+
when Array # { foo: [1,2,3] }
|
93
99
|
str = "#{key}:#{val.join(" OR #{key}:")}"
|
94
100
|
add_param(AND + str)
|
95
101
|
|
96
|
-
|
102
|
+
when Time
|
97
103
|
# The second, specify the timestamp as string in following format:
|
98
104
|
# “(YEAR)/(MONTH)/(DAY) (HOUR):(MINUTE):(SECOND)”
|
99
105
|
|
data/lib/groovy/schema.rb
CHANGED
@@ -4,6 +4,14 @@ module Groovy
|
|
4
4
|
class Schema
|
5
5
|
|
6
6
|
SEARCH_TABLE_NAME = 'Terms'.freeze
|
7
|
+
|
8
|
+
SEARCH_TABLE_OPTIONS = {
|
9
|
+
type: :patricia_trie,
|
10
|
+
normalizer: :NormalizerAuto,
|
11
|
+
key_type: "ShortText",
|
12
|
+
default_tokenizer: "TokenBigram"
|
13
|
+
}.freeze
|
14
|
+
|
7
15
|
COLUMN_DEFAULTS = {
|
8
16
|
compress: :zstandard
|
9
17
|
}.freeze
|
@@ -33,6 +41,10 @@ module Groovy
|
|
33
41
|
@table ||= context[table_name]
|
34
42
|
end
|
35
43
|
|
44
|
+
def table_type
|
45
|
+
(@opts[:type] || :array).to_sym
|
46
|
+
end
|
47
|
+
|
36
48
|
# def [](key)
|
37
49
|
# # @spec[key.to_sym]
|
38
50
|
# table.columns.select { |c| c.column? && c.name.to_s == "#{table_name}.#{key.to_s}" }
|
@@ -115,11 +127,11 @@ module Groovy
|
|
115
127
|
end
|
116
128
|
|
117
129
|
def reference(name, table_name = nil, options = {})
|
118
|
-
table_name =
|
130
|
+
table_name = Utils.pluralize_and_classify(name) if table_name.nil?
|
119
131
|
|
120
132
|
unless context[table_name]
|
121
133
|
log "Table #{table_name} doesn't exist yet! Creating now..."
|
122
|
-
create_table!(table_name)
|
134
|
+
create_table!(table_name, nil)
|
123
135
|
end
|
124
136
|
|
125
137
|
refs_by_table[table_name] = name.to_sym
|
@@ -174,19 +186,17 @@ module Groovy
|
|
174
186
|
name_col = [table_name, col].join('.')
|
175
187
|
log "Adding index on #{name_col}"
|
176
188
|
Groonga::Schema.change_table(SEARCH_TABLE_NAME, context: context) do |table|
|
177
|
-
#
|
178
|
-
|
189
|
+
if opts[:search] # search column requires with_position: true
|
190
|
+
table.index(name_col, name: name_col, with_position: true, with_section: true)
|
191
|
+
else
|
192
|
+
table.index(name_col, name: name_col.sub('.', '_'))
|
193
|
+
end
|
179
194
|
end
|
180
195
|
end
|
181
196
|
|
182
197
|
def ensure_search_table!
|
183
198
|
return if search_table
|
184
|
-
opts = (@opts[:search_table] || {}).merge(
|
185
|
-
type: :patricia_trie,
|
186
|
-
normalizer: :NormalizerAuto,
|
187
|
-
key_type: "ShortText",
|
188
|
-
default_tokenizer: "TokenBigram"
|
189
|
-
})
|
199
|
+
opts = (@opts[:search_table] || {}).merge(SEARCH_TABLE_OPTIONS)
|
190
200
|
log("Creating search table with options: #{opts.inspect}")
|
191
201
|
Groonga::Schema.create_table(SEARCH_TABLE_NAME, opts.merge(context: context))
|
192
202
|
end
|
@@ -225,9 +235,9 @@ module Groovy
|
|
225
235
|
end
|
226
236
|
end
|
227
237
|
|
228
|
-
def create_table!(name = table_name)
|
229
|
-
log "Creating table #{name}!"
|
230
|
-
Groonga::Schema.create_table(name, context: context)
|
238
|
+
def create_table!(name = table_name, type = table_type)
|
239
|
+
log "Creating table #{name} with type #{type.inspect}!"
|
240
|
+
Groonga::Schema.create_table(name, context: context, type: type)
|
231
241
|
end
|
232
242
|
|
233
243
|
def remove_table!(name = table_name)
|
data/lib/groovy/version.rb
CHANGED
data/spec/callbacks_spec.rb
CHANGED
@@ -4,14 +4,14 @@ describe Groovy::Model do
|
|
4
4
|
|
5
5
|
before :all do
|
6
6
|
Groovy.open('tmp/callbacks', 'callbacks_spec')
|
7
|
-
|
7
|
+
load_test_schema!
|
8
8
|
end
|
9
9
|
|
10
10
|
after :all do
|
11
11
|
Groovy.close('callbacks_spec')
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def load_test_schema!
|
15
15
|
klass = Class.new
|
16
16
|
Object.const_set("User", klass)
|
17
17
|
User.class_eval do
|
@@ -35,8 +35,6 @@ describe Groovy::Model do
|
|
35
35
|
# puts "updated"
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
39
|
-
User.add_reference :comments, "Comments", type: :vector
|
40
38
|
end
|
41
39
|
|
42
40
|
it 'fires created callbacks' do
|
data/spec/model_spec.rb
CHANGED
@@ -15,7 +15,6 @@ describe Groovy::Model do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
describe '.scope' do
|
18
|
-
|
19
18
|
before :all do
|
20
19
|
TestProduct.class_eval do
|
21
20
|
scope :with_name, -> (name) { where(name: name) if name }
|
@@ -147,15 +146,12 @@ describe Groovy::Model do
|
|
147
146
|
end
|
148
147
|
|
149
148
|
describe 'attributes accessors' do
|
150
|
-
|
151
149
|
end
|
152
150
|
|
153
151
|
describe 'singular refs' do
|
154
|
-
|
155
152
|
end
|
156
153
|
|
157
154
|
describe 'plural refs' do
|
158
|
-
|
159
155
|
end
|
160
156
|
|
161
157
|
end
|
data/spec/schema_spec.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
|
3
|
+
describe Groovy::Model do
|
4
|
+
|
5
|
+
CONTEXT_NAME = 'schema_spec'
|
6
|
+
|
7
|
+
before :all do
|
8
|
+
Groovy.open('tmp/' + CONTEXT_NAME, CONTEXT_NAME)
|
9
|
+
load_test_schema!
|
10
|
+
end
|
11
|
+
|
12
|
+
after :all do
|
13
|
+
Groovy.close(CONTEXT_NAME)
|
14
|
+
end
|
15
|
+
|
16
|
+
def load_test_schema!
|
17
|
+
klass = Class.new
|
18
|
+
Object.const_set("Product", klass)
|
19
|
+
Product.class_eval do
|
20
|
+
include Groovy::Model
|
21
|
+
|
22
|
+
schema(type: 'hash', context: CONTEXT_NAME) do |t|
|
23
|
+
t.string :name
|
24
|
+
t.many :categories
|
25
|
+
t.timestamps
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
klass = Class.new
|
30
|
+
Object.const_set("Category", klass)
|
31
|
+
Category.class_eval do
|
32
|
+
include Groovy::Model
|
33
|
+
|
34
|
+
schema(context: CONTEXT_NAME) do |t|
|
35
|
+
t.many :products, "Products"
|
36
|
+
t.string :name
|
37
|
+
t.timestamps
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'hash table' do
|
43
|
+
|
44
|
+
it 'creates, updates and finds records as expected' do
|
45
|
+
product = Product.new('ipod-mini', name: 'iPod Mini')
|
46
|
+
expect(product.new_record?).to eq(true)
|
47
|
+
|
48
|
+
expect(product.name).to eq('iPod Mini')
|
49
|
+
expect(product.save).to eq(true)
|
50
|
+
expect(product.persisted?).to eq(true)
|
51
|
+
expect(product.key).to eq('ipod-mini')
|
52
|
+
|
53
|
+
expect(product.update_attributes(name: 'iPod Mini 2nd Generation'))
|
54
|
+
expect(product.name).to eq('iPod Mini 2nd Generation')
|
55
|
+
|
56
|
+
expect(Product.find('ipod-mini')).to eq(product)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'works with references too' do
|
60
|
+
product = Product.new('ipod-mini', name: 'iPod Mini')
|
61
|
+
expect(product.save).to eq(true)
|
62
|
+
|
63
|
+
category = Category.new(name: 'iPods')
|
64
|
+
expect(category.save).to eq(true)
|
65
|
+
|
66
|
+
category.products << product
|
67
|
+
product.categories << category
|
68
|
+
|
69
|
+
expect(product.reload.categories).to eq([category])
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
data/spec/search_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe Groovy::Model, 'searching' do
|
|
6
6
|
Groovy.open('tmp/search', 'search_spec')
|
7
7
|
load_schema! 'search_spec'
|
8
8
|
|
9
|
-
TestProduct.add_column :description, :string, index: true
|
9
|
+
TestProduct.add_column :description, :string, index: true #, search: true
|
10
10
|
|
11
11
|
TestProduct.create!(name: 'First product', description: 'Lorem ipsum dolor sit amet')
|
12
12
|
TestProduct.create!(name: 'Second product', description: 'Lorea el ipsum poh loco')
|
@@ -51,4 +51,25 @@ describe Groovy::Model, 'searching' do
|
|
51
51
|
expect(res.first.name).to eq('Second product')
|
52
52
|
end
|
53
53
|
end
|
54
|
+
|
55
|
+
describe 'prefix search' do
|
56
|
+
it 'returns results' do
|
57
|
+
res = TestProduct.prefix_search('Lore')
|
58
|
+
expect(res.count).to eq(0)
|
59
|
+
|
60
|
+
res = TestProduct.prefix_search('lore')
|
61
|
+
expect(res.count).to eq(2)
|
62
|
+
expect(res.first).to be_a(Groonga::Record)
|
63
|
+
parts = res.map { |rec| rec['._key'] }
|
64
|
+
expect(parts).to eq(['lorem', 'lorea'])
|
65
|
+
end
|
66
|
+
|
67
|
+
# it 'works with each_with_prefix too' do
|
68
|
+
# parts = []
|
69
|
+
# res = TestProduct.each_with_prefix('lore') do |rec|
|
70
|
+
# parts.push(rec['._key'])
|
71
|
+
# end
|
72
|
+
# expect(parts).to eq(['lorem', 'lorea'])
|
73
|
+
# end
|
74
|
+
end
|
54
75
|
end
|
data/spec/vector_spec.rb
CHANGED
@@ -63,6 +63,13 @@ describe Groovy::Model do
|
|
63
63
|
expect(user2.reload.comments).to eq([])
|
64
64
|
end
|
65
65
|
|
66
|
+
it 'finds records using relations too' do
|
67
|
+
user = User.create(name: 'John')
|
68
|
+
comment = Comment.create(author: user, content: 'Hello there!')
|
69
|
+
|
70
|
+
expect(Comment.find_by(author: user)).to eq(comment)
|
71
|
+
end
|
72
|
+
|
66
73
|
end
|
67
74
|
|
68
75
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: groovy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomás Pollak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-12-
|
11
|
+
date: 2023-12-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rroonga
|
@@ -101,6 +101,7 @@ files:
|
|
101
101
|
- spec/groovy_spec.rb
|
102
102
|
- spec/model_spec.rb
|
103
103
|
- spec/query_spec.rb
|
104
|
+
- spec/schema_spec.rb
|
104
105
|
- spec/search_spec.rb
|
105
106
|
- spec/spec_helper.rb
|
106
107
|
- spec/vector_spec.rb
|