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.
- checksums.yaml +4 -4
- data/lib/no_brainer/config.rb +53 -28
- data/lib/no_brainer/connection.rb +1 -0
- data/lib/no_brainer/connection_manager.rb +60 -0
- data/lib/no_brainer/criteria/after_find.rb +3 -11
- data/lib/no_brainer/criteria/aggregate.rb +8 -5
- data/lib/no_brainer/criteria/cache.rb +7 -7
- data/lib/no_brainer/criteria/core.rb +56 -16
- 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 +19 -0
- data/lib/no_brainer/criteria/first.rb +1 -1
- data/lib/no_brainer/criteria/index.rb +7 -13
- data/lib/no_brainer/criteria/limit.rb +5 -13
- data/lib/no_brainer/criteria/order_by.rb +22 -41
- data/lib/no_brainer/criteria/pluck.rb +17 -23
- data/lib/no_brainer/criteria/preload.rb +9 -15
- data/lib/no_brainer/criteria/raw.rb +5 -11
- data/lib/no_brainer/criteria/scope.rb +9 -15
- data/lib/no_brainer/criteria/update.rb +3 -3
- data/lib/no_brainer/criteria/where.rb +33 -56
- data/lib/no_brainer/criteria.rb +1 -1
- data/lib/no_brainer/document/aliases.rb +1 -1
- 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 +4 -3
- 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/association.rb +5 -5
- data/lib/no_brainer/document/atomic_ops.rb +213 -0
- data/lib/no_brainer/document/attributes.rb +19 -10
- 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 +22 -22
- data/lib/no_brainer/document/dynamic_attributes.rb +2 -14
- data/lib/no_brainer/document/id.rb +1 -0
- 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/index.rb +13 -72
- data/lib/no_brainer/document/lazy_fetch.rb +5 -5
- data/lib/no_brainer/document/missing_attributes.rb +6 -23
- data/lib/no_brainer/document/persistance.rb +38 -21
- data/lib/no_brainer/document/polymorphic.rb +1 -1
- data/lib/no_brainer/document/types/set.rb +23 -0
- data/lib/no_brainer/document/types.rb +8 -6
- data/lib/no_brainer/document/uniqueness.rb +3 -3
- data/lib/no_brainer/document/validation.rb +13 -4
- data/lib/no_brainer/document.rb +1 -1
- data/lib/no_brainer/error.rb +14 -0
- data/lib/no_brainer/fork.rb +1 -0
- data/lib/no_brainer/query_runner/connection_lock.rb +5 -1
- 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/database.rake +12 -12
- data/lib/no_brainer/railtie.rb +5 -5
- data/lib/no_brainer/rql.rb +9 -0
- data/lib/nobrainer.rb +9 -23
- metadata +10 -4
- data/lib/no_brainer/index_manager.rb +0 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1d6a500e008eff372e800b011e917d121c07e00a
|
|
4
|
+
data.tar.gz: e43be89ac4963422c26559727c9a68011ee25f8a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 56015e819aba3537ab60ea5f039d4b391ec803cc61b5bf246e44da642787e62606e9c02339b17f05976d5428ec3e4fa0e335cb51694b840bd2ba7821b6d66b20
|
|
7
|
+
data.tar.gz: d4b78185fed14f5baa28165462a4088096da640d93c0dfb3f20c851e968deceb1f48f13602850075a7eea2408fa23e52c2694d140bea1c9a937d7d49d5084f53
|
data/lib/no_brainer/config.rb
CHANGED
|
@@ -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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
27
|
-
apply_defaults
|
|
40
|
+
instance_variables.each { |ivar| remove_instance_variable(ivar) }
|
|
28
41
|
end
|
|
29
42
|
|
|
30
43
|
def configure(&block)
|
|
31
|
-
|
|
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 ||= "#{
|
|
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
|
-
|
|
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
|
|
@@ -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 {
|
|
4
|
+
included { criteria_option :after_find, :merge_with => :append_array }
|
|
5
5
|
|
|
6
6
|
def after_find(b=nil, &block)
|
|
7
|
-
chain
|
|
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
|
-
|
|
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
|
|
5
|
+
instantiate_doc run { aggregate_rql(:min, *a, &b) }
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def max(*a, &b)
|
|
9
|
-
instantiate_doc
|
|
9
|
+
instantiate_doc run { aggregate_rql(:max, *a, &b) }
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def sum(*a, &b)
|
|
13
|
-
|
|
13
|
+
run { aggregate_rql(:sum, *a, &b) }
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def avg(*a, &b)
|
|
17
|
-
|
|
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
|
|
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 {
|
|
4
|
+
included { criteria_option :with_cache, :merge_with => :set_scalar }
|
|
5
5
|
|
|
6
6
|
def with_cache
|
|
7
|
-
chain
|
|
7
|
+
chain(:with_cache => true)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def without_cache
|
|
11
|
-
chain
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
11
|
-
|
|
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
|
|
31
|
+
# rescue super because sometimes model is not set.
|
|
20
32
|
to_rql.inspect rescue super
|
|
21
33
|
end
|
|
22
34
|
|
|
23
|
-
def run(
|
|
24
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
52
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
@@ -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 =
|
|
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 {
|
|
4
|
+
included { criteria_option :use_index, :merge_with => :set_scalar }
|
|
5
5
|
|
|
6
6
|
def with_index(index_name=true)
|
|
7
|
-
chain
|
|
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.
|
|
15
|
+
finalized_criteria.options[:use_index] == false
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def used_index
|
|
19
|
-
#
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
raise NoBrainer::Error::CannotUseIndex.new(
|
|
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 {
|
|
4
|
+
included { criteria_option :skip, :limit, :merge_with => :set_scalar }
|
|
6
5
|
|
|
7
6
|
def limit(value)
|
|
8
|
-
chain
|
|
7
|
+
chain(:limit => value)
|
|
9
8
|
end
|
|
10
9
|
|
|
11
10
|
def skip(value)
|
|
12
|
-
chain
|
|
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(
|
|
28
|
-
rql = rql.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
|