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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/lib/no_brainer/config.rb +42 -16
  3. data/lib/no_brainer/connection.rb +1 -0
  4. data/lib/no_brainer/connection_manager.rb +1 -1
  5. data/lib/no_brainer/criteria.rb +1 -1
  6. data/lib/no_brainer/criteria/aggregate.rb +8 -5
  7. data/lib/no_brainer/criteria/core.rb +8 -7
  8. data/lib/no_brainer/criteria/count.rb +1 -1
  9. data/lib/no_brainer/criteria/delete.rb +1 -1
  10. data/lib/no_brainer/criteria/extend.rb +31 -0
  11. data/lib/no_brainer/criteria/first.rb +1 -1
  12. data/lib/no_brainer/criteria/index.rb +1 -1
  13. data/lib/no_brainer/criteria/limit.rb +0 -1
  14. data/lib/no_brainer/criteria/order_by.rb +8 -9
  15. data/lib/no_brainer/criteria/pluck.rb +1 -1
  16. data/lib/no_brainer/criteria/raw.rb +1 -1
  17. data/lib/no_brainer/criteria/scope.rb +6 -6
  18. data/lib/no_brainer/criteria/update.rb +3 -3
  19. data/lib/no_brainer/criteria/where.rb +24 -32
  20. data/lib/no_brainer/document/association.rb +5 -5
  21. data/lib/no_brainer/document/association/belongs_to.rb +6 -6
  22. data/lib/no_brainer/document/association/core.rb +11 -11
  23. data/lib/no_brainer/document/association/eager_loader.rb +1 -1
  24. data/lib/no_brainer/document/association/has_many.rb +7 -7
  25. data/lib/no_brainer/document/association/has_many_through.rb +1 -1
  26. data/lib/no_brainer/document/association/has_one.rb +1 -1
  27. data/lib/no_brainer/document/atomic_ops.rb +26 -18
  28. data/lib/no_brainer/document/attributes.rb +9 -8
  29. data/lib/no_brainer/document/callbacks.rb +1 -1
  30. data/lib/no_brainer/document/core.rb +1 -1
  31. data/lib/no_brainer/document/criteria.rb +9 -2
  32. data/lib/no_brainer/document/dirty.rb +1 -3
  33. data/lib/no_brainer/document/index.rb +13 -79
  34. data/lib/no_brainer/document/index/index.rb +83 -0
  35. data/lib/no_brainer/document/index/meta_store.rb +31 -0
  36. data/lib/no_brainer/document/index/synchronizer.rb +68 -0
  37. data/lib/no_brainer/document/lazy_fetch.rb +5 -5
  38. data/lib/no_brainer/document/persistance.rb +27 -7
  39. data/lib/no_brainer/document/polymorphic.rb +1 -1
  40. data/lib/no_brainer/document/types.rb +6 -4
  41. data/lib/no_brainer/document/uniqueness.rb +3 -3
  42. data/lib/no_brainer/document/validation.rb +13 -4
  43. data/lib/no_brainer/fork.rb +1 -0
  44. data/lib/no_brainer/query_runner/database_on_demand.rb +6 -5
  45. data/lib/no_brainer/query_runner/logger.rb +10 -6
  46. data/lib/no_brainer/query_runner/missing_index.rb +5 -4
  47. data/lib/no_brainer/query_runner/reconnect.rb +20 -17
  48. data/lib/no_brainer/query_runner/run_options.rb +3 -0
  49. data/lib/no_brainer/query_runner/table_on_demand.rb +11 -8
  50. data/lib/no_brainer/railtie.rb +5 -5
  51. data/lib/no_brainer/railtie/database.rake +12 -12
  52. data/lib/no_brainer/rql.rb +9 -0
  53. data/lib/nobrainer.rb +5 -3
  54. metadata +8 -8
  55. 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
- klass_name = (options[:through] ? "#{association}_through" : association.to_s).camelize
32
- metadata_klass = NoBrainer::Document::Association.const_get(klass_name).const_get(:Metadata)
33
- r = metadata_klass.new(self, target, options)
34
- ([self] + descendants).each do |klass|
35
- klass.association_metadata[target] = r
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) || target_klass.pk_name
16
+ options[:primary_key].try(:to_sym) || target_model.pk_name
17
17
  end
18
18
 
