nobrainer 0.10.0 → 0.13.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +169 -0
  3. data/lib/no_brainer/autoload.rb +1 -1
  4. data/lib/no_brainer/criteria/after_find.rb +24 -0
  5. data/lib/no_brainer/criteria/{termination/cache.rb → cache.rb} +1 -1
  6. data/lib/no_brainer/criteria/{chainable/core.rb → core.rb} +2 -2
  7. data/lib/no_brainer/criteria/{termination/count.rb → count.rb} +1 -1
  8. data/lib/no_brainer/criteria/{termination/delete.rb → delete.rb} +2 -2
  9. data/lib/no_brainer/criteria/{termination/enumerable.rb → enumerable.rb} +1 -1
  10. data/lib/no_brainer/criteria/{termination/first.rb → first.rb} +1 -1
  11. data/lib/no_brainer/criteria/{chainable/limit.rb → limit.rb} +1 -1
  12. data/lib/no_brainer/criteria/{chainable/order_by.rb → order_by.rb} +1 -1
  13. data/lib/no_brainer/criteria/preload.rb +55 -0
  14. data/lib/no_brainer/criteria/raw.rb +25 -0
  15. data/lib/no_brainer/criteria/{chainable/scope.rb → scope.rb} +1 -1
  16. data/lib/no_brainer/criteria/update.rb +11 -0
  17. data/lib/no_brainer/criteria/{chainable/where.rb → where.rb} +61 -25
  18. data/lib/no_brainer/criteria.rb +3 -16
  19. data/lib/no_brainer/document/association/belongs_to.rb +10 -2
  20. data/lib/no_brainer/document/association/core.rb +2 -2
  21. data/lib/no_brainer/document/association/eager_loader.rb +7 -7
  22. data/lib/no_brainer/document/association/has_many.rb +1 -1
  23. data/lib/no_brainer/document/attributes.rb +30 -44
  24. data/lib/no_brainer/document/callbacks.rb +29 -0
  25. data/lib/no_brainer/document/core.rb +0 -2
  26. data/lib/no_brainer/document/criteria.rb +1 -2
  27. data/lib/no_brainer/document/dirty.rb +52 -52
  28. data/lib/no_brainer/document/dynamic_attributes.rb +11 -3
  29. data/lib/no_brainer/document/id.rb +1 -1
  30. data/lib/no_brainer/document/index.rb +7 -14
  31. data/lib/no_brainer/document/injection_layer.rb +2 -3
  32. data/lib/no_brainer/document/persistance.rb +29 -43
  33. data/lib/no_brainer/document/readonly.rb +19 -0
  34. data/lib/no_brainer/document/serialization.rb +0 -1
  35. data/lib/no_brainer/document/timestamps.rb +9 -9
  36. data/lib/no_brainer/document/types.rb +46 -41
  37. data/lib/no_brainer/document/validation.rb +6 -0
  38. data/lib/no_brainer/document.rb +4 -4
  39. data/lib/no_brainer/error.rb +37 -9
  40. data/lib/no_brainer/query_runner/connection.rb +36 -9
  41. data/lib/no_brainer/query_runner/missing_index.rb +1 -1
  42. data/lib/no_brainer/query_runner/run_options.rb +4 -2
  43. data/lib/no_brainer/railtie.rb +10 -0
  44. data/lib/nobrainer.rb +3 -7
  45. metadata +54 -44
  46. data/LICENSE.md +0 -7
  47. data/lib/no_brainer/criteria/chainable/raw.rb +0 -33
  48. data/lib/no_brainer/criteria/termination/eager_loading.rb +0 -50
  49. data/lib/no_brainer/criteria/termination/inc.rb +0 -14
  50. data/lib/no_brainer/criteria/termination/update.rb +0 -13
@@ -1,14 +1,9 @@
1
1
  module NoBrainer::Document::Types
2
2
  extend ActiveSupport::Concern
3
3
 
4
- included do
5
- # We namespace our fake Boolean class to avoid polluting the global namespace
6
- class_exec { class Boolean; def initialize; raise; end; end }
7
- before_validation :add_type_errors
8
- end
9
-
10
4
  module CastingRules
11
5
  extend self
6
+ InvalidType = NoBrainer::Error::InvalidType
12
7
 
