nobrainer 0.18.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 +35 -37
- data/lib/no_brainer/criteria/after_find.rb +3 -11
- data/lib/no_brainer/criteria/cache.rb +7 -7
- data/lib/no_brainer/criteria/core.rb +49 -10
- data/lib/no_brainer/criteria/extend.rb +4 -16
- data/lib/no_brainer/criteria/index.rb +7 -13
- data/lib/no_brainer/criteria/limit.rb +5 -12
- data/lib/no_brainer/criteria/order_by.rb +15 -33
- data/lib/no_brainer/criteria/pluck.rb +16 -22
- data/lib/no_brainer/criteria/preload.rb +9 -15
- data/lib/no_brainer/criteria/raw.rb +4 -10
- data/lib/no_brainer/criteria/scope.rb +4 -10
- data/lib/no_brainer/criteria/where.rb +10 -25
- data/lib/no_brainer/document/association/eager_loader.rb +3 -2
- metadata +1 -1
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,30 +1,25 @@
|
|
1
1
|
require 'logger'
|
2
2
|
|
3
3
|
module NoBrainer::Config
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
+
}
|
11
20
|
|
12
|
-
|
13
|
-
|
14
|
-
self.environment = default_environment
|
15
|
-
self.rethinkdb_url = default_rethinkdb_url
|
16
|
-
self.logger = default_logger
|
17
|
-
self.warn_on_active_record = true
|
18
|
-
self.auto_create_databases = true
|
19
|
-
self.auto_create_tables = true
|
20
|
-
self.max_retries_on_connection_failure = default_max_retries_on_connection_failure
|
21
|
-
self.durability = default_durability
|
22
|
-
self.user_timezone = :local
|
23
|
-
self.db_timezone = :utc
|
24
|
-
self.colorize_logger = true
|
25
|
-
self.distributed_lock_class = nil
|
26
|
-
self.per_thread_connection = false
|
27
|
-
end
|
21
|
+
class << self
|
22
|
+
attr_accessor(*SETTINGS.keys)
|
28
23
|
|
29
24
|
def max_reconnection_tries=(value)
|
30
25
|
STDERR.puts "[NoBrainer] config.max_reconnection_tries is deprecated and will be removed"
|
@@ -32,14 +27,23 @@ module NoBrainer::Config
|
|
32
27
|
self.max_retries_on_connection_failure = value
|
33
28
|
end
|
34
29
|
|
30
|
+
def apply_defaults
|
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] }
|
37
|
+
end
|
38
|
+
|
35
39
|
def reset!
|
36
|
-
|
37
|
-
apply_defaults
|
40
|
+
instance_variables.each { |ivar| remove_instance_variable(ivar) }
|
38
41
|
end
|
39
42
|
|
40
43
|
def configure(&block)
|
41
|
-
|
44
|
+
@applied_defaults_for.to_a.each { |k| remove_instance_variable("@#{k}") }
|
42
45
|
block.call(self) if block
|
46
|
+
apply_defaults
|
43
47
|
assert_valid_options!
|
44
48
|
@configured = true
|
45
49
|
|
@@ -50,20 +54,18 @@ module NoBrainer::Config
|
|
50
54
|
!!@configured
|
51
55
|
end
|
52
56
|
|
53
|
-
def assert_valid_options!
|
54
|
-
assert_array_in :durability, [:hard, :soft]
|
55
|
-
assert_array_in :user_timezone, [:unchanged, :utc, :local]
|
56
|
-
assert_array_in :db_timezone, [:unchanged, :utc, :local]
|
57
|
-
end
|
58
|
-
|
59
57
|
def assert_array_in(name, values)
|
60
58
|
unless __send__(name).in?(values)
|
61
59
|
raise ArgumentError.new("Unknown configuration for #{name}: #{__send__(name)}. Valid values are: #{values.inspect}")
|
62
60
|
end
|
63
61
|
end
|
64
62
|
|
63
|
+
def dev_mode?
|
64
|
+
self.environment.to_s.in? %w(development test)
|
65
|
+
end
|
66
|
+
|
65
67
|
def default_app_name
|
66
|
-
defined?(Rails) ? Rails.application.class.parent_name.underscore : nil
|
68
|
+
defined?(Rails) ? Rails.application.class.parent_name.underscore.presence : nil rescue nil
|
67
69
|
end
|
68
70
|
|
69
71
|
def default_environment
|
@@ -93,9 +95,5 @@ module NoBrainer::Config
|
|
93
95
|
def default_max_retries_on_connection_failure
|
94
96
|
dev_mode? ? 1 : 15
|
95
97
|
end
|
96
|
-
|
97
|
-
def dev_mode?
|
98
|
-
self.environment.to_sym.in?([:development, :test])
|
99
|
-
end
|
100
98
|
end
|
101
99
|
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
|
@@ -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
22
|
def model
|
11
|
-
|
23
|
+
@options[:model]
|
12
24
|
end
|
13
25
|
|
14
26
|
def to_rql
|
@@ -26,7 +38,11 @@ module NoBrainer::Criteria::Core
|
|
26
38
|
end
|
27
39
|
|
28
40
|
def merge!(criteria, options={})
|
29
|
-
|
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
|
30
46
|
self
|
31
47
|
end
|
32
48
|
|
@@ -41,10 +57,8 @@ module NoBrainer::Criteria::Core
|
|
41
57
|
|
42
58
|
private
|
43
59
|
|
44
|
-
def chain(options={}, &block)
|
45
|
-
|
46
|
-
block.call(tmp)
|
47
|
-
merge(tmp, options)
|
60
|
+
def chain(options={}, merge_options={}, &block)
|
61
|
+
merge(self.class.new(options), merge_options)
|
48
62
|
end
|
49
63
|
|
50
64
|
def compile_rql_pass1
|
@@ -59,7 +73,7 @@ module NoBrainer::Criteria::Core
|
|
59
73
|
end
|
60
74
|
|
61
75
|
def finalized?
|
62
|
-
|
76
|
+
!!@options[:finalized]
|
63
77
|
end
|
64
78
|
|
65
79
|
def finalized_criteria
|
@@ -67,8 +81,33 @@ module NoBrainer::Criteria::Core
|
|
67
81
|
end
|
68
82
|
|
69
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
|
+
|
70
94
|
def _finalize_criteria(base)
|
71
|
-
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
|
72
111
|
end
|
73
112
|
end
|
74
113
|
end
|
@@ -1,31 +1,19 @@
|
|
1
1
|
module NoBrainer::Criteria::Extend
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
|
-
included {
|
4
|
+
included { criteria_option :extend, :merge_with => :append_array }
|
5
5
|
|
6
6
|
def extend(*modules, &block)
|
7
7
|
options = modules.extract_options!
|
8
8
|
modules << Module.new(&block) if block
|
9
9
|
|
10
10
|
return super(*modules) if options[:original_behavior]
|
11
|
-
|
12
|
-
chain do |criteria|
|
13
|
-
criteria.extend_modules ||= []
|
14
|
-
criteria.extend_modules += [modules]
|
15
|
-
end
|
11
|
+
chain(:extend => [modules])
|
16
12
|
end
|
17
13
|
|
18
14
|
def merge!(criteria, options={})
|
19
|
-
super
|
20
|
-
|
21
|
-
if criteria.extend_modules.present?
|
22
|
-
self.extend_modules = self.extend_modules.to_a + criteria.extend_modules
|
15
|
+
super.tap do
|
16
|
+
@options[:extend].to_a.each { |modules| extend(*modules, :original_behavior => true) }
|
23
17
|
end
|
24
|
-
|
25
|
-
if self.extend_modules.present?
|
26
|
-
self.extend_modules.each { |modules| extend(*modules, :original_behavior => true) }
|
27
|
-
end
|
28
|
-
|
29
|
-
self
|
30
18
|
end
|
31
19
|
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,30 +1,23 @@
|
|
1
1
|
module NoBrainer::Criteria::Limit
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
|
-
included {
|
4
|
+
included { criteria_option :skip, :limit, :merge_with => :set_scalar }
|
5
5
|
|
6
6
|
def limit(value)
|
7
|
-
chain
|
7
|
+
chain(:limit => value)
|
8
8
|
end
|
9
9
|
|
10
10
|
def skip(value)
|
11
|
-
chain
|
11
|
+
chain(:skip => value)
|
12
12
|
end
|
13
13
|
alias_method :offset, :skip
|
14
14
|
|
15
|
-
def merge!(criteria, options={})
|
16
|
-
super
|
17
|
-
self._skip = criteria._skip if criteria._skip
|
18
|
-
self._limit = criteria._limit if criteria._limit
|
19
|
-
self
|
20
|
-
end
|
21
|
-
|
22
15
|
private
|
23
16
|
|
24
17
|
def compile_rql_pass2
|
25
18
|
rql = super
|
26
|
-
rql = rql.skip(
|
27
|
-
rql = rql.limit(
|
19
|
+
rql = rql.skip(@options[:skip]) if @options[:skip]
|
20
|
+
rql = rql.limit(@options[:limit]) if @options[:limit]
|
28
21
|
rql
|
29
22
|
end
|
30
23
|
end
|
@@ -1,12 +1,8 @@
|
|
1
1
|
module NoBrainer::Criteria::OrderBy
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(options={})
|
7
|
-
super
|
8
|
-
self.order = {}
|
9
|
-
end
|
4
|
+
# The latest order_by() wins
|
5
|
+
included { criteria_option :order_by, :ordering_mode, :merge_with => :set_scalar }
|
10
6
|
|
11
7
|
def order_by(*rules, &block)
|
12
8
|
# Note: We are relying on the fact that Hashes are ordered (since 1.9)
|
@@ -21,34 +17,20 @@ module NoBrainer::Criteria::OrderBy
|
|
21
17
|
end
|
22
18
|
end.reduce({}, :merge)
|
23
19
|
|
24
|
-
chain
|
25
|
-
criteria.order = rules
|
26
|
-
criteria.ordering_mode = :normal
|
27
|
-
end
|
20
|
+
chain(:order_by => rules, :ordering_mode => :normal)
|
28
21
|
end
|
29
22
|
|
30
23
|
def without_ordering
|
31
|
-
chain
|
32
|
-
end
|
33
|
-
|
34
|
-
def merge!(criteria, options={})
|
35
|
-
super
|
36
|
-
# The latest order_by() wins
|
37
|
-
self.order = criteria.order if criteria.order.present?
|
38
|
-
self.ordering_mode = criteria.ordering_mode unless criteria.ordering_mode.nil?
|
39
|
-
self
|
24
|
+
chain(:ordering_mode => :disabled)
|
40
25
|
end
|
41
26
|
|
42
27
|
def reverse_order
|
43
|
-
chain
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
when :disabled then :disabled
|
50
|
-
end
|
51
|
-
end
|
28
|
+
chain(:ordering_mode => case @options[:ordering_mode]
|
29
|
+
when nil then :reversed
|
30
|
+
when :normal then :reversed
|
31
|
+
when :reversed then :normal
|
32
|
+
when :disabled then :disabled
|
33
|
+
end)
|
52
34
|
end
|
53
35
|
|
54
36
|
def order_by_indexed?
|
@@ -62,15 +44,15 @@ module NoBrainer::Criteria::OrderBy
|
|
62
44
|
private
|
63
45
|
|
64
46
|
def effective_order
|
65
|
-
|
47
|
+
@options[:order_by].presence || (model ? {model.pk_name => :asc} : {})
|
66
48
|
end
|
67
49
|
|
68
50
|
def reverse_order?
|
69
|
-
|
51
|
+
@options[:ordering_mode] == :reversed
|
70
52
|
end
|
71
53
|
|
72
54
|
def should_order?
|
73
|
-
|
55
|
+
@options[:ordering_mode] != :disabled
|
74
56
|
end
|
75
57
|
|
76
58
|
class IndexFinder < Struct.new(:criteria, :index_name, :rql_proc)
|
@@ -90,8 +72,8 @@ module NoBrainer::Criteria::OrderBy
|
|
90
72
|
return if criteria.without_index?
|
91
73
|
return unless first_key_indexable?
|
92
74
|
|
93
|
-
if criteria.
|
94
|
-
return unless first_key.to_s == criteria.
|
75
|
+
if criteria.options[:use_index] && criteria.options[:use_index] != true
|
76
|
+
return unless first_key.to_s == criteria.options[:use_index].to_s
|
95
77
|
end
|
96
78
|
|
97
79
|
# We need make sure that the where index finder has been invoked, it has priority.
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module NoBrainer::Criteria::Pluck
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
|
-
included {
|
4
|
+
included { criteria_option :missing_attributes, :merge_with =>
|
5
|
+
NoBrainer::Criteria::Pluck.method(:merge_missing_attributes) }
|
5
6
|
|
6
7
|
def pluck(*attrs)
|
7
8
|
_missing_attributes_criteria(:pluck, attrs)
|
@@ -16,24 +17,19 @@ module NoBrainer::Criteria::Pluck
|
|
16
17
|
end
|
17
18
|
|
18
19
|
def without_plucking
|
19
|
-
chain
|
20
|
+
chain(:missing_attributes => :remove)
|
20
21
|
end
|
21
22
|
|
22
|
-
def
|
23
|
-
return
|
23
|
+
def self.merge_missing_attributes(a, b)
|
24
|
+
return nil if b.nil? || b == :remove
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
old_attrs = self.missing_attributes[type] || {}.with_indifferent_access
|
31
|
-
new_attrs = old_attrs.deep_merge(attrs)
|
32
|
-
self.missing_attributes[type] = new_attrs
|
33
|
-
end
|
26
|
+
a = a ? a.dup : {}
|
27
|
+
b.each do |type, attrs|
|
28
|
+
old_attrs = a[type] || {}.with_indifferent_access
|
29
|
+
new_attrs = old_attrs.deep_merge(attrs)
|
30
|
+
a[type] = new_attrs
|
34
31
|
end
|
35
|
-
|
36
|
-
self
|
32
|
+
a
|
37
33
|
end
|
38
34
|
|
39
35
|
private
|
@@ -41,16 +37,14 @@ module NoBrainer::Criteria::Pluck
|
|
41
37
|
def _missing_attributes_criteria(type, args)
|
42
38
|
raise ArgumentError if args.size.zero?
|
43
39
|
args = [Hash[args.flatten.map { |k| [k, true] }]] unless args.size == 1 && args.first.is_a?(Hash)
|
44
|
-
chain
|
45
|
-
|
40
|
+
chain(:missing_attributes => {type => args.first})
|
46
41
|
end
|
47
42
|
|
48
43
|
def effective_missing_attributes
|
49
|
-
return nil if
|
44
|
+
return nil if @options[:missing_attributes].nil?
|
50
45
|
@effective_missing_attributes ||= begin
|
51
46
|
# pluck gets priority
|
52
|
-
|
53
|
-
missing_attributes = Hash[self.missing_attributes.map do |type, attrs|
|
47
|
+
missing_attributes = Hash[@options[:missing_attributes].map do |type, attrs|
|
54
48
|
attrs = attrs.select { |k,v| v } # TODO recursive
|
55
49
|
attrs.empty? ? nil : [type, attrs]
|
56
50
|
end.compact]
|
@@ -65,9 +59,9 @@ module NoBrainer::Criteria::Pluck
|
|
65
59
|
end
|
66
60
|
|
67
61
|
def _instantiate_model(attrs, options={})
|
68
|
-
return super if missing_attributes.nil?
|
62
|
+
return super if @options[:missing_attributes].nil?
|
69
63
|
super(attrs, options.merge(:missing_attributes => effective_missing_attributes,
|
70
|
-
:lazy_fetch => missing_attributes[:lazy_fetch]))
|
64
|
+
:lazy_fetch => @options[:missing_attributes][:lazy_fetch]))
|
71
65
|
end
|
72
66
|
|
73
67
|
def compile_rql_pass2
|
@@ -1,24 +1,18 @@
|
|
1
1
|
module NoBrainer::Criteria::Preload
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
|
-
included {
|
5
|
-
|
6
|
-
def initialize(options={})
|
7
|
-
super
|
8
|
-
self._preloads = []
|
9
|
-
end
|
4
|
+
included { criteria_option :preload, :merge_with => :append_array }
|
10
5
|
|
11
6
|
def preload(*values)
|
12
|
-
chain(:
|
7
|
+
chain({:preload => values}, :copy_cache_from => self)
|
13
8
|
end
|
14
9
|
|
15
10
|
def merge!(criteria, options={})
|
16
|
-
super
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
perform_preloads(@cache)
|
11
|
+
super.tap do
|
12
|
+
# XXX Not pretty hack
|
13
|
+
if criteria.options[:preload].present? && criteria.cached?
|
14
|
+
perform_preloads(@cache)
|
15
|
+
end
|
22
16
|
end
|
23
17
|
end
|
24
18
|
|
@@ -35,7 +29,7 @@ module NoBrainer::Criteria::Preload
|
|
35
29
|
private
|
36
30
|
|
37
31
|
def should_preloads?
|
38
|
-
|
32
|
+
@options[:preload].present? && !raw?
|
39
33
|
end
|
40
34
|
|
41
35
|
def get_one(criteria)
|
@@ -44,7 +38,7 @@ module NoBrainer::Criteria::Preload
|
|
44
38
|
|
45
39
|
def perform_preloads(docs)
|
46
40
|
if should_preloads? && docs.present?
|
47
|
-
NoBrainer::Document::Association::EagerLoader.new.eager_load(docs,
|
41
|
+
NoBrainer::Document::Association::EagerLoader.new.eager_load(docs, @options[:preload])
|
48
42
|
end
|
49
43
|
end
|
50
44
|
end
|
@@ -1,20 +1,14 @@
|
|
1
1
|
module NoBrainer::Criteria::Raw
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
|
-
included {
|
4
|
+
included { criteria_option :raw, :merge_with => :set_scalar }
|
5
5
|
|
6
|
-
def raw
|
7
|
-
chain
|
8
|
-
end
|
9
|
-
|
10
|
-
def merge!(criteria, options={})
|
11
|
-
super
|
12
|
-
self._raw = criteria._raw unless criteria._raw.nil?
|
13
|
-
self
|
6
|
+
def raw(value = true)
|
7
|
+
chain(:raw => value)
|
14
8
|
end
|
15
9
|
|
16
10
|
def raw?
|
17
|
-
!!finalized_criteria.
|
11
|
+
!!finalized_criteria.options[:raw]
|
18
12
|
end
|
19
13
|
|
20
14
|
private
|
@@ -1,20 +1,14 @@
|
|
1
1
|
module NoBrainer::Criteria::Scope
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
|
-
included {
|
4
|
+
included { criteria_option :use_default_scope, :merge_with => :set_scalar }
|
5
5
|
|
6
6
|
def scoped
|
7
|
-
chain
|
7
|
+
chain(:use_default_scope => true)
|
8
8
|
end
|
9
9
|
|
10
10
|
def unscoped
|
11
|
-
chain
|
12
|
-
end
|
13
|
-
|
14
|
-
def merge!(criteria, options={})
|
15
|
-
super
|
16
|
-
self.use_default_scope = criteria.use_default_scope unless criteria.use_default_scope.nil?
|
17
|
-
self
|
11
|
+
chain(:use_default_scope => false)
|
18
12
|
end
|
19
13
|
|
20
14
|
def respond_to?(name, include_private = false)
|
@@ -31,7 +25,7 @@ module NoBrainer::Criteria::Scope
|
|
31
25
|
private
|
32
26
|
|
33
27
|
def should_apply_default_scope?
|
34
|
-
model.default_scope_proc && use_default_scope != false
|
28
|
+
model.default_scope_proc && @options[:use_default_scope] != false
|
35
29
|
end
|
36
30
|
|
37
31
|
def _apply_default_scope
|
@@ -1,35 +1,20 @@
|
|
1
1
|
module NoBrainer::Criteria::Where
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
|
-
included
|
5
|
-
|
6
|
-
def initialize(options={})
|
7
|
-
super
|
4
|
+
included do
|
5
|
+
criteria_option :where_ast, :merge_with => NoBrainer::Criteria::Where.method(:merge_where_ast)
|
8
6
|
end
|
9
7
|
|
10
8
|
def where(*args, &block)
|
11
|
-
chain
|
9
|
+
chain(:where_ast => parse_clause([*args, block].compact))
|
12
10
|
end
|
13
11
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
-
if criteria.where_ast
|
18
|
-
if self.where_ast
|
19
|
-
self.where_ast = MultiOperator.new(:and, [self.where_ast, criteria.where_ast])
|
20
|
-
else
|
21
|
-
self.where_ast = criteria.where_ast
|
22
|
-
end
|
23
|
-
self.where_ast = self.where_ast.simplify
|
24
|
-
raise unless criteria.where_ast.is_a?(MultiOperator)
|
25
|
-
end
|
26
|
-
|
27
|
-
self.with_index_name = criteria.with_index_name unless criteria.with_index_name.nil?
|
28
|
-
self
|
12
|
+
def self.merge_where_ast(a, b)
|
13
|
+
(a ? MultiOperator.new(:and, [a, b]) : b).simplify
|
29
14
|
end
|
30
15
|
|
31
16
|
def where_present?
|
32
|
-
finalized_criteria.where_ast.try(:clauses).present?
|
17
|
+
finalized_criteria.options[:where_ast].try(:clauses).present?
|
33
18
|
end
|
34
19
|
|
35
20
|
def where_indexed?
|
@@ -232,8 +217,8 @@ module NoBrainer::Criteria::Where
|
|
232
217
|
@usable_indexes[types] ||= begin
|
233
218
|
indexes = criteria.model.indexes.values
|
234
219
|
indexes = indexes.select { |i| types.include?(i.kind) } if types.present?
|
235
|
-
if criteria.
|
236
|
-
indexes = indexes.select { |i| i.name == criteria.
|
220
|
+
if criteria.options[:use_index] && criteria.options[:use_index] != true
|
221
|
+
indexes = indexes.select { |i| i.name == criteria.options[:use_index].to_sym }
|
237
222
|
end
|
238
223
|
indexes
|
239
224
|
end
|
@@ -327,7 +312,7 @@ module NoBrainer::Criteria::Where
|
|
327
312
|
|
328
313
|
def where_index_finder
|
329
314
|
return finalized_criteria.__send__(:where_index_finder) unless finalized?
|
330
|
-
@where_index_finder ||= IndexFinder.new(self, where_ast).tap { |index_finder| index_finder.find_index }
|
315
|
+
@where_index_finder ||= IndexFinder.new(self, @options[:where_ast]).tap { |index_finder| index_finder.find_index }
|
331
316
|
end
|
332
317
|
|
333
318
|
def compile_rql_pass1
|
@@ -338,7 +323,7 @@ module NoBrainer::Criteria::Where
|
|
338
323
|
|
339
324
|
def compile_rql_pass2
|
340
325
|
rql = super
|
341
|
-
ast = where_index_finder.could_find_index? ? where_index_finder.ast :
|
326
|
+
ast = where_index_finder.could_find_index? ? where_index_finder.ast : @options[:where_ast]
|
342
327
|
rql = rql.filter { |doc| ast.to_rql(doc) } if ast.try(:clauses).present?
|
343
328
|
rql
|
344
329
|
end
|
@@ -45,14 +45,15 @@ class NoBrainer::Document::Association::EagerLoader
|
|
45
45
|
when Hash then preloads.each do |k,v|
|
46
46
|
if v.is_a?(NoBrainer::Criteria)
|
47
47
|
v = v.dup
|
48
|
-
nested_preloads, v.
|
48
|
+
nested_preloads, v.options[:preload] = v.options[:preload], []
|
49
49
|
eager_load(eager_load_association(docs, k, v), nested_preloads)
|
50
50
|
else
|
51
51
|
eager_load(eager_load_association(docs, k), v)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
when Array then preloads.each { |v| eager_load(docs, v) }
|
55
|
-
|
55
|
+
when nil then;
|
56
|
+
else eager_load_association(docs, preloads) # String and Symbol
|
56
57
|
end
|
57
58
|
true
|
58
59
|
end
|