19
- def target_klass
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
- owner_klass.field(foreign_key, :as => options[:foreign_key_as], :index => options[:index])
33
- owner_klass.validates(target_name, { :presence => true }) if options[:required]
34
- owner_klass.validates(target_name, options[:validates]) if options[:validates]
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(target_klass.unscoped.where(primary_key => fk).first)
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 :owner_klass, :target_name, :options
7
+ attr_accessor :owner_model, :target_name, :options
8
8
 
9
- def initialize(owner_klass, target_name, options={})
10
- @owner_klass = owner_klass
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 association_klass
16
- @association_klass ||= self.class.name.deconstantize.constantize
15
+ def association_model
16
+ @association_model ||= self.class.name.deconstantize.constantize
17
17
  end
18
18
 
19
19
  def new(owner)
20
- association_klass.new(self, owner)
20
+ association_model.new(self, owner)
21
21
  end
22
22
 
23
23
  def delegate(method_name, target, options={})
24
24
  metadata = self
25
- owner_klass.inject_in_layer :associations do
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
- owner_klass.#{what} { associations[metadata].#{what}_callback }
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, :target_klass, :to => :metadata
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?(target_klass) || value.nil?
60
- options = { :attr_name => target_name, :value => value, :type => target_klass }
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 = target_klass.all
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) || :"#{owner_klass.name.underscore}_#{owner_klass.pk_name}"
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) || target_klass.pk_name
16
+ options[:primary_key].try(:to_sym) || target_model.pk_name
17
17
  end
18
18
 
19
- def target_klass
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
- target_klass.association_metadata.values.select do |assoc|
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.target_klass.root_class == owner_klass.root_class
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 ||= target_klass.where(foreign_key => owner.pk_value)
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 #{target_klass} manually."
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
- owner_klass.association_metadata[through_association_name] or
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 target_klass
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, user_value, options={})
6
- klass = case user_value
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
- klass.new(instance, field, user_value, options)
11
+ model.new(instance, field, value, is_user_value, options)
12
12
  end
13
13
 
14
- def initialize(instance, field, user_value, options={})
14
+ def initialize(instance, field, value, is_user_value, options={})
15
15
  @instance = instance
16
- @field = field
17
- @user_value = user_value
18
- @value_tainted = instance._is_attribute_tainted?(field)
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
- @options[:write_access] == true
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 = @value_tainted ? RethinkDB::RQL.new.expr(@user_value) : rql_doc[field]
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
- @_tainted_attributes = Set.new
108
+ @_touched_attributes = Set.new
109
109
  end
110
110
 
111
- def _taint_attribute(name)
112
- @_tainted_attributes << name
111
+ def _touch_attribute(name)
112
+ @_touched_attributes << name.to_s
113
113
  end
114
114
 
115
- def _is_attribute_tainted?(name)
116
- @_tainted_attributes.include?(name)
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.to_s, value, :write_access => false)
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 { _taint_attribute(name.to_s) }
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, :validates, :required, :unique,
3
- :in, :readonly, :primary_key, :as, :lazy_fetch]
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
- klass_from_attrs(attrs).new(attrs, options) if attrs
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 |klass|
128
- klass.fields[attr] ||= {}
129
- klass.fields[attr].deep_merge!(options)
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 |klass|
148
- klass.fields.delete(attr)
148
+ ([self] + descendants).each do |model|
149
+ model.fields.delete(attr)
149
150
  end
150
151
  end
151
152
 
@@ -20,7 +20,7 @@ module NoBrainer::Document::Callbacks
20
20
  run_callbacks(:update) { super }
21
21
  end
22
22
 
23
- def save?(*args, &block)
23
+ def _save?(*args, &block)
24
24
  run_callbacks(:save) { super }
25
25
  end
26
26
 
@@ -22,6 +22,6 @@ module NoBrainer::Document::Core
22
22
  extend ActiveModel::Naming
23
23
  extend ActiveModel::Translation
24
24
 
25
- NoBrainer::Document::Core._all << self
25
+ NoBrainer::Document::Core._all << self unless self.name =~ /^NoBrainer::/
26
26
  end
27
27
  end
@@ -5,7 +5,10 @@ module NoBrainer::Document::Criteria
5
5
  self.class.selector_for(pk_value)
6
6
  end
7
7
 
8
- included { cattr_accessor :default_scope_proc, :instance_accessor => false }
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(:klass => self)
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 then [:single, name.to_sym]
20
- when Array then [:compound, args.first.map(&:to_sym)]
21
- when Proc then [:proc, args.first]
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] = {:kind => kind, :what => what, :as => as, :options => options}
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][:kind] != :single
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 perform_create_index(index_name, options={})
76
- index_name = index_name.to_sym
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