13
8
  def String(value)
14
9
  case value
@@ -63,67 +58,77 @@ module NoBrainer::Document::Types
63
58
  else raise InvalidType
64
59
  end
65
60
  end
66
- end
67
-
68
- def self.cast(value, type, cast_method)
69
- return value if value.nil? || type.nil? || value.is_a?(type)
70
- cast_method.call(value)
71
- end
72
61
 
73
- def self.lookup_cast_method(type)
74
- type = type.to_s
75
- type = 'Boolean' if type == 'NoBrainer::Document::Types::Boolean'
76
- CastingRules.method(type)
77
- rescue NameError
78
- proc { raise InvalidType }
79
- end
62
+ def lookup(type)
63
+ CastingRules.method(type.to_s)
64
+ rescue NameError
65
+ proc { raise InvalidType }
66
+ end
80
67
 
81
- class InvalidType < RuntimeError
82
- attr_accessor :type
83
- def initialize(type=nil)
84
- @type = type
68
+ def cast(value, type, type_cast_method)
69
+ return value if value.nil? || type.nil? || value.is_a?(type)
70
+ type_cast_method.call(value)
85
71
  end
72
+ end
86
73
 
87
- def validation_error_args
88
- [:invalid_type, :type => type.to_s.underscore.humanize.downcase]
74
+ included do
75
+ # We namespace our fake Boolean class to avoid polluting the global namespace
76
+ class_exec do
77
+ class Boolean
78
+ def initialize; raise; end
79
+ def self.inspect; 'Boolean'; end
80
+ def self.to_s; inspect; end
81
+ def self.name; inspect; end
82
+ end
89
83
  end
84
+ before_validation :add_type_errors
90
85
  end
91
86
 
92
87
  def add_type_errors
93
88
  return unless @pending_type_errors
94
89
  @pending_type_errors.each do |name, error|
95
- errors.add(name, *error.validation_error_args)
90
+ errors.add(name, :invalid_type, :type => error.human_type_name)
96
91
  end
97
92
  end
98
93
 
99
94
  module ClassMethods
100
- def field(name, options={})
95
+ def cast_value_for(attr, value)
96
+ attr = attr.to_sym
97
+ field_def = fields[attr]
98
+ return value unless field_def && field_def[:type]
99
+ NoBrainer::Document::Types::CastingRules.cast(value, field_def[:type], field_def[:type_cast_method])
100
+ rescue NoBrainer::Error::InvalidType => error
101
+ error.type = field_def[:type]
102
+ error.value = value
103
+ error.attr_name = attr
104
+ raise error
105
+ end
106
+
107
+ def _field(attr, options={})
101
108
  super
102
- return unless options.has_key?(:type)
103
- name = name.to_sym
104
- type = options[:type]
105
- cast_method = NoBrainer::Document::Types.lookup_cast_method(type)
106
109
 
107
110
  inject_in_layer :types do
108
- define_method("#{name}=") do |value|
111
+ define_method("#{attr}=") do |value|
109
112
  begin
110
- value = NoBrainer::Document::Types.cast(value, type, cast_method)
111
- @pending_type_errors.try(:delete, name)
112
- rescue NoBrainer::Document::Types::InvalidType => error
113
- error.type ||= type
113
+ value = self.class.cast_value_for(attr, value)
114
+ @pending_type_errors.try(:delete, attr)
115
+ rescue NoBrainer::Error::InvalidType => error
114
116
  @pending_type_errors ||= {}
115
- @pending_type_errors[name] = error
117
+ @pending_type_errors[attr] = error
116
118
  end
117
119
  super(value)
118
120
  end
121
+
122
+ define_method("#{attr}?") { !!read_attribute(attr) } if options[:type] == Boolean
119
123
  end
120
124
  end
121
125
 
122
- def remove_field(name)
126
+ def field(attr, options={})
127
+ if options[:type]
128
+ type_cast_method = NoBrainer::Document::Types::CastingRules.lookup(options[:type])
129
+ options = options.merge(:type_cast_method => type_cast_method)
130
+ end
123
131
  super
124
- inject_in_layer :types, <<-RUBY, __FILE__, __LINE__ + 1
125
- undef #{name}=
126
- RUBY
127
132
  end
