nobrainer 0.16.0 → 0.18.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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/no_brainer/config.rb +53 -28
  3. data/lib/no_brainer/connection.rb +1 -0
  4. data/lib/no_brainer/connection_manager.rb +60 -0
  5. data/lib/no_brainer/criteria/after_find.rb +3 -11
  6. data/lib/no_brainer/criteria/aggregate.rb +8 -5
  7. data/lib/no_brainer/criteria/cache.rb +7 -7
  8. data/lib/no_brainer/criteria/core.rb +56 -16
  9. data/lib/no_brainer/criteria/count.rb +1 -1
  10. data/lib/no_brainer/criteria/delete.rb +1 -1
  11. data/lib/no_brainer/criteria/extend.rb +19 -0
  12. data/lib/no_brainer/criteria/first.rb +1 -1
  13. data/lib/no_brainer/criteria/index.rb +7 -13
  14. data/lib/no_brainer/criteria/limit.rb +5 -13
  15. data/lib/no_brainer/criteria/order_by.rb +22 -41
  16. data/lib/no_brainer/criteria/pluck.rb +17 -23
  17. data/lib/no_brainer/criteria/preload.rb +9 -15
  18. data/lib/no_brainer/criteria/raw.rb +5 -11
  19. data/lib/no_brainer/criteria/scope.rb +9 -15
  20. data/lib/no_brainer/criteria/update.rb +3 -3
  21. data/lib/no_brainer/criteria/where.rb +33 -56
  22. data/lib/no_brainer/criteria.rb +1 -1
  23. data/lib/no_brainer/document/aliases.rb +1 -1
  24. data/lib/no_brainer/document/association/belongs_to.rb +6 -6
  25. data/lib/no_brainer/document/association/core.rb +11 -11
  26. data/lib/no_brainer/document/association/eager_loader.rb +4 -3
  27. data/lib/no_brainer/document/association/has_many.rb +7 -7
  28. data/lib/no_brainer/document/association/has_many_through.rb +1 -1
  29. data/lib/no_brainer/document/association/has_one.rb +1 -1
  30. data/lib/no_brainer/document/association.rb +5 -5
  31. data/lib/no_brainer/document/atomic_ops.rb +213 -0
  32. data/lib/no_brainer/document/attributes.rb +19 -10
  33. data/lib/no_brainer/document/callbacks.rb +1 -1
  34. data/lib/no_brainer/document/core.rb +1 -1
  35. data/lib/no_brainer/document/criteria.rb +9 -2
  36. data/lib/no_brainer/document/dirty.rb +22 -22
  37. data/lib/no_brainer/document/dynamic_attributes.rb +2 -14
  38. data/lib/no_brainer/document/id.rb +1 -0
  39. data/lib/no_brainer/document/index/index.rb +83 -0
  40. data/lib/no_brainer/document/index/meta_store.rb +31 -0
  41. data/lib/no_brainer/document/index/synchronizer.rb +68 -0
  42. data/lib/no_brainer/document/index.rb +13 -72
  43. data/lib/no_brainer/document/lazy_fetch.rb +5 -5
  44. data/lib/no_brainer/document/missing_attributes.rb +6 -23
  45. data/lib/no_brainer/document/persistance.rb +38 -21
  46. data/lib/no_brainer/document/polymorphic.rb +1 -1
  47. data/lib/no_brainer/document/types/set.rb +23 -0
  48. data/lib/no_brainer/document/types.rb +8 -6
  49. data/lib/no_brainer/document/uniqueness.rb +3 -3
  50. data/lib/no_brainer/document/validation.rb +13 -4
  51. data/lib/no_brainer/document.rb +1 -1
  52. data/lib/no_brainer/error.rb +14 -0
  53. data/lib/no_brainer/fork.rb +1 -0
  54. data/lib/no_brainer/query_runner/connection_lock.rb +5 -1
  55. data/lib/no_brainer/query_runner/database_on_demand.rb +6 -5
  56. data/lib/no_brainer/query_runner/logger.rb +10 -6
  57. data/lib/no_brainer/query_runner/missing_index.rb +5 -4
  58. data/lib/no_brainer/query_runner/reconnect.rb +20 -17
  59. data/lib/no_brainer/query_runner/run_options.rb +3 -0
  60. data/lib/no_brainer/query_runner/table_on_demand.rb +11 -8
  61. data/lib/no_brainer/railtie/database.rake +12 -12
  62. data/lib/no_brainer/railtie.rb +5 -5
  63. data/lib/no_brainer/rql.rb +9 -0
  64. data/lib/nobrainer.rb +9 -23
  65. metadata +10 -4
  66. data/lib/no_brainer/index_manager.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fe36d41b56c9780a4d16f3085d31de0361d34cae
