nobrainer 0.17.0 → 0.18.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/no_brainer/config.rb +42 -16
- data/lib/no_brainer/connection.rb +1 -0
- data/lib/no_brainer/connection_manager.rb +1 -1
- data/lib/no_brainer/criteria.rb +1 -1
- data/lib/no_brainer/criteria/aggregate.rb +8 -5
- data/lib/no_brainer/criteria/core.rb +8 -7
- data/lib/no_brainer/criteria/count.rb +1 -1
- data/lib/no_brainer/criteria/delete.rb +1 -1
- data/lib/no_brainer/criteria/extend.rb +31 -0
- data/lib/no_brainer/criteria/first.rb +1 -1
- data/lib/no_brainer/criteria/index.rb +1 -1
- data/lib/no_brainer/criteria/limit.rb +0 -1
- data/lib/no_brainer/criteria/order_by.rb +8 -9
- data/lib/no_brainer/criteria/pluck.rb +1 -1
- data/lib/no_brainer/criteria/raw.rb +1 -1
- data/lib/no_brainer/criteria/scope.rb +6 -6
- data/lib/no_brainer/criteria/update.rb +3 -3
- data/lib/no_brainer/criteria/where.rb +24 -32
- data/lib/no_brainer/document/association.rb +5 -5
- data/lib/no_brainer/document/association/belongs_to.rb +6 -6
- data/lib/no_brainer/document/association/core.rb +11 -11
- data/lib/no_brainer/document/association/eager_loader.rb +1 -1
- data/lib/no_brainer/document/association/has_many.rb +7 -7
- data/lib/no_brainer/document/association/has_many_through.rb +1 -1
- data/lib/no_brainer/document/association/has_one.rb +1 -1
- data/lib/no_brainer/document/atomic_ops.rb +26 -18
- data/lib/no_brainer/document/attributes.rb +9 -8
- data/lib/no_brainer/document/callbacks.rb +1 -1
- data/lib/no_brainer/document/core.rb +1 -1
- data/lib/no_brainer/document/criteria.rb +9 -2
- data/lib/no_brainer/document/dirty.rb +1 -3
- data/lib/no_brainer/document/index.rb +13 -79
- data/lib/no_brainer/document/index/index.rb +83 -0
- data/lib/no_brainer/document/index/meta_store.rb +31 -0
- data/lib/no_brainer/document/index/synchronizer.rb +68 -0
- data/lib/no_brainer/document/lazy_fetch.rb +5 -5
- data/lib/no_brainer/document/persistance.rb +27 -7
- data/lib/no_brainer/document/polymorphic.rb +1 -1
- data/lib/no_brainer/document/types.rb +6 -4
- data/lib/no_brainer/document/uniqueness.rb +3 -3
- data/lib/no_brainer/document/validation.rb +13 -4
- data/lib/no_brainer/fork.rb +1 -0
- data/lib/no_brainer/query_runner/database_on_demand.rb +6 -5
- data/lib/no_brainer/query_runner/logger.rb +10 -6
- data/lib/no_brainer/query_runner/missing_index.rb +5 -4
- data/lib/no_brainer/query_runner/reconnect.rb +20 -17
- data/lib/no_brainer/query_runner/run_options.rb +3 -0
- data/lib/no_brainer/query_runner/table_on_demand.rb +11 -8
- data/lib/no_brainer/railtie.rb +5 -5
- data/lib/no_brainer/railtie/database.rake +12 -12
- data/lib/no_brainer/rql.rb +9 -0
- data/lib/nobrainer.rb +5 -3
- metadata +8 -8
- data/lib/no_brainer/index_manager.rb +0 -9
@@ -28,11 +28,11 @@ module NoBrainer::Document::Association
|
|
28
28
|
raise "Cannot change the :through option" unless r.options[:through] == options[:through]
|
29
29
|
r.options.merge!(options)
|
30
30
|
else
|
31
|
-
|
32
|
-
|
33
|
-
r =
|
34
|
-
([self] + descendants).each do |
|
35
|
-
|
31
|
+
model_name = (options[:through] ? "#{association}_through" : association.to_s).camelize
|
32
|
+
metadata_model = NoBrainer::Document::Association.const_get(model_name).const_get(:Metadata)
|
33
|
+
r = metadata_model.new(self, target, options)
|
34
|
+
([self] + descendants).each do |model|
|
35
|
+
model.association_metadata[target] = r
|
36
36
|
end
|
37
37
|
end
|
38
38
|
r.hook
|
@@ -13,10 +13,10 @@ class NoBrainer::Document::Association::BelongsTo
|
|
13
13
|
|
14
14
|
def primary_key
|
15
15
|
# TODO test :primary_key
|
16
|
-
options[:primary_key].try(:to_sym) ||
|
16
|
+
options[:primary_key].try(:to_sym) || target_model.pk_name
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
19
|
+
def target_model
|
20
20
|
# TODO test :class_name
|
21
21
|
(options[:class_name] || target_name.to_s.camelize).constantize
|
22
22
|
end
|
@@ -29,9 +29,9 @@ class NoBrainer::Document::Association::BelongsTo
|
|
29
29
|
# This would have the effect of loading all the models because they
|
30
30
|
# are likely to be related to each other. So we don't know the type
|
31
31
|
# of the primary key of the target.
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
owner_model.field(foreign_key, :as => options[:foreign_key_as], :index => options[:index])
|
33
|
+
owner_model.validates(target_name, { :presence => true }) if options[:required]
|
34
|
+
owner_model.validates(target_name, options[:validates]) if options[:validates]
|
35
35
|
|
36
36
|
delegate("#{foreign_key}=", :assign_foreign_key, :call_super => true)
|
37
37
|
add_callback_for(:after_validation)
|
@@ -54,7 +54,7 @@ class NoBrainer::Document::Association::BelongsTo
|
|
54
54
|
return target if loaded?
|
55
55
|
|
56
56
|
if fk = owner.read_attribute(foreign_key)
|
57
|
-
preload(
|
57
|
+
preload(target_model.unscoped.where(primary_key => fk).first)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -4,25 +4,25 @@ module NoBrainer::Document::Association::Core
|
|
4
4
|
module Metadata
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
attr_accessor :
|
7
|
+
attr_accessor :owner_model, :target_name, :options
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
@
|
9
|
+
def initialize(owner_model, target_name, options={})
|
10
|
+
@owner_model = owner_model
|
11
11
|
@target_name = target_name
|
12
12
|
@options = options
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
@
|
15
|
+
def association_model
|
16
|
+
@association_model ||= self.class.name.deconstantize.constantize
|
17
17
|
end
|
18
18
|
|
19
19
|
def new(owner)
|
20
|
-
|
20
|
+
association_model.new(self, owner)
|
21
21
|
end
|
22
22
|
|
23
23
|
def delegate(method_name, target, options={})
|
24
24
|
metadata = self
|
25
|
-
|
25
|
+
owner_model.inject_in_layer :associations do
|
26
26
|
define_method(method_name) do |*args, &block|
|
27
27
|
super(*args, &block) if options[:call_super]
|
28
28
|
associations[metadata].__send__(target, *args, &block)
|
@@ -40,7 +40,7 @@ module NoBrainer::Document::Association::Core
|
|
40
40
|
instance_eval <<-RUBY, __FILE__, __LINE__+1
|
41
41
|
if !@added_#{what}
|
42
42
|
metadata = self
|
43
|
-
|
43
|
+
owner_model.#{what} { associations[metadata].#{what}_callback }
|
44
44
|
@added_#{what} = true
|
45
45
|
end
|
46
46
|
RUBY
|
@@ -49,15 +49,15 @@ module NoBrainer::Document::Association::Core
|
|
49
49
|
|
50
50
|
included { attr_accessor :metadata, :owner }
|
51
51
|
|
52
|
-
delegate :primary_key, :foreign_key, :target_name, :
|
52
|
+
delegate :primary_key, :foreign_key, :target_name, :target_model, :to => :metadata
|
53
53
|
|
54
54
|
def initialize(metadata, owner)
|
55
55
|
@metadata, @owner = metadata, owner
|
56
56
|
end
|
57
57
|
|
58
58
|
def assert_target_type(value)
|
59
|
-
unless value.is_a?(
|
60
|
-
options = { :attr_name => target_name, :value => value, :type =>
|
59
|
+
unless value.is_a?(target_model) || value.nil?
|
60
|
+
options = { :attr_name => target_name, :value => value, :type => target_model }
|
61
61
|
raise NoBrainer::Error::InvalidType.new(options)
|
62
62
|
end
|
63
63
|
end
|
@@ -7,7 +7,7 @@ class NoBrainer::Document::Association::EagerLoader
|
|
7
7
|
owner_key = instance_exec(&options[:owner_key])
|
8
8
|
target_key = instance_exec(&options[:target_key])
|
9
9
|
|
10
|
-
criteria =
|
10
|
+
criteria = target_model.all
|
11
11
|
criteria = criteria.merge(additional_criteria) if additional_criteria
|
12
12
|
criteria = criteria.unscoped if options[:unscoped]
|
13
13
|
|
@@ -8,15 +8,15 @@ class NoBrainer::Document::Association::HasMany
|
|
8
8
|
|
9
9
|
def foreign_key
|
10
10
|
# TODO test :foreign_key
|
11
|
-
options[:foreign_key].try(:to_sym) || :"#{
|
11
|
+
options[:foreign_key].try(:to_sym) || :"#{owner_model.name.underscore}_#{owner_model.pk_name}"
|
12
12
|
end
|
13
13
|
|
14
14
|
def primary_key
|
15
15
|
# TODO test :primary_key
|
16
|
-
options[:primary_key].try(:to_sym) ||
|
16
|
+
options[:primary_key].try(:to_sym) || target_model.pk_name
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
19
|
+
def target_model
|
20
20
|
# TODO test :class_name
|
21
21
|
(options[:class_name] || target_name.to_s.singularize.camelize).constantize
|
22
22
|
end
|
@@ -27,11 +27,11 @@ class NoBrainer::Document::Association::HasMany
|
|
27
27
|
# selector.
|
28
28
|
# XXX Without caching, this is going to get CPU intensive quickly, but
|
29
29
|
# caching is hard (rails console reload, etc.).
|
30
|
-
|
30
|
+
target_model.association_metadata.values.select do |assoc|
|
31
31
|
assoc.is_a?(NoBrainer::Document::Association::BelongsTo::Metadata) and
|
32
32
|
assoc.foreign_key == self.foreign_key and
|
33
33
|
assoc.primary_key == self.primary_key and
|
34
|
-
assoc.
|
34
|
+
assoc.target_model.root_class == owner_model.root_class
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -44,7 +44,7 @@ class NoBrainer::Document::Association::HasMany
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def target_criteria
|
47
|
-
@target_criteria ||=
|
47
|
+
@target_criteria ||= target_model.where(foreign_key => owner.pk_value)
|
48
48
|
.after_find(set_inverse_proc)
|
49
49
|
end
|
50
50
|
|
@@ -54,7 +54,7 @@ class NoBrainer::Document::Association::HasMany
|
|
54
54
|
|
55
55
|
def write(new_children)
|
56
56
|
raise "You can't assign #{target_name}. " +
|
57
|
-
"Instead, you must modify delete and create #{
|
57
|
+
"Instead, you must modify delete and create #{target_model} manually."
|
58
58
|
end
|
59
59
|
|
60
60
|
def loaded?
|
@@ -10,7 +10,7 @@ class NoBrainer::Document::Association::HasManyThrough
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def through_association
|
13
|
-
|
13
|
+
owner_model.association_metadata[through_association_name] or
|
14
14
|
raise "#{through_association_name} association not found"
|
15
15
|
end
|
16
16
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class NoBrainer::Document::Association::HasOne < NoBrainer::Document::Association::HasMany
|
2
2
|
class Metadata < NoBrainer::Document::Association::HasMany::Metadata
|
3
|
-
def
|
3
|
+
def target_model
|
4
4
|
(options[:class_name] || target_name.to_s.camelize).constantize
|
5
5
|
end
|
6
6
|
end
|
@@ -2,26 +2,26 @@ module NoBrainer::Document::AtomicOps
|
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
4
|
class PendingAtomic
|
5
|
-
def self._new(instance, field,
|
6
|
-
|
5
|
+
def self._new(instance, field, value, is_user_value, options={})
|
6
|
+
model = case value
|
7
7
|
when Array then PendingAtomicArray
|
8
8
|
when Set then PendingAtomicSet
|
9
9
|
else self
|
10
10
|
end
|
11
|
-
|
11
|
+
model.new(instance, field, value, is_user_value, options)
|
12
12
|
end
|
13
13
|
|
14
|
-
def initialize(instance, field,
|
14
|
+
def initialize(instance, field, value, is_user_value, options={})
|
15
15
|
@instance = instance
|
16
|
-
@field = field
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@options = options
|
16
|
+
@field = field.to_s
|
17
|
+
@value = value
|
18
|
+
@is_user_value = is_user_value
|
19
|
+
@options = options.dup
|
20
20
|
@ops = []
|
21
21
|
end
|
22
22
|
|
23
23
|
def write_access?
|
24
|
-
|
24
|
+
!!@options[:write_access]
|
25
25
|
end
|
26
26
|
|
27
27
|
def ensure_writeable!
|
@@ -43,7 +43,7 @@ module NoBrainer::Document::AtomicOps
|
|
43
43
|
|
44
44
|
def compile_rql_value(rql_doc)
|
45
45
|
field = @instance.class.lookup_field_alias(@field)
|
46
|
-
value = @
|
46
|
+
value = @is_user_value ? RethinkDB::RQL.new.expr(@value) : rql_doc[field]
|
47
47
|
@ops.each { |method_name, a, b| value = value.__send__(method_name, *a, &b) }
|
48
48
|
value
|
49
49
|
end
|
@@ -105,15 +105,15 @@ module NoBrainer::Document::AtomicOps
|
|
105
105
|
|
106
106
|
def clear_dirtiness(options={})
|
107
107
|
super
|
108
|
-
@
|
108
|
+
@_touched_attributes = Set.new
|
109
109
|
end
|
110
110
|
|
111
|
-
def
|
112
|
-
@
|
111
|
+
def _touch_attribute(name)
|
112
|
+
@_touched_attributes << name.to_s
|
113
113
|
end
|
114
114
|
|
115
|
-
def
|
116
|
-
@
|
115
|
+
def _is_attribute_touched?(name)
|
116
|
+
@_touched_attributes.include?(name.to_s)
|
117
117
|
end
|
118
118
|
|
119
119
|
def in_atomic?
|
@@ -146,7 +146,7 @@ module NoBrainer::Document::AtomicOps
|
|
146
146
|
|
147
147
|
case [in_atomic?, value.is_a?(PendingAtomic)]
|
148
148
|
when [true, true] then value
|
149
|
-
when [true, false] then PendingAtomic._new(self, name
|
149
|
+
when [true, false] then PendingAtomic._new(self, name, value, _is_attribute_touched?(name))
|
150
150
|
when [false, true] then raise NoBrainer::Error::CannotReadAtomic.new(self, name, value)
|
151
151
|
when [false, false] then value
|
152
152
|
end
|
@@ -159,7 +159,7 @@ module NoBrainer::Document::AtomicOps
|
|
159
159
|
when [true, true] then super
|
160
160
|
when [true, false] then raise NoBrainer::Error::AtomicBlock.new('Avoid the use of atomic blocks for non atomic operations')
|
161
161
|
when [false, true] then raise NoBrainer::Error::AtomicBlock.new('Use atomic blocks for atomic operations')
|
162
|
-
when [false, false] then super.tap {
|
162
|
+
when [false, false] then super.tap { _touch_attribute(name) }
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
@@ -169,8 +169,16 @@ module NoBrainer::Document::AtomicOps
|
|
169
169
|
end
|
170
170
|
|
171
171
|
def save?(options={})
|
172
|
+
# TODO allow reload => true as an option to save+reload in a single op.
|
172
173
|
raise NoBrainer::Error::AtomicBlock.new('You may persist documents only outside of queue_atomic blocks') if in_atomic?
|
173
|
-
super
|
174
|
+
super.tap do |saved|
|
175
|
+
if saved
|
176
|
+
@_attributes.each do |attr, value|
|
177
|
+
next unless value.is_a?(PendingAtomic)
|
178
|
+
@_attributes[attr] = value.class.new(self, attr, nil, false)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
174
182
|
end
|
175
183
|
|
176
184
|
def read_attribute_for_change(attr)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module NoBrainer::Document::Attributes
|
2
|
-
VALID_FIELD_OPTIONS = [:index, :default, :type, :real_type,
|
3
|
-
:
|
2
|
+
VALID_FIELD_OPTIONS = [:index, :default, :type, :real_type,
|
3
|
+
:validates, :required, :unique, :uniq, :format, :in,
|
4
|
+
:readonly, :primary_key, :as, :lazy_fetch]
|
4
5
|
RESERVED_FIELD_NAMES = [:index, :default, :and, :or, :selector, :associations, :pk_value] \
|
5
6
|
+ NoBrainer::DecoratedSymbol::MODIFIERS.keys
|
6
7
|
extend ActiveSupport::Concern
|
@@ -99,7 +100,7 @@ module NoBrainer::Document::Attributes
|
|
99
100
|
module ClassMethods
|
100
101
|
def new_from_db(attrs, options={})
|
101
102
|
options = options.reverse_merge(:pristine => true, :from_db => true)
|
102
|
-
|
103
|
+
model_from_attrs(attrs).new(attrs, options) if attrs
|
103
104
|
end
|
104
105
|
|
105
106
|
def inherited(subclass)
|
@@ -124,9 +125,9 @@ module NoBrainer::Document::Attributes
|
|
124
125
|
raise "Cannot use a reserved field attr: #{attr}"
|
125
126
|
end
|
126
127
|
|
127
|
-
([self] + descendants).each do |
|
128
|
-
|
129
|
-
|
128
|
+
([self] + descendants).each do |model|
|
129
|
+
model.fields[attr] ||= {}
|
130
|
+
model.fields[attr].deep_merge!(options)
|
130
131
|
end
|
131
132
|
|
132
133
|
_field(attr, self.fields[attr])
|
@@ -144,8 +145,8 @@ module NoBrainer::Document::Attributes
|
|
144
145
|
|
145
146
|
_remove_field(attr, options)
|
146
147
|
|
147
|
-
([self] + descendants).each do |
|
148
|
-
|
148
|
+
([self] + descendants).each do |model|
|
149
|
+
model.fields.delete(attr)
|
149
150
|
end
|
150
151
|
end
|
151
152
|
|
@@ -5,7 +5,10 @@ module NoBrainer::Document::Criteria
|
|
5
5
|
self.class.selector_for(pk_value)
|
6
6
|
end
|
7
7
|
|
8
|
-
included
|
8
|
+
included do
|
9
|
+
cattr_accessor :default_scope_proc, :instance_accessor => false
|
10
|
+
cattr_accessor :perf_warnings_disabled, :instance_accessor => false
|
11
|
+
end
|
9
12
|
|
10
13
|
module ClassMethods
|
11
14
|
delegate :to_rql, # Core
|
@@ -27,7 +30,7 @@ module NoBrainer::Document::Criteria
|
|
27
30
|
:to => :all
|
28
31
|
|
29
32
|
def all
|
30
|
-
NoBrainer::Criteria.new(:
|
33
|
+
NoBrainer::Criteria.new(:model => self)
|
31
34
|
end
|
32
35
|
|
33
36
|
def scope(name, criteria=nil, &block)
|
@@ -59,5 +62,9 @@ module NoBrainer::Document::Criteria
|
|
59
62
|
raise NoBrainer::Error::DocumentNotFound, "#{self} #{pk_name}: #{pk} not found" unless doc
|
60
63
|
end
|
61
64
|
end
|
65
|
+
|
66
|
+
def disable_perf_warnings
|
67
|
+
self.perf_warnings_disabled = true
|
68
|
+
end
|
62
69
|
end
|
63
70
|
end
|
@@ -17,9 +17,7 @@ module NoBrainer::Document::Dirty
|
|
17
17
|
def clear_dirtiness(options={})
|
18
18
|
if options[:keep_ivars] && options[:missing_attributes].try(:[], :pluck)
|
19
19
|
attrs = options[:missing_attributes][:pluck].keys
|
20
|
-
@_old_attributes = @_old_attributes.reject { |k,v| attrs.include?(k) }
|
21
|
-
else
|
22
|
-
@_old_attributes = {}.with_indifferent_access
|
20
|
+
@_old_attributes = @_old_attributes.reject { |k,v| attrs.include?(k) } else @_old_attributes = {}.with_indifferent_access
|
23
21
|
end
|
24
22
|
|
25
23
|
@_old_attributes_keys = @_attributes.keys # to track undefined -> nil changes
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module NoBrainer::Document::Index
|
2
|
-
VALID_INDEX_OPTIONS = [:multi, :as]
|
2
|
+
VALID_INDEX_OPTIONS = [:external, :geo, :multi, :as]
|
3
3
|
extend ActiveSupport::Concern
|
4
|
+
extend NoBrainer::Autoload
|
5
|
+
|
6
|
+
autoload :Index, :Synchronizer, :MetaStore
|
4
7
|
|
5
8
|
included do
|
6
9
|
cattr_accessor :indexes, :instance_accessor => false
|
@@ -16,9 +19,9 @@ module NoBrainer::Document::Index
|
|
16
19
|
raise "Too many arguments: #{args}" if args.size > 1
|
17
20
|
|
18
21
|
kind, what = case args.first
|
19
|
-
when nil
|
20
|
-
when Array
|
21
|
-
when Proc
|
22
|
+
when nil then [:single, name.to_sym]
|
23
|
+
when Array then [:compound, args.first.map(&:to_sym)]
|
24
|
+
when Proc then [:proc, args.first]
|
22
25
|
else raise "Index argument must be a lambda or a list of fields"
|
23
26
|
end
|
24
27
|
|
@@ -35,7 +38,8 @@ module NoBrainer::Document::Index
|
|
35
38
|
as ||= name
|
36
39
|
as = as.to_sym
|
37
40
|
|
38
|
-
indexes[name] =
|
41
|
+
indexes[name] = NoBrainer::Document::Index::Index.new(self.root_class, name, as,
|
42
|
+
kind, what, options[:external], options[:geo], options[:multi], nil)
|
39
43
|
end
|
40
44
|
|
41
45
|
def remove_index(name)
|
@@ -46,12 +50,8 @@ module NoBrainer::Document::Index
|
|
46
50
|
!!indexes[name.to_sym]
|
47
51
|
end
|
48
52
|
|
49
|
-
def lookup_index_alias(attr)
|
50
|
-
indexes[attr.to_sym].try(:[], :as) || attr
|
51
|
-
end
|
52
|
-
|
53
53
|
def _field(attr, options={})
|
54
|
-
if has_index?(attr) && indexes[attr]
|
54
|
+
if has_index?(attr) && indexes[attr].kind != :single
|
55
55
|
raise "Cannot reuse index attr #{attr}"
|
56
56
|
end
|
57
57
|
|
@@ -68,78 +68,12 @@ module NoBrainer::Document::Index
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def _remove_field(attr, options={})
|
71
|
-
super
|
72
71
|
remove_index(attr) if fields[attr][:index]
|
72
|
+
super
|
73
73
|
end
|
74
74
|
|
75
|
-
def
|
76
|
-
|
77
|
-
index_args = self.indexes[index_name]
|
78
|
-
aliased_name = index_args[:as]
|
79
|
-
|
80
|
-
index_proc = case index_args[:kind]
|
81
|
-
when :single then ->(doc) { doc[lookup_field_alias(index_name)] }
|
82
|
-
when :compound then ->(doc) { index_args[:what].map { |field| doc[lookup_field_alias(field)] } }
|
83
|
-
when :proc then index_args[:what]
|
84
|
-
end
|
85
|
-
|
86
|
-
NoBrainer.run(self.rql_table.index_create(aliased_name, index_args[:options], &index_proc))
|
87
|
-
wait_for_index(index_name) unless options[:wait] == false
|
88
|
-
|
89
|
-
readable_index_name = "index #{self}.#{index_name}"
|
90
|
-
readable_index_name += " as #{aliased_name}" unless index_name == aliased_name
|
91
|
-
|
92
|
-
STDERR.puts "Created index #{readable_index_name}" if options[:verbose]
|
93
|
-
end
|
94
|
-
|
95
|
-
def perform_drop_index(index_name, options={})
|
96
|
-
index_name = index_name.to_sym
|
97
|
-
aliased_name = self.indexes[index_name].try(:[], :as) || index_name
|
98
|
-
|
99
|
-
readable_index_name = "index #{self}.#{index_name}"
|
100
|
-
readable_index_name += " as #{aliased_name}" unless index_name == aliased_name
|
101
|
-
|
102
|
-
if STDIN.stat.chardev? && STDERR.stat.chardev? && !options[:no_confirmation]
|
103
|
-
STDERR.print "Confirm dropping #{readable_index_name} [yna]: "
|
104
|
-
case STDIN.gets.strip.chomp
|
105
|
-
when 'y' then
|
106
|
-
when 'n' then return
|
107
|
-
when 'a' then options[:no_confirmation] = true
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
NoBrainer.run(self.rql_table.index_drop(aliased_name))
|
112
|
-
STDERR.puts "Dropped #{readable_index_name}" if options[:verbose]
|
113
|
-
end
|
114
|
-
|
115
|
-
def get_index_alias_reverse_map
|
116
|
-
Hash[self.indexes.map { |k,v| [v[:as], k] }].tap do |mapping|
|
117
|
-
raise "Detected clashing index aliases" if mapping.count != self.indexes.count
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def perform_update_indexes(options={})
|
122
|
-
alias_mapping = self.get_index_alias_reverse_map
|
123
|
-
current_indexes = NoBrainer.run(self.rql_table.index_list).map do |index|
|
124
|
-
alias_mapping[index.to_sym] || index.to_sym
|
125
|
-
end
|
126
|
-
wanted_indexes = self.indexes.keys - [self.pk_name]
|
127
|
-
|
128
|
-
# FIXME removing an aliased field is not going to work well with this method
|
129
|
-
|
130
|
-
(current_indexes - wanted_indexes).each do |index_name|
|
131
|
-
perform_drop_index(index_name, options)
|
132
|
-
end
|
133
|
-
|
134
|
-
(wanted_indexes - current_indexes).each do |index_name|
|
135
|
-
perform_create_index(index_name, options)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
alias_method :update_indexes, :perform_update_indexes
|
139
|
-
|
140
|
-
def wait_for_index(index_name=nil, options={})
|
141
|
-
args = [index_name].compact
|
142
|
-
NoBrainer.run(self.rql_table.index_wait(*args))
|
75
|
+
def lookup_index_alias(attr)
|
76
|
+
indexes[attr.to_sym].try(:aliased_name) || attr
|
143
77
|
end
|
144
78
|
end
|
145
79
|
end
|