128
133
  end
129
134
  end
@@ -8,6 +8,12 @@ module NoBrainer::Document::Validation
8
8
  end
9
9
 
10
10
  module ClassMethods
11
+ def _field(attr, options={})
12
+ super
13
+ validates(attr, { :presence => true }) if options[:required]
14
+ validates(attr, options[:validates]) if options[:validates]
15
+ end
16
+
11
17
  def validates_uniqueness_of(*attr_names)
12
18
  validates_with UniquenessValidator, _merge_attributes(attr_names)
13
19
  end
@@ -4,11 +4,11 @@ module NoBrainer::Document
4
4
  extend ActiveSupport::Concern
5
5
  extend NoBrainer::Autoload
6
6
 
7
- autoload_and_include :Core, :StoreIn, :InjectionLayer, :Attributes, :Validation, :Types,
8
- :Persistance, :Dirty, :Id, :Association, :Serialization, :Criteria,
9
- :Polymorphic, :Index, :Timestamps
7
+ autoload_and_include :Core, :StoreIn, :InjectionLayer, :Attributes, :Readonly, :Validation, :Types,
8
+ :Persistance, :Callbacks, :Dirty, :Id, :Association, :Serialization,
9
+ :Criteria, :Polymorphic, :Index
10
10
 
11
- autoload :DynamicAttributes
11
+ autoload :DynamicAttributes, :Timestamps
12
12
 
13
13
  singleton_class.delegate :all, :to => Core
14
14
  end
@@ -1,11 +1,39 @@
1
1
  module NoBrainer::Error
2
- class Connection < StandardError; end
3
- class DocumentNotFound < StandardError; end
4
- class DocumentInvalid < StandardError; end
5
- class DocumentNotSaved < StandardError; end
6
- class ChildrenExist < StandardError; end
7
- class CannotUseIndex < StandardError; end
8
- class MissingIndex < StandardError; end
9
- class InvalidType < StandardError; end
10
- class AssociationNotSaved < StandardError; end
2
+ class Connection < RuntimeError; end
3
+ class DocumentNotFound < RuntimeError; end
4
+ class DocumentNotSaved < RuntimeError; end
5
+ class ChildrenExist < RuntimeError; end
6
+ class CannotUseIndex < RuntimeError; end
7
+ class MissingIndex < RuntimeError; end
8
+ class InvalidType < RuntimeError; end
9
+ class AssociationNotSaved < RuntimeError; end
10
+ class ReadonlyField < RuntimeError; end
11
+
12
+ class DocumentInvalid < RuntimeError
13
+ attr_accessor :instance
14
+ def initialize(instance)
15
+ @instance = instance
16
+ end
17
+
18
+ def message
19
+ "#{instance} is invalid: #{instance.errors.full_messages.join(", ")}"
20
+ end
21
+ end
22
+
23
+ class InvalidType < RuntimeError
24
+ attr_accessor :attr_name, :value, :type
25
+ def initialize(options={})
26
+ @attr_name = options[:attr_name]
27
+ @value = options[:value]
28
+ @type = options[:type]
29
+ end
30
+
31
+ def human_type_name
32
+ type.to_s.underscore.humanize.downcase
33
+ end
34
+
35
+ def message
36
+ "#{attr_name} should be used with a #{human_type_name}. Got `#{value}`"
37
+ end
38
+ end
11
39
  end
@@ -1,17 +1,44 @@
1
1
  class NoBrainer::QueryRunner::Connection < NoBrainer::QueryRunner::Middleware
2
2
  def call(env)
3
3
  @runner.call(env)
4
- rescue RuntimeError, NoBrainer::Error::DocumentNotSaved => e
5
- if e.message =~ /cannot perform (read|write): lost contact with master/
6
- env[:connection_retries] ||= 0
7
- # TODO sleep in between? timing out should be time based?
4
+ rescue StandardError => e
5
+ # TODO test that thing
6
+ if is_connection_error_exception?(e)
7
+ retry if reconnect
8
+ end
9
+ raise
10
+ end
11
+
12
+ private
8
13
 