4
- data.tar.gz: 9f89b0da1f34d65c8861345307adc79f93a5593d
3
+ metadata.gz: 1d6a500e008eff372e800b011e917d121c07e00a
4
+ data.tar.gz: e43be89ac4963422c26559727c9a68011ee25f8a
5
5
  SHA512:
6
- metadata.gz: 43e0cf6f767028a46068635713cb9c1d639a8e03de6503493a6af05179977dfe1ae01b5c6a49d93ec0f2e4012a24b0386b6f66d31c7dd274ec05f5f69b252ba3
7
- data.tar.gz: e728763fc6095d493db2ed93a9141f72d7cfc927f35300993f0ca6272996a5bac120f6f9cbfc9a985d80329a78da88ec5d827d5af31ccce93c833704b3a17f0b
6
+ metadata.gz: 56015e819aba3537ab60ea5f039d4b391ec803cc61b5bf246e44da642787e62606e9c02339b17f05976d5428ec3e4fa0e335cb51694b840bd2ba7821b6d66b20
7
+ data.tar.gz: d4b78185fed14f5baa28165462a4088096da640d93c0dfb3f20c851e968deceb1f48f13602850075a7eea2408fa23e52c2694d140bea1c9a937d7d49d5084f53
@@ -1,60 +1,81 @@
1
1
  require 'logger'
2
2
 
3
3
  module NoBrainer::Config
4
+ SETTINGS = {
5
+ :app_name => { :default => ->{ default_app_name } },
6
+ :environment => { :default => ->{ default_environment } },
7
+ :rethinkdb_url => { :default => ->{ default_rethinkdb_url } },
8
+ :logger => { :default => ->{ default_logger } },
9
+ :warn_on_active_record => { :default => ->{ true }, :valid_values => [true, false] },
10
+ :auto_create_databases => { :default => ->{ true }, :valid_values => [true, false] },
11
+ :auto_create_tables => { :default => ->{ true }, :valid_values => [true, false] },
12
+ :max_retries_on_connection_failure => { :default => ->{ default_max_retries_on_connection_failure } },
13
+ :durability => { :default => ->{ default_durability }, :valid_values => [:hard, :soft] },
14
+ :user_timezone => { :default => ->{ :local }, :valid_values => [:unchanged, :utc, :local] },
15
+ :db_timezone => { :default => ->{ :utc }, :valid_values => [:unchanged, :utc, :local] },
16
+ :colorize_logger => { :default => ->{ true }, :valid_values => [true, false] },
17
+ :distributed_lock_class => { :default => ->{ nil } },
18
+ :per_thread_connection => { :default => ->{ false }, :valid_values => [true, false] },
19
+ }
20
+
4
21
  class << self
5
- mattr_accessor :rethinkdb_url, :logger, :warn_on_active_record,
6
- :auto_create_databases, :auto_create_tables,
7
- :max_reconnection_tries, :durability,
8
- :user_timezone, :db_timezone, :colorize_logger,
9
- :distributed_lock_class
22
+ attr_accessor(*SETTINGS.keys)
23
+
24
+ def max_reconnection_tries=(value)
25
+ STDERR.puts "[NoBrainer] config.max_reconnection_tries is deprecated and will be removed"
26
+ STDERR.puts "[NoBrainer] use config.max_retries_on_connection_failure instead."
27
+ self.max_retries_on_connection_failure = value
28
+ end
10
29
 
11
30
  def apply_defaults
12
- self.rethinkdb_url = default_rethinkdb_url
13
- self.logger = default_logger
14
- self.warn_on_active_record = true
15
- self.auto_create_databases = true
16
- self.auto_create_tables = true
17
- self.max_reconnection_tries = 10
18
- self.durability = default_durability
19
- self.user_timezone = :local
20
- self.db_timezone = :utc
21
- self.colorize_logger = true
22
- self.distributed_lock_class = nil
31
+ @applied_defaults_for = SETTINGS.keys.reject { |k| instance_variable_defined?("@#{k}") }
32
+ @applied_defaults_for.each { |k| __send__("#{k}=", SETTINGS[k][:default].call) }
33
+ end
34
+
35
+ def assert_valid_options!
36
+ SETTINGS.each { |k,v| assert_array_in(k, v[:valid_values]) if v[:valid_values] }
23
37
  end
