nobrainer 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
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