9
- # XXX Possibly dangerous, as we could reexecute a non idempotent operation
10
- # Check the semantics of the db
14
+ def reconnect
15
+ # FIXME thread safety? perhaps we need to use a connection pool
16
+ # XXX Possibly dangerous, as we could reexecute a non idempotent operation
17
+ # Check the semantics of the db
18
+ NoBrainer::Config.max_reconnection_tries.times do
19
+ begin
20
+ NoBrainer.logger.try(:warn, "Lost connection to #{NoBrainer::Config.rethinkdb_url}, retrying...")
21
+ sleep 1
22
+ NoBrainer.connection.reconnect(:noreply_wait => false)
23
+ return true
24
+ rescue StandardError => e
25
+ retry if is_connection_error_exception?(e)
26
+ raise
27
+ end
28
+ end
29
+ false
30
+ end
11
31
 
12
- # TODO Unit test
13
- retry if (env[:connection_retries] += 1) < NoBrainer::Config.max_reconnection_tries
32
+ def is_connection_error_exception?(e)
33
+ case e
34
+ when Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::EPIPE,
35
+ Errno::ECONNRESET, Errno::ETIMEDOUT, IOError
36
+ true
37
+ when RethinkDB::RqlRuntimeError
38
+ e.message =~ /cannot perform (read|write): No master available/ ||
39
+ e.message =~ /Error: Connection Closed/
40
+ else
41
+ false
14
42
  end
15
- raise e
16
43
  end
17
44
  end
@@ -3,7 +3,7 @@ class NoBrainer::QueryRunner::MissingIndex < NoBrainer::QueryRunner::Middleware
3
3
  @runner.call(env)
4
4
  rescue RethinkDB::RqlRuntimeError => e
5
5
  if e.message =~ /^Index `(.+)` was not found\.$/