24
38
 
25
39
  def reset!
26
- @configured = false
27
- apply_defaults
40
+ instance_variables.each { |ivar| remove_instance_variable(ivar) }
28
41
  end
29
42
 
30
43
  def configure(&block)
31
- apply_defaults unless configured?
44
+ @applied_defaults_for.to_a.each { |k| remove_instance_variable("@#{k}") }
32
45
  block.call(self) if block
46
+ apply_defaults
33
47
  assert_valid_options!
34
48
  @configured = true
35
49
 
36
- NoBrainer.disconnect_if_url_changed
50
+ NoBrainer::ConnectionManager.disconnect_if_url_changed
37
51
  end
38
52
 
39
53
  def configured?
40
54
  !!@configured
41
55
  end
42
56
 
43
- def assert_valid_options!
44
- assert_array_in :durability, [:hard, :soft]
45
- assert_array_in :user_timezone, [:unchanged, :utc, :local]
46
- assert_array_in :db_timezone, [:unchanged, :utc, :local]
47
- end
48
-
49
57
  def assert_array_in(name, values)
50
58
  unless __send__(name).in?(values)
51
59
  raise ArgumentError.new("Unknown configuration for #{name}: #{__send__(name)}. Valid values are: #{values.inspect}")
52
60
  end
53
61
  end
54
62
 
