elastic_record 1.1.8 → 1.2.1
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/.travis.yml +4 -1
- data/Gemfile +3 -1
- data/elastic_record.gemspec +1 -1
- data/lib/elastic_record/callbacks.rb +2 -0
- data/lib/elastic_record/connection.rb +5 -9
- data/lib/elastic_record/index/mapping.rb +2 -2
- data/lib/elastic_record/model.rb +1 -1
- data/lib/elastic_record/relation/search_methods.rb +0 -9
- data/lib/elastic_record/relation/value_methods.rb +1 -1
- data/lib/elastic_record/relation.rb +7 -26
- data/lib/elastic_record.rb +0 -1
- data/test/elastic_record/config_test.rb +1 -1
- data/test/elastic_record/connection_test.rb +2 -2
- data/test/elastic_record/index/mapping_test.rb +11 -1
- data/test/elastic_record/integration/active_record_test.rb +62 -25
- data/test/elastic_record/relation_test.rb +0 -47
- data/test/helper.rb +1 -7
- data/test/support/models/test_model.rb +1 -19
- data/test/support/models/warehouse.rb +0 -1
- data/test/support/models/widget.rb +0 -2
- metadata +11 -24
- data/lib/elastic_record/searches_many/association.rb +0 -149
- data/lib/elastic_record/searches_many/autosave.rb +0 -72
- data/lib/elastic_record/searches_many/builder.rb +0 -42
- data/lib/elastic_record/searches_many/collection_proxy.rb +0 -26
- data/lib/elastic_record/searches_many/reflection.rb +0 -45
- data/lib/elastic_record/searches_many.rb +0 -100
- data/test/elastic_record/searches_many/association_test.rb +0 -47
- data/test/elastic_record/searches_many/autosave_test.rb +0 -32
- data/test/elastic_record/searches_many/collection_proxy_test.rb +0 -23
- data/test/elastic_record/searches_many/reflection_test.rb +0 -33
- data/test/elastic_record/searches_many_test.rb +0 -76
- data/test/support/models/option.rb +0 -24
- data/test/support/query_counter.rb +0 -56
@@ -1,149 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/module/delegation'
|
2
|
-
|
3
|
-
module ElasticRecord
|
4
|
-
module SearchesMany
|
5
|
-
class Association
|
6
|
-
attr_reader :owner, :reflection, :collection
|
7
|
-
|
8
|
-
delegate :klass, :options, to: :reflection
|
9
|
-
|
10
|
-
def initialize(owner, reflection)
|
11
|
-
@owner = owner
|
12
|
-
@reflection = reflection
|
13
|
-
@collection = []
|
14
|
-
@loaded = false
|
15
|
-
end
|
16
|
-
|
17
|
-
def writer(other_records)
|
18
|
-
other_records = other_records.map do |other_record|
|
19
|
-
other_record.is_a?(Hash) ? klass.new(other_record) : other_record
|
20
|
-
end
|
21
|
-
|
22
|
-
delete(load_collection - other_records)
|
23
|
-
merge_collections(load_collection, other_records)
|
24
|
-
concat(other_records - load_collection)
|
25
|
-
|
26
|
-
if reflection.counter_cache_column
|
27
|
-
owner.send("#{reflection.counter_cache_column}=", other_records.size)
|
28
|
-
end
|
29
|
-
|
30
|
-
if reflection.touch_column
|
31
|
-
owner.send("#{reflection.touch_column}=", Time.current)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def reader
|
36
|
-
CollectionProxy.new(self)
|
37
|
-
end
|
38
|
-
|
39
|
-
def loaded?
|
40
|
-
@loaded
|
41
|
-
end
|
42
|
-
|
43
|
-
def concat(*records)
|
44
|
-
load_collection if owner.new_record?
|
45
|
-
|
46
|
-
result = true
|
47
|
-
|
48
|
-
records.flatten.each do |record|
|
49
|
-
add_to_collection(record) do |r|
|
50
|
-
result &&= record.save unless owner.new_record?
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
result && records
|
55
|
-
end
|
56
|
-
|
57
|
-
def delete(records)
|
58
|
-
records.each do |record|
|
59
|
-
callback(:before_remove, record)
|
60
|
-
|
61
|
-
if options[:autosave] || owner.new_record?
|
62
|
-
record.mark_for_destruction
|
63
|
-
else
|
64
|
-
record.destroy
|
65
|
-
end
|
66
|
-
|
67
|
-
callback(:after_remove, record)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def scope
|
72
|
-
search = klass.elastic_search.filter("#{reflection.belongs_to}_id" => owner.id).limit(1000000)
|
73
|
-
if options[:as]
|
74
|
-
search.filter! "#{reflection.belongs_to}_type" => owner.class.name
|
75
|
-
end
|
76
|
-
search
|
77
|
-
end
|
78
|
-
|
79
|
-
def load_collection
|
80
|
-
unless @loaded
|
81
|
-
@collection = merge_collections(persisted_collection, collection)
|
82
|
-
@loaded = true
|
83
|
-
end
|
84
|
-
|
85
|
-
collection
|
86
|
-
end
|
87
|
-
|
88
|
-
def eager_loaded_collection(records)
|
89
|
-
unless @loaded
|
90
|
-
@collection = records
|
91
|
-
@loaded = true
|
92
|
-
end
|
93
|
-
|
94
|
-
collection
|
95
|
-
end
|
96
|
-
|
97
|
-
private
|
98
|
-
|
99
|
-
def load_persisted_collection?
|
100
|
-
!loaded? || owner.new_record?
|
101
|
-
end
|
102
|
-
|
103
|
-
def persisted_collection
|
104
|
-
@persisted_collection ||= scope.to_a
|
105
|
-
end
|
106
|
-
|
107
|
-
def merge_collections(existing_records, new_records)
|
108
|
-
return existing_records if new_records.empty?
|
109
|
-
return new_records if existing_records.empty?
|
110
|
-
|
111
|
-
existing_records.map! do |existing_record|
|
112
|
-
if new_record = new_records.delete(existing_record)
|
113
|
-
(existing_record.attributes.keys - new_record.changes.keys).each do |name|
|
114
|
-
new_record.send("#{name}=", existing_record.send(name))
|
115
|
-
end
|
116
|
-
|
117
|
-
new_record
|
118
|
-
else
|
119
|
-
existing_record
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
existing_records + new_records
|
124
|
-
end
|
125
|
-
|
126
|
-
def add_to_collection(record)
|
127
|
-
callback(:before_add, record)
|
128
|
-
|
129
|
-
record.send("#{reflection.belongs_to}=", owner)
|
130
|
-
yield(record) if block_given?
|
131
|
-
@collection << record
|
132
|
-
|
133
|
-
callback(:after_add, record)
|
134
|
-
|
135
|
-
record
|
136
|
-
end
|
137
|
-
|
138
|
-
def callback(method, record)
|
139
|
-
reflection.callbacks[method].each do |callback|
|
140
|
-
if callback.respond_to?(:call)
|
141
|
-
callback.call(owner, record)
|
142
|
-
else
|
143
|
-
owner.send(callback, record)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
module ElasticRecord
|
2
|
-
module SearchesMany
|
3
|
-
module Autosave
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
|
6
|
-
module ClassMethods
|
7
|
-
def add_autosave_callbacks(reflection)
|
8
|
-
add_autosave_after_save_callbacks(reflection)
|
9
|
-
add_autosave_validation_callbacks(reflection)
|
10
|
-
end
|
11
|
-
|
12
|
-
def add_autosave_after_save_callbacks(reflection)
|
13
|
-
before_save { save_autosave_records(reflection) }
|
14
|
-
end
|
15
|
-
|
16
|
-
def add_autosave_validation_callbacks(reflection)
|
17
|
-
validate { validate_autosave_records(reflection) }
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def save_autosave_records(reflection)
|
23
|
-
if association = searches_many_instance_get(reflection.name)
|
24
|
-
associated_records_to_autosave(association).each do |record|
|
25
|
-
if record.marked_for_destruction?
|
26
|
-
record.destroy
|
27
|
-
elsif record.changed?
|
28
|
-
record.save
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def validate_autosave_records(reflection)
|
35
|
-
if association = searches_many_instance_get(reflection.name)
|
36
|
-
associated_records_to_autosave(association).each do |record|
|
37
|
-
unless record.valid?
|
38
|
-
record.errors.each do |attribute, message|
|
39
|
-
attribute = "#{reflection.name}.#{attribute}"
|
40
|
-
errors[attribute] << message
|
41
|
-
errors[attribute].uniq!
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def associated_records_to_autosave(association)
|
49
|
-
if association.loaded?
|
50
|
-
association.load_collection
|
51
|
-
else
|
52
|
-
[]
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# Marks this record to be destroyed as part of the parents save transaction.
|
57
|
-
# This does _not_ actually destroy the record instantly, rather child record will be destroyed
|
58
|
-
# when <tt>parent.save</tt> is called.
|
59
|
-
#
|
60
|
-
# Only useful if the <tt>:autosave</tt> option on the parent is enabled for this associated model.
|
61
|
-
def mark_for_destruction
|
62
|
-
@marked_for_destruction = true
|
63
|
-
end
|
64
|
-
|
65
|
-
# Returns whether or not this record will be destroyed as part of the parents save transaction.
|
66
|
-
#
|
67
|
-
# Only useful if the <tt>:autosave</tt> option on the parent is enabled for this associated model.
|
68
|
-
def marked_for_destruction?
|
69
|
-
@marked_for_destruction
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
module ElasticRecord
|
2
|
-
module SearchesMany
|
3
|
-
class Builder
|
4
|
-
def self.build(model, name, options)
|
5
|
-
new(model, name, options).build
|
6
|
-
end
|
7
|
-
|
8
|
-
attr_reader :model, :name, :options
|
9
|
-
def initialize(model, name, options)
|
10
|
-
@model, @name, @options = model, name, options
|
11
|
-
end
|
12
|
-
|
13
|
-
def build
|
14
|
-
define_writer
|
15
|
-
define_reader
|
16
|
-
|
17
|
-
reflection = ElasticRecord::SearchesMany::Reflection.new(model, name, options)
|
18
|
-
model.searches_many_reflections = model.searches_many_reflections.merge(name => reflection)
|
19
|
-
|
20
|
-
model.add_autosave_callbacks(reflection) if options[:autosave]
|
21
|
-
end
|
22
|
-
|
23
|
-
def mixin
|
24
|
-
model.generated_searches_many_methods
|
25
|
-
end
|
26
|
-
|
27
|
-
def define_writer
|
28
|
-
name = self.name
|
29
|
-
mixin.redefine_method("#{name}=") do |records|
|
30
|
-
searches_many_association(name).writer(records)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def define_reader
|
35
|
-
name = self.name
|
36
|
-
mixin.redefine_method(name) do
|
37
|
-
searches_many_association(name).reader
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module ElasticRecord
|
2
|
-
module SearchesMany
|
3
|
-
class CollectionProxy < ElasticRecord::Relation
|
4
|
-
def initialize(association)
|
5
|
-
@association = association
|
6
|
-
super association.klass
|
7
|
-
merge! association.scope
|
8
|
-
end
|
9
|
-
|
10
|
-
def eager_loaded(records)
|
11
|
-
@association.eager_loaded_collection(records)
|
12
|
-
end
|
13
|
-
|
14
|
-
def to_a
|
15
|
-
records = @association.load_collection.reject(&:destroyed?)
|
16
|
-
records = eager_load_associations(records) if eager_loading?
|
17
|
-
records
|
18
|
-
end
|
19
|
-
|
20
|
-
def <<(*records)
|
21
|
-
@association.concat(records) && self
|
22
|
-
end
|
23
|
-
alias_method :push, :<<
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module ElasticRecord
|
2
|
-
module SearchesMany
|
3
|
-
class Reflection
|
4
|
-
attr_reader :model, :name, :options
|
5
|
-
attr_reader :callbacks
|
6
|
-
def initialize(model, name, options)
|
7
|
-
@model, @name, @options = model, name, options
|
8
|
-
@callbacks = define_callbacks(options)
|
9
|
-
end
|
10
|
-
|
11
|
-
def klass
|
12
|
-
klass_name.constantize
|
13
|
-
end
|
14
|
-
|
15
|
-
def klass_name
|
16
|
-
options[:class_name] || name.to_s.classify
|
17
|
-
end
|
18
|
-
|
19
|
-
def belongs_to
|
20
|
-
options[:as] ? options[:as].to_s : model.name.to_s.demodulize.underscore
|
21
|
-
end
|
22
|
-
|
23
|
-
def foreign_key
|
24
|
-
options[:foreign_key] ? options[:foreign_key].to_s : "#{model.name.to_s.demodulize.underscore}_id"
|
25
|
-
end
|
26
|
-
|
27
|
-
CALLBACKS = [:before_add, :after_add, :before_remove, :after_remove]
|
28
|
-
def define_callbacks(options)
|
29
|
-
Hash[CALLBACKS.map { |callback_name| [callback_name, Array(options[callback_name.to_sym])] }]
|
30
|
-
end
|
31
|
-
|
32
|
-
def touch_column
|
33
|
-
if options[:touch]
|
34
|
-
options[:touch] == true ? :updated_at : options[:touch].to_sym
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def counter_cache_column
|
39
|
-
if options[:counter_cache]
|
40
|
-
(options[:counter_cache] == true ? "#{name}_count" : options[:counter_cache]).to_sym
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,100 +0,0 @@
|
|
1
|
-
require 'elastic_record/searches_many/association'
|
2
|
-
require 'elastic_record/searches_many/autosave'
|
3
|
-
require 'elastic_record/searches_many/builder'
|
4
|
-
require 'elastic_record/searches_many/collection_proxy'
|
5
|
-
require 'elastic_record/searches_many/reflection'
|
6
|
-
|
7
|
-
module ElasticRecord
|
8
|
-
module SearchesMany
|
9
|
-
def self.included(base)
|
10
|
-
base.class_eval do
|
11
|
-
extend ClassMethods
|
12
|
-
|
13
|
-
class_attribute :searches_many_reflections
|
14
|
-
self.searches_many_reflections = {}
|
15
|
-
|
16
|
-
include ElasticRecord::SearchesMany::Autosave
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
module ClassMethods
|
21
|
-
# Specifies a one-to-many association. The following methods for retrieval and query of
|
22
|
-
# collections of associated objects will be added:
|
23
|
-
#
|
24
|
-
# [collection]
|
25
|
-
# Returns an array of all the associated objects.
|
26
|
-
# [collection=objects]
|
27
|
-
# Replaces the collections content by deleting and adding objects as appropriate.
|
28
|
-
# [collection_params=objects]
|
29
|
-
# Support for nested assignment from a form
|
30
|
-
# === Options
|
31
|
-
# [:as]
|
32
|
-
# Specifies a polymorphic interface (See <tt>belongs_to</tt>).
|
33
|
-
# [:touch]
|
34
|
-
# Specify to update the owner when changed. Specify <tt>true</tt>
|
35
|
-
# to update the updated_at field. If you specify a symbol, that attribute
|
36
|
-
# will be updated with the current time in addition to the updated_at/on attribute.
|
37
|
-
# [:autosave]
|
38
|
-
# If true, always save the associated objects or destroy them if marked for destruction, when
|
39
|
-
# saving the parent object.
|
40
|
-
# [:counter_cache]
|
41
|
-
# Caches the number of belonging objects on the associate class. This requires that a column
|
42
|
-
# named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
|
43
|
-
# is used on the associate class (such as a Post class). You can also specify a custom counter
|
44
|
-
# cache column by providing a column name instead of a +true+/+false+ value to this
|
45
|
-
# option (e.g., <tt>:counter_cache => :my_custom_counter</tt>.)
|
46
|
-
# [:class_name]
|
47
|
-
# Specify the class name of the association. Use it only if that name can't be inferred
|
48
|
-
# from the association name. So <tt>has_one :manager</tt> will by default be linked to the Manager class, but
|
49
|
-
# if the real class name is Person, you'll have to specify it with this option.
|
50
|
-
#
|
51
|
-
# === Example
|
52
|
-
#
|
53
|
-
# Example: A Firm class declares <tt>has_many :clients</tt>, which will add:
|
54
|
-
# * <tt>Firm#clients</tt>
|
55
|
-
# * <tt>Firm#clients=(objects)</tt>
|
56
|
-
# * <tt>Firm#client_params=(params)</tt>
|
57
|
-
def searches_many(name, options = {})
|
58
|
-
ElasticRecord::SearchesMany::Builder.build(self, name, options)
|
59
|
-
end
|
60
|
-
|
61
|
-
def generated_searches_many_methods
|
62
|
-
@generated_searches_many_methods ||= begin
|
63
|
-
mod = const_set(:GeneratedSearchesManyMethods, Module.new)
|
64
|
-
include mod
|
65
|
-
mod
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# Returns the searches_many instance for the given name, instantiating it if it doesn't already exist
|
71
|
-
def searches_many_association(name)
|
72
|
-
association = searches_many_instance_get(name)
|
73
|
-
|
74
|
-
if association.nil?
|
75
|
-
association = ElasticRecord::SearchesMany::Association.new(self, searches_many_reflections[name])
|
76
|
-
searches_many_instance_set(name, association)
|
77
|
-
end
|
78
|
-
|
79
|
-
association
|
80
|
-
end
|
81
|
-
|
82
|
-
def reload
|
83
|
-
super
|
84
|
-
searches_many_cache.clear
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
def searches_many_cache
|
89
|
-
@searches_many_cache ||= {}
|
90
|
-
end
|
91
|
-
|
92
|
-
def searches_many_instance_get(name)
|
93
|
-
searches_many_cache[name.to_sym]
|
94
|
-
end
|
95
|
-
|
96
|
-
def searches_many_instance_set(name, association)
|
97
|
-
searches_many_cache[name.to_sym] = association
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class ElasticRecord::SearchesMany::AssociationTest < MiniTest::Spec
|
4
|
-
|
5
|
-
def test_writer_assignment_from_hash
|
6
|
-
warehouse = Warehouse.new
|
7
|
-
warehouse.widgets = [{color: 'blue', name: 'thing'}]
|
8
|
-
|
9
|
-
assert_equal 1, warehouse.widgets.all.count
|
10
|
-
expected = {
|
11
|
-
'color' => 'blue',
|
12
|
-
'name' => 'thing',
|
13
|
-
'warehouse_id' => warehouse.id,
|
14
|
-
}
|
15
|
-
assert_equal expected, warehouse.widgets[0].attributes
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_writer
|
19
|
-
warehouse = Warehouse.new
|
20
|
-
|
21
|
-
warehouse.widgets = [{color: 'blue', name: 'thing'}]
|
22
|
-
|
23
|
-
assert_equal 1, warehouse.widgets.all.count
|
24
|
-
|
25
|
-
warehouse.widgets = [ {color: 'red', name: 'device'}, {color: 'blue', name: 'thing'} ]
|
26
|
-
|
27
|
-
assert_equal 3, warehouse.widgets.all.count
|
28
|
-
assert warehouse.widgets[0].marked_for_destruction?
|
29
|
-
refute warehouse.widgets[1].marked_for_destruction?
|
30
|
-
refute warehouse.widgets[2].marked_for_destruction?
|
31
|
-
|
32
|
-
expected = {
|
33
|
-
'color' => 'red',
|
34
|
-
'name' => 'device',
|
35
|
-
'warehouse_id' => warehouse.id,
|
36
|
-
}
|
37
|
-
assert_equal expected, warehouse.widgets[1].attributes
|
38
|
-
|
39
|
-
expected = {
|
40
|
-
'color' => 'blue',
|
41
|
-
'name' => 'thing',
|
42
|
-
'warehouse_id' => warehouse.id,
|
43
|
-
}
|
44
|
-
assert_equal expected, warehouse.widgets[2].attributes
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class ElasticRecord::SearchesMany::AutosaveTest < MiniTest::Unit::TestCase
|
4
|
-
def test_save_associations_autosave_callback
|
5
|
-
warehouse = Warehouse.new
|
6
|
-
widget = Widget.new
|
7
|
-
warehouse.widgets = [widget]
|
8
|
-
assert warehouse.new_record?
|
9
|
-
assert widget.new_record?
|
10
|
-
|
11
|
-
warehouse.save
|
12
|
-
|
13
|
-
assert widget.persisted?
|
14
|
-
end
|
15
|
-
|
16
|
-
def test_validate_associations_autosave_callback
|
17
|
-
warehouse = Warehouse.new
|
18
|
-
widget = Widget.new color: 123
|
19
|
-
warehouse.widgets = [widget]
|
20
|
-
|
21
|
-
assert warehouse.invalid?
|
22
|
-
assert_equal ["is invalid"], warehouse.errors['widgets.color']
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_mark_for_destruction
|
26
|
-
widget = Widget.new
|
27
|
-
|
28
|
-
widget.mark_for_destruction
|
29
|
-
|
30
|
-
assert widget.marked_for_destruction?
|
31
|
-
end
|
32
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class ElasticRecord::SearchesMany::CollectionProxyTest < MiniTest::Unit::TestCase
|
4
|
-
def test_add_to_new_record
|
5
|
-
warehouse = Warehouse.new
|
6
|
-
widget = Widget.new
|
7
|
-
|
8
|
-
warehouse.widgets << widget
|
9
|
-
|
10
|
-
assert widget.new_record?
|
11
|
-
assert_equal [widget], warehouse.widgets
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_add_to_persisted_record
|
15
|
-
warehouse = Warehouse.create
|
16
|
-
widget = Widget.new
|
17
|
-
|
18
|
-
warehouse.widgets << widget
|
19
|
-
|
20
|
-
assert !widget.new_record?
|
21
|
-
assert_equal [widget], warehouse.widgets
|
22
|
-
end
|
23
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class ElasticRecord::SearchesMany::ReflectionTest < MiniTest::Unit::TestCase
|
4
|
-
|
5
|
-
def test_foreiegn_key
|
6
|
-
assert_equal 'warehouse_id', reflection_class.new(Warehouse, :widgets, {}).foreign_key
|
7
|
-
assert_equal 'foo_id', reflection_class.new(Warehouse, :widgets, {:foreign_key => 'foo_id' }).foreign_key
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_klass_name
|
11
|
-
assert_equal 'Product', reflection_class.new(Warehouse, :widgets, {class_name: 'Product'}).klass_name
|
12
|
-
assert_equal 'Widget', reflection_class.new(Warehouse, :widgets, {}).klass_name
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_touch_column
|
16
|
-
assert_nil reflection_class.new(Warehouse, :widgets, {}).touch_column
|
17
|
-
assert_equal :updated_at, reflection_class.new(Warehouse, :widgets, touch: true).touch_column
|
18
|
-
assert_equal :my_column, reflection_class.new(Warehouse, :widgets, touch: :my_column).touch_column
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_counter_cache_column
|
22
|
-
assert_nil reflection_class.new(Warehouse, :widgets, {}).counter_cache_column
|
23
|
-
assert_equal :widgets_count, reflection_class.new(Warehouse, :widgets, counter_cache: true).counter_cache_column
|
24
|
-
assert_equal :my_column, reflection_class.new(Warehouse, :widgets, counter_cache: :my_column).counter_cache_column
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def reflection_class
|
30
|
-
ElasticRecord::SearchesMany::Reflection
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class ElasticRecord::SearchesManyTest < MiniTest::Unit::TestCase
|
4
|
-
def test_reader
|
5
|
-
warehouse = Warehouse.create
|
6
|
-
related_widget = Widget.create warehouse: warehouse
|
7
|
-
unrelated_widget = Widget.create
|
8
|
-
|
9
|
-
assert_equal [related_widget], warehouse.widgets
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_write_with_objects
|
13
|
-
warehouse = Warehouse.new
|
14
|
-
widget = Widget.new
|
15
|
-
|
16
|
-
warehouse.widgets = [widget]
|
17
|
-
|
18
|
-
assert widget.new_record?
|
19
|
-
assert_equal warehouse.id, widget.warehouse_id
|
20
|
-
# assert_equal 1, warehouse.widgets_count
|
21
|
-
# assert_in_delta Time.current, warehouse.widgets_updated_at, 5
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_write_with_attributes
|
25
|
-
warehouse = Warehouse.new
|
26
|
-
|
27
|
-
warehouse.widgets = [
|
28
|
-
{
|
29
|
-
color: 'blue',
|
30
|
-
name: 'Toy'
|
31
|
-
}
|
32
|
-
]
|
33
|
-
|
34
|
-
widgets = warehouse.widgets
|
35
|
-
assert_equal 1, widgets.size
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_write_marks_destroyed
|
39
|
-
warehouse = Warehouse.new
|
40
|
-
widget = Widget.create warehouse: warehouse
|
41
|
-
|
42
|
-
warehouse.widgets = []
|
43
|
-
|
44
|
-
association = warehouse.searches_many_association(:widgets)
|
45
|
-
assert_equal 1, association.reader.size
|
46
|
-
assert association.reader.first.marked_for_destruction?
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_write_existing_record
|
50
|
-
widget = Widget.create name: 'Toy', color: 'green'
|
51
|
-
warehouse = Warehouse.new widgets: [widget]
|
52
|
-
|
53
|
-
warehouse.widgets = [
|
54
|
-
{
|
55
|
-
id: widget.id,
|
56
|
-
color: "blue"
|
57
|
-
}
|
58
|
-
]
|
59
|
-
|
60
|
-
widgets = warehouse.widgets
|
61
|
-
assert_equal 1, widgets.size
|
62
|
-
assert_equal "blue", widgets.first.color
|
63
|
-
assert_equal "Toy", widgets.first.name
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_reload
|
67
|
-
warehouse = Warehouse.create
|
68
|
-
widget = Widget.create name: 'Toy', color: 'green', warehouse: warehouse
|
69
|
-
assert_equal [widget], warehouse.widgets
|
70
|
-
widget.destroy
|
71
|
-
|
72
|
-
warehouse.reload
|
73
|
-
|
74
|
-
assert_equal [], warehouse.widgets
|
75
|
-
end
|
76
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
class Option
|
2
|
-
include TestModel
|
3
|
-
|
4
|
-
define_attributes [:name, :widget_id]
|
5
|
-
|
6
|
-
searches_many :options
|
7
|
-
|
8
|
-
self.elastic_index.mapping[:properties].update(
|
9
|
-
name: {
|
10
|
-
type: 'multi_field',
|
11
|
-
fields: {
|
12
|
-
name: {type: 'string', index: 'not_analyzed'},
|
13
|
-
analyzed: {type: 'string', index: 'analyzed'}
|
14
|
-
}
|
15
|
-
},
|
16
|
-
widget_id: {
|
17
|
-
type: 'string', index: 'not_analyzed'
|
18
|
-
}
|
19
|
-
)
|
20
|
-
|
21
|
-
def widget=(other)
|
22
|
-
self.widget_id = other.id
|
23
|
-
end
|
24
|
-
end
|