6
- raise NoBrainer::Error::MissingIndex.new("Please run \"rake db:update_indexes\" to create index `#{$1}`\n" +
6
+ raise NoBrainer::Error::MissingIndex.new("Please run \"rake db:update_indexes\" to create the index `#{$1}`\n" +
7
7
  "--> Read http://nobrainer.io/docs/indexes for more information.")
8
8
  end
9
9
  raise
@@ -16,11 +16,11 @@ class NoBrainer::QueryRunner::RunOptions < NoBrainer::QueryRunner::Middleware
16
16
  def call(env)
17
17
  env[:options].symbolize_keys!
18
18
  if Thread.current[:nobrainer_options]
19
- env[:options] = env[:options].reverse_merge(Thread.current[:nobrainer_options])
19
+ env[:options].reverse_merge!(Thread.current[:nobrainer_options])
20
20
  end
21
21
 
22
22
  if NoBrainer::Config.durability.to_s != 'hard'
23
- env[:options] = env[:options].reverse_merge(:durability => NoBrainer::Config.durability)
23
+ env[:options].reverse_merge!(:durability => NoBrainer::Config.durability)
24
24
  end
25
25
 
26
26
  if env[:options][:db] && !env[:options][:db].is_a?(RethinkDB::RQL)
@@ -28,6 +28,8 @@ class NoBrainer::QueryRunner::RunOptions < NoBrainer::QueryRunner::Middleware
28
28
  env[:options][:db] = RethinkDB::RQL.new.db(env[:db_name])
29
29
  end
30
30
 
31
+ env[:criteria] = env[:options].delete(:criteria)
32
+
31
33
  @runner.call(env)
32
34
  end
33
35
  end
@@ -7,12 +7,22 @@ class NoBrainer::Railtie < Rails::Railtie
7
7
  config.action_dispatch.rescue_responses.merge!(
8
8
  "NoBrainer::Errors::DocumentNotFound" => :not_found,
9
9
  "NoBrainer::Errors::DocumentInvalid" => :unprocessable_entity,
10
+ "NoBrainer::Errors::InvalidType" => :bad_request,
10
11
  )
11
12
 
12
13
  rake_tasks do
13
14
  load "no_brainer/railtie/database.rake"
14
15
  end
15
16
 
17
+ console do
18
+ # Send console messages to standard error like ActiveRecord.
19
+ # Not the cleanest behavior, but if ActiveRecord does it, why not.
20
+ unless defined?(ActiveRecord)
21
+ console = ActiveSupport::Logger.new(STDERR)
22
+ Rails.logger.extend ActiveSupport::Logger.broadcast(console)
23
+ end
24
+ end
25
+
16
26
  config.after_initialize do
17
27
  NoBrainer::Config.configure unless NoBrainer::Config.configured?
18
28
 
data/lib/nobrainer.rb CHANGED
@@ -1,10 +1,6 @@
1
- if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('1.9')
2
- raise 'Please use Ruby 1.9 or later'
3
- end
4
-
5
1
  require 'active_support'
6
- %w(module/delegation module/attribute_accessors class/attribute object/blank object/inclusion
7
- object/duplicable object/try hash/keys hash/reverse_merge array/extract_options)
2
+ %w(module/delegation module/attribute_accessors class/attribute object/blank object/inclusion object/deep_dup
3
+ object/try hash/keys hash/indifferent_access hash/reverse_merge hash/deep_merge array/extract_options)
8
4
  .each { |dep| require "active_support/core_ext/#{dep}" }
9
5
 
10
6
  module NoBrainer
@@ -28,7 +24,7 @@ module NoBrainer
28
24
  end
29
25
 
30
26
  def disconnect
31
- @connection.try(:disconnect)
27
+ @connection.try(:disconnect, :noreply_wait => true)
32
28
  @connection = nil
33
29
  end
34
30
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nobrainer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicolas Viennot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-07 00:00:00.000000000 Z
11
+ date: 2014-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rethinkdb
@@ -25,25 +25,33 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.11.0.1
27
27
  - !ruby/object:Gem::Dependency
28
- name: activemodel
28
+ name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '>='
32
32
  - !ruby/object:Gem::Version
33
- version: 3.2.0
34
- - - <
35
- - !ruby/object:Gem::Version
36
- version: '5'
33
+ version: 4.0.0
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
37
  requirements:
41
38
  - - '>='
42
39
  - !ruby/object:Gem::Version
43
- version: 3.2.0
44
- - - <
40
+ version: 4.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: activemodel
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
45
46
  - !ruby/object:Gem::Version
46
- version: '5'
47
+ version: 4.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 4.0.0
47
55
  - !ruby/object:Gem::Dependency
48
56
  name: middleware
49
57
  requirement: !ruby/object:Gem::Requirement
@@ -65,75 +73,77 @@ executables: []
65
73
  extensions: []
66
74
  extra_rdoc_files: []
67
75
  files:
68
- - lib/no_brainer/document/id.rb
69
- - lib/no_brainer/document/association/belongs_to.rb
70
- - lib/no_brainer/document/association/has_many.rb
71
76
  - lib/no_brainer/document/association/has_one.rb
72
77
  - lib/no_brainer/document/association/has_one_through.rb
73
78
  - lib/no_brainer/document/association/has_many_through.rb
79
+ - lib/no_brainer/document/association/has_many.rb
74
80
  - lib/no_brainer/document/association/eager_loader.rb
75
81
  - lib/no_brainer/document/association/core.rb
76
- - lib/no_brainer/document/dynamic_attributes.rb
77
- - lib/no_brainer/document/criteria.rb
82
+ - lib/no_brainer/document/association/belongs_to.rb
78
83
  - lib/no_brainer/document/polymorphic.rb
79
84
  - lib/no_brainer/document/store_in.rb
80
85
  - lib/no_brainer/document/core.rb
81
- - lib/no_brainer/document/injection_layer.rb
82
- - lib/no_brainer/document/index.rb
83
86
  - lib/no_brainer/document/serialization.rb
84
87
  - lib/no_brainer/document/association.rb
85
- - lib/no_brainer/document/validation.rb
88
+ - lib/no_brainer/document/callbacks.rb
89
+ - lib/no_brainer/document/dynamic_attributes.rb
86
90
  - lib/no_brainer/document/timestamps.rb
87
91
  - lib/no_brainer/document/dirty.rb
88
- - lib/no_brainer/document/persistance.rb
92
+ - lib/no_brainer/document/index.rb
93
+ - lib/no_brainer/document/validation.rb
89
94
  - lib/no_brainer/document/attributes.rb
95
+ - lib/no_brainer/document/id.rb
96
+ - lib/no_brainer/document/injection_layer.rb
97
+ - lib/no_brainer/document/persistance.rb
98
+ - lib/no_brainer/document/readonly.rb
90
99
  - lib/no_brainer/document/types.rb
91
- - lib/no_brainer/query_runner/connection.rb
100
+ - lib/no_brainer/document/criteria.rb
92
101
  - lib/no_brainer/query_runner/database_on_demand.rb
93
- - lib/no_brainer/query_runner/logger.rb
94
102
  - lib/no_brainer/query_runner/table_on_demand.rb
95
103
  - lib/no_brainer/query_runner/write_error.rb
96
104
  - lib/no_brainer/query_runner/driver.rb
105
+ - lib/no_brainer/query_runner/logger.rb
97
106
  - lib/no_brainer/query_runner/missing_index.rb
98
107
  - lib/no_brainer/query_runner/run_options.rb
108
+ - lib/no_brainer/query_runner/connection.rb
99
109
  - lib/no_brainer/railtie/database.rake
100
- - lib/no_brainer/criteria/chainable/limit.rb
101
- - lib/no_brainer/criteria/chainable/order_by.rb
102
- - lib/no_brainer/criteria/chainable/scope.rb
103
- - lib/no_brainer/criteria/chainable/raw.rb
104
- - lib/no_brainer/criteria/chainable/core.rb
105
- - lib/no_brainer/criteria/chainable/where.rb
106
- - lib/no_brainer/criteria/termination/inc.rb
107
- - lib/no_brainer/criteria/termination/count.rb
108
- - lib/no_brainer/criteria/termination/first.rb
109
- - lib/no_brainer/criteria/termination/enumerable.rb
110
- - lib/no_brainer/criteria/termination/update.rb
111
- - lib/no_brainer/criteria/termination/delete.rb
112
- - lib/no_brainer/criteria/termination/eager_loading.rb
113
- - lib/no_brainer/criteria/termination/cache.rb
114
- - lib/no_brainer/decorated_symbol.rb
115
110
  - lib/no_brainer/index_manager.rb
116
111
  - lib/no_brainer/loader.rb
117
112
  - lib/no_brainer/locale/en.yml
118
- - lib/no_brainer/util.rb
119
113
  - lib/no_brainer/fork.rb
120
- - lib/no_brainer/criteria.rb
121
114
  - lib/no_brainer/connection.rb
122
115
  - lib/no_brainer/query_runner.rb
123
- - lib/no_brainer/error.rb
116
+ - lib/no_brainer/util.rb
117
+ - lib/no_brainer/decorated_symbol.rb
118
+ - lib/no_brainer/criteria/scope.rb
119
+ - lib/no_brainer/criteria/raw.rb
120
+ - lib/no_brainer/criteria/preload.rb
121
+ - lib/no_brainer/criteria/order_by.rb
122
+ - lib/no_brainer/criteria/limit.rb
123
+ - lib/no_brainer/criteria/first.rb
124
+ - lib/no_brainer/criteria/enumerable.rb
125
+ - lib/no_brainer/criteria/count.rb
126
+ - lib/no_brainer/criteria/cache.rb
127
+ - lib/no_brainer/criteria/after_find.rb
128
+ - lib/no_brainer/criteria/where.rb
129
+ - lib/no_brainer/criteria/update.rb
130
+ - lib/no_brainer/criteria/delete.rb
131
+ - lib/no_brainer/criteria/core.rb
124
132
  - lib/no_brainer/railtie.rb
125
133
  - lib/no_brainer/config.rb
126
- - lib/no_brainer/autoload.rb
127
134
  - lib/no_brainer/document.rb
135
+ - lib/no_brainer/criteria.rb
136
+ - lib/no_brainer/error.rb
137
+ - lib/no_brainer/autoload.rb
128
138
  - lib/rails/generators/nobrainer.rb
129
139
  - lib/rails/generators/nobrainer/model/model_generator.rb
130
140
  - lib/rails/generators/nobrainer/model/templates/model.rb.tt
131
141
  - lib/nobrainer.rb
132
142
  - README.md
133
- - LICENSE.md
134
- homepage: http://github.com/nviennot/nobrainer
143
+ - LICENSE
144
+ homepage: http://nobrainer.io
135
145
  licenses:
136
- - MIT
146
+ - LGPLv3
137
147
  metadata: {}
138
148
  post_install_message:
139
149
  rdoc_options: []
@@ -143,7 +153,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
143
153
  requirements:
144
154
  - - '>='
145
155
  - !ruby/object:Gem::Version
146
- version: '0'
156
+ version: 1.9.0
147
157
  required_rubygems_version: !ruby/object:Gem::Requirement
148
158
  requirements:
149
159
  - - '>='
data/LICENSE.md DELETED
@@ -1,7 +0,0 @@
1
- Copyright (C) 2012 Nicolas Viennot
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
-
5
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
-
7
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,33 +0,0 @@
1
- module NoBrainer::Criteria::Chainable::Raw
2
- extend ActiveSupport::Concern
3
-
4
- included { attr_accessor :_raw, :__after_instantiate }
5
-
6
- def raw
7
- chain { |criteria| criteria._raw = true }
8
- end
9
-
10
- def _after_instantiate(block)
11
- # Just some helper for the has_many association to set the inverses on the
12
- # related belongs_to. A bit hackish.
13
- chain { |criteria| criteria.__after_instantiate = block }
14
- end
15
-
16
- def merge!(criteria, options={})
17
- super
18
- self._raw = criteria._raw unless criteria._raw.nil?
19
- self.__after_instantiate ||= criteria.__after_instantiate
20
- self
21
- end
22
-
23
- private
24
-
25
- def raw?
26
- !!_raw
27
- end
28
-
29
- def instantiate_doc(attrs)
30
- (raw? ? attrs : klass.new_from_db(attrs))
31
- .tap { |doc| __after_instantiate.call(doc) if __after_instantiate }
32
- end
33
- end
@@ -1,50 +0,0 @@
1
- module NoBrainer::Criteria::Termination::EagerLoading
2
- extend ActiveSupport::Concern
3
-
4
- included { attr_accessor :_includes }
5
-
6
- def initialize(options={})
7
- super
8
- self._includes = []
9
- end
10
-
11
- def includes(*values)
12
- chain(:keep_cache => true) { |criteria| criteria._includes = values }
13
- end
14
-
15
- def merge!(criteria, options={})
16
- super
17
- self._includes = self._includes + criteria._includes
18
-
19
- # XXX Not pretty hack
20
- if criteria._includes.present? && cached?
21
- perform_eager_loading(@cache)
22
- end
23
- end
24
-
25
- def each(options={}, &block)
26
- return super unless should_eager_load? && !options[:no_eager_loading] && block
27
-
28
- docs = []
29
- super(options.merge(:no_eager_loading => true)) { |doc| docs << doc }
30
- perform_eager_loading(docs)
31
- docs.each(&block)
32
- self
33
- end
34
-
35
- private
36
-
37
- def should_eager_load?
38
- self._includes.present? && !raw?
39
- end
40
-
41
- def get_one(criteria)
42
- super.tap { |doc| perform_eager_loading([doc]) }
43
- end
44
-
45
- def perform_eager_loading(docs)
46
- if should_eager_load? && docs.present?
47
- NoBrainer::Document::Association::EagerLoader.new.eager_load(docs, self._includes)
48
- end
49
- end
50
- end
@@ -1,14 +0,0 @@
1
- module NoBrainer::Criteria::Termination::Inc
2
- extend ActiveSupport::Concern
3
-
4
- def inc_all(field, value=1)
5
- # TODO The useful inc() is on a model instance.
6
- # But then do we want to postpone the inc() to the next save?
7
- # It might make sense (because we don't have transactions).
8
- update_all { |doc| { field => doc[field] + value } }
9
- end
10
-
11
- def dec_all(field, value=1)
12
- inc_all(field, -value)
13
- end
14
- end
@@ -1,13 +0,0 @@
1
- module NoBrainer::Criteria::Termination::Update
2
- extend ActiveSupport::Concern
3
-
4
- def update_all(attrs={}, &block)
5
- block = proc { attrs } unless block_given?
6
- run(to_rql.update(&block))['replaced']
7
- end
8
-
9
- def replace_all(attrs={}, &block)
10
- block = proc { attrs } unless block_given?
11
- run(to_rql.replace(&block))['replaced']
12
- end
13
- end