63
+ def dev_mode?
64
+ self.environment.to_s.in? %w(development test)
65
+ end
66
+
67
+ def default_app_name
68
+ defined?(Rails) ? Rails.application.class.parent_name.underscore.presence : nil rescue nil
69
+ end
70
+
71
+ def default_environment
72
+ return Rails.env if defined?(Rails.env)
73
+ ENV['RUBY_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || :production
74
+ end
75
+
55
76
  def default_rethinkdb_url
56
77
  db = ENV['RETHINKDB_DB'] || ENV['RDB_DB']
57
- db ||= "#{Rails.application.class.parent_name.underscore}_#{Rails.env}" rescue nil
78
+ db ||= "#{self.app_name}_#{self.environment}" if self.app_name && self.environment
58
79
  host = ENV['RETHINKDB_HOST'] || ENV['RDB_HOST'] || 'localhost'
59
80
  port = ENV['RETHINKDB_PORT'] || ENV['RDB_PORT']
60
81
  auth = ENV['RETHINKDB_AUTH'] || ENV['RDB_AUTH']
@@ -68,7 +89,11 @@ module NoBrainer::Config
68
89
  end
69
90
 
70
91
  def default_durability
71
- (defined?(Rails.env) && (Rails.env.test? || Rails.env.development?)) ? :soft : :hard
92
+ dev_mode? ? :soft : :hard
93
+ end
94
+
95
+ def default_max_retries_on_connection_failure
96
+ dev_mode? ? 1 : 15
72
97
  end
73
98
  end
74
99
  end
@@ -52,6 +52,7 @@ class NoBrainer::Connection
52
52
  # database (drop)
53
53
  def purge!(options={})
54
54
  table_list.each do |table_name|
55
+ next if table_name =~ /^nobrainer_/
55
56
  NoBrainer.run { |r| r.table(table_name).delete }
56
57
  end
57
58
  true
@@ -0,0 +1,60 @@
1
+ module NoBrainer::ConnectionManager
2
+ extend self
3
+
4
+ @lock = Mutex.new
5
+
6
+ def synchronize(&block)
7
+ if NoBrainer::Config.per_thread_connection
8
+ block.call
9
+ else
10
+ @lock.synchronize { block.call }
11
+ end
12
+ end
13
+
14
+ def get_new_connection
15
+ url = NoBrainer::Config.rethinkdb_url
16
+ raise "Please specify a database connection to RethinkDB" unless url
17
+ NoBrainer::Connection.new(url)
18
+ end
19
+
20
+ def current_connection
21
+ if NoBrainer::Config.per_thread_connection
22
+ Thread.current[:nobrainer_connection]
23
+ else
24
+ @connection
25
+ end
26
+ end
27
+
28
+ def current_connection=(value)
29
+ if NoBrainer::Config.per_thread_connection
30
+ Thread.current[:nobrainer_connection] = value
31
+ else
32
+ @connection = value
33
+ end
34
+ end
35
+
36
+ def connection
37
+ c = self.current_connection
38
+ return c if c
39
+
40
+ synchronize do
41
+ self.current_connection ||= get_new_connection
42
+ end
43
+ end
44
+
45
+ def _disconnect
46
+ self.current_connection.try(:close, :noreply_wait => false) rescue nil
47
+ self.current_connection = nil
48
+ end
49
+
50
+ def disconnect
51
+ synchronize { _disconnect }
52
+ end
53
+
54
+ def disconnect_if_url_changed
55
+ synchronize do
56
+ c = current_connection
57
+ _disconnect if c && c.uri != NoBrainer::Config.rethinkdb_url
58
+ end
59
+ end
60
+ end
@@ -1,23 +1,15 @@
1
1
  module NoBrainer::Criteria::AfterFind
2
2
  extend ActiveSupport::Concern
3
3
 
4
- included { attr_accessor :_after_find }
4
+ included { criteria_option :after_find, :merge_with => :append_array }
5
5
 
6
6
  def after_find(b=nil, &block)
7
- chain { |criteria| criteria._after_find = [b || block] }
8
- end
9
-
10
- def merge!(criteria, options={})
11
- super
12
- if criteria._after_find.present?
13
- self._after_find = (self._after_find || []) + criteria._after_find
14
- end
15
- self
7
+ chain(:after_find => [b, block].compact)
16
8
  end
17
9
 
18
10
  def _instantiate_doc(attrs)
19
11
  super.tap do |doc|
20
- self._after_find.to_a.each { |block| block.call(doc) }
12
+ @options[:after_find].to_a.each { |block| block.call(doc) }
21
13
  doc.run_callbacks(:find) if doc.is_a?(NoBrainer::Document)
22
14
  end
23
15
  end
@@ -2,24 +2,27 @@ module NoBrainer::Criteria::Aggregate
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  def min(*a, &b)
5
- instantiate_doc NoBrainer.run { aggregate_rql(:min, *a, &b) }
5
+ instantiate_doc run { aggregate_rql(:min, *a, &b) }
6
6
  end
7
7
 
8
8
  def max(*a, &b)
9
- instantiate_doc NoBrainer.run { aggregate_rql(:max, *a, &b) }
9
+ instantiate_doc run { aggregate_rql(:max, *a, &b) }
10
10
  end
11
11
 
12
12
  def sum(*a, &b)
13
- NoBrainer.run { aggregate_rql(:sum, *a, &b) }
13
+ run { aggregate_rql(:sum, *a, &b) }
14
14
  end
15
15
 
16
16
  def avg(*a, &b)
17
- NoBrainer.run { aggregate_rql(:avg, *a, &b) }
17
+ run { aggregate_rql(:avg, *a, &b) }
18
18
  end
19
19
 
20
20
  private
21
21
 
22
22
  def aggregate_rql(type, *a, &b)
23
- without_ordering.without_plucking.to_rql.__send__(type, *klass.with_fields_aliased(a), &b)
23
+ rql = without_ordering.without_plucking.to_rql
24
+ rql = rql.__send__(type, *model.with_fields_aliased(a), &b)
25
+ rql = rql.default(nil) unless type == :sum
26
+ rql
24
27
  end
25
28
  end
@@ -1,14 +1,14 @@
1
1
  module NoBrainer::Criteria::Cache
2
2
  extend ActiveSupport::Concern
3
3
 
4
- included { attr_accessor :_with_cache }
4
+ included { criteria_option :with_cache, :merge_with => :set_scalar }
5
5
 
6
6
  def with_cache
7
- chain { |criteria| criteria._with_cache = true }
7
+ chain(:with_cache => true)
8
8
  end
9
9
 
10
10
  def without_cache
11
- chain { |criteria| criteria._with_cache = false }
11
+ chain(:with_cache => false)
12
12
  end
13
13
 
14
14
  def inspect
@@ -18,14 +18,14 @@ module NoBrainer::Criteria::Cache
18
18
  end
19
19
 
20
20
  def merge!(criteria, options={})
21
+ if options[:copy_cache_from] && options[:copy_cache_from].cached?
22
+ @cache = options[:copy_cache_from].instance_variable_get(:@cache)
23
+ end
21
24
  super
22
- self._with_cache = criteria._with_cache unless criteria._with_cache.nil?
23
- self.reload unless options[:keep_cache]
24
- self
25
25
  end
26
26
 
27
27
  def with_cache?
28
- @_with_cache != false
28
+ finalized_criteria.options[:with_cache] != false
29
29
  end
30
30
 
31
31
  def reload
@@ -1,14 +1,26 @@
1
1
  module NoBrainer::Criteria::Core
2
2
  extend ActiveSupport::Concern
3
3
 
4
- included { attr_accessor :init_options }
4
+ included do
5
+ singleton_class.send(:attr_accessor, :options_definitions)
6
+ self.options_definitions = {}
7
+ attr_accessor :options
8
+
9
+ criteria_option :model, :merge_with => :set_scalar
10
+ criteria_option :finalized, :merge_with => :set_scalar
11
+ end
5
12
 
6
13
  def initialize(options={})
7
- self.init_options = options
14
+ @options = options
15
+ end
16
+
17
+ def dup
18
+ # We don't keep any of the instance variables except options.
19
+ self.class.new(@options.dup)
8
20
  end
9
21
 
10
- def klass
11
- init_options[:klass]
22
+ def model
23
+ @options[:model]
12
24
  end
13
25
 
14
26
  def to_rql
@@ -16,16 +28,21 @@ module NoBrainer::Criteria::Core
16
28
  end
17
29
 
18
30
  def inspect
19
- # rescue super because sometimes klass is not set.
31
+ # rescue super because sometimes model is not set.
20
32
  to_rql.inspect rescue super
21
33
  end
22
34
 
23
- def run(rql=nil)
24
- NoBrainer.run(:criteria => self) { (rql || to_rql) }
35
+ def run(&block)
36
+ block ||= proc { to_rql }
37
+ NoBrainer.run(:criteria => self, &block)
25
38
  end
26
39
 
27
40
  def merge!(criteria, options={})
28
- self.init_options = self.init_options.merge(criteria.init_options)
41
+ criteria.options.each do |k,v|
42
+ merge_proc = self.class.options_definitions[k]
43
+ raise "Non declared option: #{k}" unless merge_proc
44
+ @options[k] = merge_proc.call(@options[k], v)
45
+ end
29
46
  self
30
47
  end
31
48
 
@@ -40,16 +57,14 @@ module NoBrainer::Criteria::Core
40
57
 
41
58
  private
42
59
 
43
- def chain(options={}, &block)
44
- tmp = self.class.new(self.init_options) # we might want to optimize that thing
45
- block.call(tmp)
46
- merge(tmp, options)
60
+ def chain(options={}, merge_options={}, &block)
61
+ merge(self.class.new(options), merge_options)
47
62
  end
48
63
 
49
64
  def compile_rql_pass1
50
65
  # This method is overriden by other modules.
51
- raise "Criteria not bound to a class" unless klass
52
- klass.rql_table
66
+ raise "Criteria not bound to a model" unless model
67
+ model.rql_table
53
68
  end
54
69
 
55
70
  def compile_rql_pass2
@@ -58,7 +73,7 @@ module NoBrainer::Criteria::Core
58
73
  end
59
74
 
60
75
  def finalized?
61
- !!init_options[:finalized]
76
+ !!@options[:finalized]
62
77
  end
63
78
 
64
79
  def finalized_criteria
@@ -66,8 +81,33 @@ module NoBrainer::Criteria::Core
66
81
  end
67
82
 
68
83
  module ClassMethods
84
+ def criteria_option(*names)
85
+ options = names.extract_options!
86
+
87
+ names.map(&:to_sym).each do |name|
88
+ merge_proc = options[:merge_with]
89
+ merge_proc = MergeStrategies.method(merge_proc) if merge_proc.is_a?(Symbol)
90
+ self.options_definitions[name] = merge_proc
91
+ end
92
+ end
93
+
69
94
  def _finalize_criteria(base)
70
- base.merge(base.class.new(:finalized => true))
95
+ base.__send__(:chain, :finalized => true)
96
+ end
97
+ end
98
+
99
+ module MergeStrategies
100
+ extend self
101
+ def set_scalar(a, b)
102
+ b
103
+ end
104
+
105
+ def merge_hash(a, b)
106
+ a ? a.merge(b) : b
107
+ end
108
+
109
+ def append_array(a, b)
110
+ a ? a+b : b
71
111
  end
72
112
  end
73
113
  end
@@ -2,7 +2,7 @@ module NoBrainer::Criteria::Count
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  def count
5
- run(without_ordering.without_plucking.to_rql.count)
5
+ run { without_ordering.without_plucking.to_rql.count }
6
6
  end
7
7
 
8
8
  def empty?
@@ -2,7 +2,7 @@ module NoBrainer::Criteria::Delete
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  def delete_all
5
- run(without_ordering.without_plucking.to_rql.delete)
5
+ run { without_ordering.without_plucking.to_rql.delete }
6
6
  end
7
7
 
8
8
  def destroy_all
@@ -0,0 +1,19 @@
1
+ module NoBrainer::Criteria::Extend
2
+ extend ActiveSupport::Concern
3
+
4
+ included { criteria_option :extend, :merge_with => :append_array }
5
+
6
+ def extend(*modules, &block)
7
+ options = modules.extract_options!
8
+ modules << Module.new(&block) if block
9
+
10
+ return super(*modules) if options[:original_behavior]
11
+ chain(:extend => [modules])
12
+ end
13
+
14
+ def merge!(criteria, options={})
15
+ super.tap do
16
+ @options[:extend].to_a.each { |modules| extend(*modules, :original_behavior => true) }
17
+ end
18
+ end
19
+ end
@@ -18,7 +18,7 @@ module NoBrainer::Criteria::First
18
18
  end
19
19
 
20
20
  def sample(n=nil)
21
- result = NoBrainer.run { self.without_ordering.to_rql.sample(n.nil? ? 1 : n) }
21
+ result = run { self.without_ordering.to_rql.sample(n.nil? ? 1 : n) }
22
22
  result = result.map(&method(:instantiate_doc))
23
23
  n.nil? ? result.first : result
24
24
  end
@@ -1,10 +1,10 @@
1
1
  module NoBrainer::Criteria::Index
2
2
  extend ActiveSupport::Concern
3
3
 
4
- included { attr_accessor :with_index_name }
4
+ included { criteria_option :use_index, :merge_with => :set_scalar }
5
5
 
6
6
  def with_index(index_name=true)
7
- chain { |criteria| criteria.with_index_name = index_name }
7
+ chain(:use_index => index_name)
8
8
  end
9
9
 
10
10
  def without_index
@@ -12,25 +12,19 @@ module NoBrainer::Criteria::Index
12
12
  end
13
13
 
14
14
  def without_index?
15
- finalized_criteria.with_index_name == false
15
+ finalized_criteria.options[:use_index] == false
16
16
  end
17
17
 
18
18
  def used_index
19
- # only one of them will be active.
19
+ # Only one of them will be active.
20
20
  where_index_name || order_by_index_name
21
21
  end
22
22
 
23
- def merge!(criteria, options={})
24
- super
25
- self.with_index_name = criteria.with_index_name unless criteria.with_index_name.nil?
26
- self
27
- end
28
-
29
23
  def compile_rql_pass2
30
24
  super.tap do
31
- if with_index_name && (!used_index || order_by_index_name.to_s == klass.pk_name.to_s)
32
- # The implicit ordering on the indexed pk does not count.
33
- raise NoBrainer::Error::CannotUseIndex.new(with_index_name)
25
+ # The implicit ordering on the indexed pk does not count.
26
+ if @options[:use_index] && (!used_index || order_by_index_name.to_s == model.pk_name.to_s)
27
+ raise NoBrainer::Error::CannotUseIndex.new(@options[:use_index])
34
28
  end
35
29
  end
36
30
  end
@@ -1,31 +1,23 @@
1
1
  module NoBrainer::Criteria::Limit
2
- # TODO Test these guys
3
2
  extend ActiveSupport::Concern
4
3
 
5
- included { attr_accessor :_skip, :_limit }
4
+ included { criteria_option :skip, :limit, :merge_with => :set_scalar }
6
5
 
7
6
  def limit(value)
8
- chain { |criteria| criteria._limit = value }
7
+ chain(:limit => value)
9
8
  end
10
9
 
11
10
  def skip(value)
12
- chain { |criteria| criteria._skip = value }
11
+ chain(:skip => value)
13
12
  end
14
13
  alias_method :offset, :skip
15
14
 
16
- def merge!(criteria, options={})
17
- super
18
- self._skip = criteria._skip if criteria._skip
19
- self._limit = criteria._limit if criteria._limit
20
- self
21
- end
22
-
23
15
  private
24
16
 
25
17
  def compile_rql_pass2
26
18
  rql = super
27
- rql = rql.skip(_skip) if _skip
28
- rql = rql.limit(_limit) if _limit
19
+ rql = rql.skip(@options[:skip]) if @options[:skip]
20
+ rql = rql.limit(@options[:limit]) if @options[:limit]
29
21
  rql
30
22
  end
31
23
  end