nobrainer 0.13.0 → 0.13.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 +3 -1
 - data/lib/no_brainer/connection.rb +14 -12
 - data/lib/no_brainer/criteria/core.rb +1 -6
 - data/lib/no_brainer/criteria/preload.rb +0 -5
 - data/lib/no_brainer/criteria/where.rb +34 -7
 - data/lib/no_brainer/decorated_symbol.rb +2 -1
 - data/lib/no_brainer/document.rb +1 -1
 - data/lib/no_brainer/document/association/belongs_to.rb +9 -6
 - data/lib/no_brainer/document/attributes.rb +3 -2
 - data/lib/no_brainer/document/callbacks.rb +11 -2
 - data/lib/no_brainer/document/core.rb +10 -3
 - data/lib/no_brainer/document/dirty.rb +0 -5
 - data/lib/no_brainer/document/index.rb +6 -1
 - data/lib/no_brainer/document/persistance.rb +0 -5
 - data/lib/no_brainer/document/types.rb +54 -13
 - data/lib/no_brainer/document/uniqueness.rb +97 -0
 - data/lib/no_brainer/document/validation.rb +8 -24
 - data/lib/no_brainer/error.rb +1 -1
 - data/lib/no_brainer/index_manager.rb +4 -2
 - data/lib/no_brainer/loader.rb +1 -1
 - data/lib/no_brainer/query_runner.rb +2 -2
 - data/lib/no_brainer/query_runner/logger.rb +20 -14
 - data/lib/no_brainer/query_runner/{connection.rb → reconnect.rb} +1 -1
 - metadata +65 -64
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: b5ca498dfa914c0c0178f339485d78ba804c5b95
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: c0e0c6f35d8927bb6281f860aac769753df59b88
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: ed914e1eee020658197d596245404a2a088acbf033f5fc3a44cb490620cdc5ef110d62e4da927e7579e5e3383bc90e16dd499269a9bd8952dfa2011d3e2f2a12
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: f3204081b4ef7617706ee3c037830bdacbde973ae79e914b782b39fb41f1ec36b0125f78b427d0f21078bdae543ee426f2936ba69a1327bc36176acc6997765e
         
     | 
    
        data/lib/no_brainer/config.rb
    CHANGED
    
    | 
         @@ -4,7 +4,8 @@ module NoBrainer::Config 
     | 
|
| 
       4 
4 
     | 
    
         
             
              class << self
         
     | 
| 
       5 
5 
     | 
    
         
             
                mattr_accessor :rethinkdb_url, :logger, :warn_on_active_record,
         
     | 
| 
       6 
6 
     | 
    
         
             
                               :auto_create_databases, :auto_create_tables,
         
     | 
| 
       7 
     | 
    
         
            -
                               :max_reconnection_tries, :durability, :colorize_logger
         
     | 
| 
      
 7 
     | 
    
         
            +
                               :max_reconnection_tries, :durability, :colorize_logger,
         
     | 
| 
      
 8 
     | 
    
         
            +
                               :distributed_lock_class
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
10 
     | 
    
         
             
                def apply_defaults
         
     | 
| 
       10 
11 
     | 
    
         
             
                  self.rethinkdb_url           = default_rethinkdb_url
         
     | 
| 
         @@ -15,6 +16,7 @@ module NoBrainer::Config 
     | 
|
| 
       15 
16 
     | 
    
         
             
                  self.max_reconnection_tries  = 10
         
     | 
| 
       16 
17 
     | 
    
         
             
                  self.durability              = default_durability
         
     | 
| 
       17 
18 
     | 
    
         
             
                  self.colorize_logger         = true
         
     | 
| 
      
 19 
     | 
    
         
            +
                  self.distributed_lock_class  = nil
         
     | 
| 
       18 
20 
     | 
    
         
             
                end
         
     | 
| 
       19 
21 
     | 
    
         | 
| 
       20 
22 
     | 
    
         
             
                def reset!
         
     | 
| 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'rethinkdb'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            class NoBrainer::Connection
         
     | 
| 
       4 
     | 
    
         
            -
              attr_accessor :uri
         
     | 
| 
      
 4 
     | 
    
         
            +
              attr_accessor :uri, :parsed_uri
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
              def initialize(uri)
         
     | 
| 
       7 
7 
     | 
    
         
             
                self.uri = uri
         
     | 
| 
         @@ -9,19 +9,21 @@ class NoBrainer::Connection 
     | 
|
| 
       9 
9 
     | 
    
         
             
              end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
              def parsed_uri
         
     | 
| 
       12 
     | 
    
         
            -
                 
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
      
 12 
     | 
    
         
            +
                @parsed_uri ||= begin
         
     | 
| 
      
 13 
     | 
    
         
            +
                  require 'uri'
         
     | 
| 
      
 14 
     | 
    
         
            +
                  uri = URI.parse(self.uri)
         
     | 
| 
       14 
15 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
      
 16 
     | 
    
         
            +
                  if uri.scheme != 'rethinkdb'
         
     | 
| 
      
 17 
     | 
    
         
            +
                    raise NoBrainer::Error::Connection,
         
     | 
| 
      
 18 
     | 
    
         
            +
                      "Invalid URI. Expecting something like rethinkdb://host:port/database. Got #{uri}"
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
       19 
20 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
      
 21 
     | 
    
         
            +
                  { :auth_key => uri.password,
         
     | 
| 
      
 22 
     | 
    
         
            +
                    :host     => uri.host,
         
     | 
| 
      
 23 
     | 
    
         
            +
                    :port     => uri.port || 28015,
         
     | 
| 
      
 24 
     | 
    
         
            +
                    :db       => uri.path.gsub(/^\//, ''),
         
     | 
| 
      
 25 
     | 
    
         
            +
                  }.tap { |result| raise "No database specified in #{uri}" unless result[:db].present? }
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
       25 
27 
     | 
    
         
             
              end
         
     | 
| 
       26 
28 
     | 
    
         | 
| 
       27 
29 
     | 
    
         
             
              def raw
         
     | 
| 
         @@ -17,12 +17,7 @@ module NoBrainer::Criteria::Core 
     | 
|
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
              def inspect
         
     | 
| 
       19 
19 
     | 
    
         
             
                # rescue super because sometimes klass is not set.
         
     | 
| 
       20 
     | 
    
         
            -
                 
     | 
| 
       21 
     | 
    
         
            -
                if str =~ /Erroneous_Portion_Constructed/
         
     | 
| 
       22 
     | 
    
         
            -
                  # Need to fix the rethinkdb gem.
         
     | 
| 
       23 
     | 
    
         
            -
                  str = "the rethinkdb gem is flipping out with Erroneous_Portion_Constructed"
         
     | 
| 
       24 
     | 
    
         
            -
                end
         
     | 
| 
       25 
     | 
    
         
            -
                str
         
     | 
| 
      
 20 
     | 
    
         
            +
                to_rql.inspect rescue super
         
     | 
| 
       26 
21 
     | 
    
         
             
              end
         
     | 
| 
       27 
22 
     | 
    
         | 
| 
       28 
23 
     | 
    
         
             
              def run(rql=nil)
         
     | 
| 
         @@ -12,11 +12,6 @@ module NoBrainer::Criteria::Preload 
     | 
|
| 
       12 
12 
     | 
    
         
             
                chain(:keep_cache => true) { |criteria| criteria._preloads = values }
         
     | 
| 
       13 
13 
     | 
    
         
             
              end
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
              def includes(*values)
         
     | 
| 
       16 
     | 
    
         
            -
                NoBrainer.logger.warn "[NoBrainer] includes() is deprecated and will be removed, use preload() instead."
         
     | 
| 
       17 
     | 
    
         
            -
                preload(*values)
         
     | 
| 
       18 
     | 
    
         
            -
              end
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
15 
     | 
    
         
             
              def merge!(criteria, options={})
         
     | 
| 
       21 
16 
     | 
    
         
             
                super
         
     | 
| 
       22 
17 
     | 
    
         
             
                self._preloads = self._preloads + criteria._preloads
         
     | 
| 
         @@ -56,14 +56,15 @@ module NoBrainer::Criteria::Where 
     | 
|
| 
       56 
56 
     | 
    
         | 
| 
       57 
57 
     | 
    
         
             
              class BinaryOperator < Struct.new(:key, :op, :value, :criteria)
         
     | 
| 
       58 
58 
     | 
    
         
             
                def simplify
         
     | 
| 
      
 59 
     | 
    
         
            +
                  key = cast_key(self.key)
         
     | 
| 
       59 
60 
     | 
    
         
             
                  case op
         
     | 
| 
       60 
61 
     | 
    
         
             
                  when :in then
         
     | 
| 
       61 
62 
     | 
    
         
             
                    case value
         
     | 
| 
       62 
     | 
    
         
            -
                    when Range then BinaryOperator.new(key, :between, ( 
     | 
| 
       63 
     | 
    
         
            -
                    when Array then BinaryOperator.new(key, :in, value.map(&method(: 
     | 
| 
      
 63 
     | 
    
         
            +
                    when Range then BinaryOperator.new(key, :between, (cast_value(value.min)..cast_value(value.max)), criteria)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    when Array then BinaryOperator.new(key, :in, value.map(&method(:cast_value)).uniq, criteria)
         
     | 
| 
       64 
65 
     | 
    
         
             
                    else raise ArgumentError.new ":in takes an array/range, not #{value}"
         
     | 
| 
       65 
66 
     | 
    
         
             
                    end
         
     | 
| 
       66 
     | 
    
         
            -
                  else BinaryOperator.new(key, op,  
     | 
| 
      
 67 
     | 
    
         
            +
                  else BinaryOperator.new(key, op, cast_value(value), criteria)
         
     | 
| 
       67 
68 
     | 
    
         
             
                  end
         
     | 
| 
       68 
69 
     | 
    
         
             
                end
         
     | 
| 
       69 
70 
     | 
    
         | 
| 
         @@ -77,8 +78,33 @@ module NoBrainer::Criteria::Where 
     | 
|
| 
       77 
78 
     | 
    
         | 
| 
       78 
79 
     | 
    
         
             
                private
         
     | 
| 
       79 
80 
     | 
    
         | 
| 
       80 
     | 
    
         
            -
                def  
     | 
| 
       81 
     | 
    
         
            -
                   
     | 
| 
      
 81 
     | 
    
         
            +
                def association
         
     | 
| 
      
 82 
     | 
    
         
            +
                  # FIXME This leaks memory with dynamic attributes. The internals of type
         
     | 
| 
      
 83 
     | 
    
         
            +
                  # checking will convert the key to a symbol, and Ruby does not garbage
         
     | 
| 
      
 84 
     | 
    
         
            +
                  # collect symbols.
         
     | 
| 
      
 85 
     | 
    
         
            +
                  @association ||= [criteria.klass.association_metadata[key.to_sym]]
         
     | 
| 
      
 86 
     | 
    
         
            +
                  @association.first
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                def cast_value(value)
         
     | 
| 
      
 90 
     | 
    
         
            +
                  case association
         
     | 
| 
      
 91 
     | 
    
         
            +
                  when NoBrainer::Document::Association::BelongsTo::Metadata
         
     | 
| 
      
 92 
     | 
    
         
            +
                    target_klass = association.target_klass
         
     | 
| 
      
 93 
     | 
    
         
            +
                    opts = { :attr_name => key, :value => value, :type => target_klass}
         
     | 
| 
      
 94 
     | 
    
         
            +
                    raise NoBrainer::Error::InvalidType.new(opts) unless value.is_a?(target_klass)
         
     | 
| 
      
 95 
     | 
    
         
            +
                    value.id
         
     | 
| 
      
 96 
     | 
    
         
            +
                  else
         
     | 
| 
      
 97 
     | 
    
         
            +
                    criteria.klass.cast_user_to_db_for(key, value)
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                def cast_key(key)
         
     | 
| 
      
 102 
     | 
    
         
            +
                  case association
         
     | 
| 
      
 103 
     | 
    
         
            +
                  when NoBrainer::Document::Association::BelongsTo::Metadata
         
     | 
| 
      
 104 
     | 
    
         
            +
                    association.foreign_key
         
     | 
| 
      
 105 
     | 
    
         
            +
                  else
         
     | 
| 
      
 106 
     | 
    
         
            +
                    key
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
       82 
108 
     | 
    
         
             
                end
         
     | 
| 
       83 
109 
     | 
    
         
             
              end
         
     | 
| 
       84 
110 
     | 
    
         | 
| 
         @@ -126,8 +152,9 @@ module NoBrainer::Criteria::Where 
     | 
|
| 
       126 
152 
     | 
    
         
             
                when String, Symbol then parse_clause_stub_eq(key, value)
         
     | 
| 
       127 
153 
     | 
    
         
             
                when NoBrainer::DecoratedSymbol then
         
     | 
| 
       128 
154 
     | 
    
         
             
                  case key.modifier
         
     | 
| 
       129 
     | 
    
         
            -
                  when : 
     | 
| 
       130 
     | 
    
         
            -
                  when : 
     | 
| 
      
 155 
     | 
    
         
            +
                  when :nin then parse_clause(:not => { key.symbol.in => value })
         
     | 
| 
      
 156 
     | 
    
         
            +
                  when :ne  then parse_clause(:not => { key.symbol.eq => value })
         
     | 
| 
      
 157 
     | 
    
         
            +
                  when :eq  then parse_clause_stub_eq(key.symbol, value)
         
     | 
| 
       131 
158 
     | 
    
         
             
                  else BinaryOperator.new(key.symbol, key.modifier, value, self)
         
     | 
| 
       132 
159 
     | 
    
         
             
                  end
         
     | 
| 
       133 
160 
     | 
    
         
             
                else raise "Invalid key: #{key}"
         
     | 
| 
         @@ -1,5 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class NoBrainer::DecoratedSymbol < Struct.new(:symbol, :modifier, :args)
         
     | 
| 
       2 
     | 
    
         
            -
              MODIFIERS = { : 
     | 
| 
      
 2 
     | 
    
         
            +
              MODIFIERS = { :in => :in, :nin => :nin,
         
     | 
| 
      
 3 
     | 
    
         
            +
                            :eq => :eq, :ne => :ne, :not => :ne,
         
     | 
| 
       3 
4 
     | 
    
         
             
                            :gt => :gt, :ge => :ge, :gte => :ge,
         
     | 
| 
       4 
5 
     | 
    
         
             
                            :lt => :lt, :le => :le, :lte => :le}
         
     | 
| 
       5 
6 
     | 
    
         | 
    
        data/lib/no_brainer/document.rb
    CHANGED
    
    | 
         @@ -5,7 +5,7 @@ module NoBrainer::Document 
     | 
|
| 
       5 
5 
     | 
    
         
             
              extend NoBrainer::Autoload
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
              autoload_and_include :Core, :StoreIn, :InjectionLayer, :Attributes, :Readonly, :Validation, :Types,
         
     | 
| 
       8 
     | 
    
         
            -
                                   :Persistance, :Callbacks, :Dirty, :Id, :Association, :Serialization,
         
     | 
| 
      
 8 
     | 
    
         
            +
                                   :Persistance, :Uniqueness, :Callbacks, :Dirty, :Id, :Association, :Serialization,
         
     | 
| 
       9 
9 
     | 
    
         
             
                                   :Criteria, :Polymorphic, :Index
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
              autoload :DynamicAttributes, :Timestamps
         
     | 
| 
         @@ -30,7 +30,6 @@ class NoBrainer::Document::Association::BelongsTo 
     | 
|
| 
       30 
30 
     | 
    
         | 
| 
       31 
31 
     | 
    
         
             
                  delegate("#{foreign_key}=", :assign_foreign_key, :call_super => true)
         
     | 
| 
       32 
32 
     | 
    
         
             
                  add_callback_for(:after_validation)
         
     | 
| 
       33 
     | 
    
         
            -
                  # TODO test if we are not overstepping on another foreign_key
         
     | 
| 
       34 
33 
     | 
    
         
             
                end
         
     | 
| 
       35 
34 
     | 
    
         | 
| 
       36 
35 
     | 
    
         
             
                eager_load_with :owner_key => ->{ foreign_key }, :target_key => ->{ :id },
         
     | 
| 
         @@ -47,7 +46,7 @@ class NoBrainer::Document::Association::BelongsTo 
     | 
|
| 
       47 
46 
     | 
    
         
             
              end
         
     | 
| 
       48 
47 
     | 
    
         | 
| 
       49 
48 
     | 
    
         
             
              def read
         
     | 
| 
       50 
     | 
    
         
            -
                return  
     | 
| 
      
 49 
     | 
    
         
            +
                return target if loaded?
         
     | 
| 
       51 
50 
     | 
    
         | 
| 
       52 
51 
     | 
    
         
             
                if fk = owner.read_attribute(foreign_key)
         
     | 
| 
       53 
52 
     | 
    
         
             
                  preload(target_klass.find(fk))
         
     | 
| 
         @@ -60,8 +59,12 @@ class NoBrainer::Document::Association::BelongsTo 
     | 
|
| 
       60 
59 
     | 
    
         
             
                preload(target)
         
     | 
| 
       61 
60 
     | 
    
         
             
              end
         
     | 
| 
       62 
61 
     | 
    
         | 
| 
       63 
     | 
    
         
            -
              def preload( 
     | 
| 
       64 
     | 
    
         
            -
                @target_container = [* 
     | 
| 
      
 62 
     | 
    
         
            +
              def preload(targets)
         
     | 
| 
      
 63 
     | 
    
         
            +
                @target_container = [*targets] # the * is for the generic eager loading code
         
     | 
| 
      
 64 
     | 
    
         
            +
                target
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              def target
         
     | 
| 
       65 
68 
     | 
    
         
             
                @target_container.first
         
     | 
| 
       66 
69 
     | 
    
         
             
              end
         
     | 
| 
       67 
70 
     | 
    
         | 
| 
         @@ -70,8 +73,8 @@ class NoBrainer::Document::Association::BelongsTo 
     | 
|
| 
       70 
73 
     | 
    
         
             
              end
         
     | 
| 
       71 
74 
     | 
    
         | 
| 
       72 
75 
     | 
    
         
             
              def after_validation_callback
         
     | 
| 
       73 
     | 
    
         
            -
                if loaded? &&  
     | 
| 
       74 
     | 
    
         
            -
                  raise NoBrainer::Error:: 
     | 
| 
      
 76 
     | 
    
         
            +
                if loaded? && target && !target.persisted?
         
     | 
| 
      
 77 
     | 
    
         
            +
                  raise NoBrainer::Error::AssociationNotPersisted.new("#{target_name} must be saved first")
         
     | 
| 
       75 
78 
     | 
    
         
             
                end
         
     | 
| 
       76 
79 
     | 
    
         
             
              end
         
     | 
| 
       77 
80 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module NoBrainer::Document::Attributes
         
     | 
| 
       2 
     | 
    
         
            -
              VALID_FIELD_OPTIONS = [:index, :default, :type, : 
     | 
| 
      
 2 
     | 
    
         
            +
              VALID_FIELD_OPTIONS = [:index, :default, :type, :cast_user_to_db, :cast_db_to_user, :validates, :required, :unique, :readonly]
         
     | 
| 
       3 
3 
     | 
    
         
             
              RESERVED_FIELD_NAMES = [:index, :default, :and, :or, :selector, :associations] + NoBrainer::DecoratedSymbol::MODIFIERS.keys
         
     | 
| 
       4 
4 
     | 
    
         
             
              extend ActiveSupport::Concern
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
         @@ -43,13 +43,14 @@ module NoBrainer::Document::Attributes 
     | 
|
| 
       43 
43 
     | 
    
         
             
                @_attributes.clear if options[:pristine]
         
     | 
| 
       44 
44 
     | 
    
         
             
                if options[:from_db]
         
     | 
| 
       45 
45 
     | 
    
         
             
                  @_attributes.merge!(attrs)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  clear_dirtiness
         
     | 
| 
       46 
47 
     | 
    
         
             
                else
         
     | 
| 
      
 48 
     | 
    
         
            +
                  clear_dirtiness if options[:pristine]
         
     | 
| 
       47 
49 
     | 
    
         
             
                  attrs.each { |k,v| self.write_attribute(k,v) }
         
     | 
| 
       48 
50 
     | 
    
         
             
                end
         
     | 
| 
       49 
51 
     | 
    
         
             
                assign_defaults if options[:pristine]
         
     | 
| 
       50 
52 
     | 
    
         
             
                self
         
     | 
| 
       51 
53 
     | 
    
         
             
              end
         
     | 
| 
       52 
     | 
    
         
            -
              def attributes=(*args); assign_attributes(*args); end
         
     | 
| 
       53 
54 
     | 
    
         | 
| 
       54 
55 
     | 
    
         
             
              def inspectable_attributes
         
     | 
| 
       55 
56 
     | 
    
         
             
                # TODO test that thing
         
     | 
| 
         @@ -1,10 +1,19 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module NoBrainer::Document::Callbacks
         
     | 
| 
       2 
2 
     | 
    
         
             
              extend ActiveSupport::Concern
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
      
 4 
     | 
    
         
            +
              def self.terminator
         
     | 
| 
      
 5 
     | 
    
         
            +
                if Gem.loaded_specs['activesupport'].version.release >= Gem::Version.new('4.1')
         
     | 
| 
      
 6 
     | 
    
         
            +
                  proc { false }
         
     | 
| 
      
 7 
     | 
    
         
            +
                else
         
     | 
| 
      
 8 
     | 
    
         
            +
                  'false'
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       4 
12 
     | 
    
         
             
              included do
         
     | 
| 
       5 
13 
     | 
    
         
             
                extend ActiveModel::Callbacks
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                define_model_callbacks : 
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                define_model_callbacks :initialize, :create, :update, :save, :destroy, :terminator => NoBrainer::Document::Callbacks.terminator
         
     | 
| 
      
 16 
     | 
    
         
            +
                define_model_callbacks :find, :only => [:after], :terminator => NoBrainer::Document::Callbacks.terminator
         
     | 
| 
       8 
17 
     | 
    
         
             
              end
         
     | 
| 
       9 
18 
     | 
    
         | 
| 
       10 
19 
     | 
    
         
             
              def initialize(*args, &block)
         
     | 
| 
         @@ -1,8 +1,15 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module NoBrainer::Document::Core
         
     | 
| 
       2 
2 
     | 
    
         
             
              extend ActiveSupport::Concern
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
              singleton_class. 
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
      
 4 
     | 
    
         
            +
              singleton_class.class_eval do
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_accessor :_all
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def all
         
     | 
| 
      
 8 
     | 
    
         
            +
                  Rails.application.eager_load! if defined?(Rails)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @_all
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
              self._all = []
         
     | 
| 
       6 
13 
     | 
    
         | 
| 
       7 
14 
     | 
    
         
             
              # TODO This assume the primary key is id.
         
     | 
| 
       8 
15 
     | 
    
         
             
              # RethinkDB can have a custom primary key. careful.
         
     | 
| 
         @@ -13,6 +20,6 @@ module NoBrainer::Document::Core 
     | 
|
| 
       13 
20 
     | 
    
         
             
                extend ActiveModel::Naming
         
     | 
| 
       14 
21 
     | 
    
         
             
                extend ActiveModel::Translation
         
     | 
| 
       15 
22 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                NoBrainer::Document::Core. 
     | 
| 
      
 23 
     | 
    
         
            +
                NoBrainer::Document::Core._all << self
         
     | 
| 
       17 
24 
     | 
    
         
             
              end
         
     | 
| 
       18 
25 
     | 
    
         
             
            end
         
     | 
| 
         @@ -6,11 +6,6 @@ module NoBrainer::Document::Dirty 
     | 
|
| 
       6 
6 
     | 
    
         
             
              # things like undefined -> nil. Going through the getters will
         
     | 
| 
       7 
7 
     | 
    
         
             
              # not give us that.
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
              def assign_attributes(attrs, options={})
         
     | 
| 
       10 
     | 
    
         
            -
                clear_dirtiness if options[:pristine]
         
     | 
| 
       11 
     | 
    
         
            -
                super
         
     | 
| 
       12 
     | 
    
         
            -
              end
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
9 
     | 
    
         
             
              def _create(*args)
         
     | 
| 
       15 
10 
     | 
    
         
             
                super.tap { clear_dirtiness }
         
     | 
| 
       16 
11 
     | 
    
         
             
              end
         
     | 
| 
         @@ -68,7 +68,7 @@ module NoBrainer::Document::Index 
     | 
|
| 
       68 
68 
     | 
    
         
             
                  end
         
     | 
| 
       69 
69 
     | 
    
         | 
| 
       70 
70 
     | 
    
         
             
                  NoBrainer.run(self.rql_table.index_create(index_name, index_args[:options], &index_proc))
         
     | 
| 
       71 
     | 
    
         
            -
                   
     | 
| 
      
 71 
     | 
    
         
            +
                  wait_for_index(index_name) unless options[:wait] == false
         
     | 
| 
       72 
72 
     | 
    
         
             
                  STDERR.puts "Created index #{self}.#{index_name}" if options[:verbose]
         
     | 
| 
       73 
73 
     | 
    
         
             
                end
         
     | 
| 
       74 
74 
     | 
    
         | 
| 
         @@ -90,5 +90,10 @@ module NoBrainer::Document::Index 
     | 
|
| 
       90 
90 
     | 
    
         
             
                  end
         
     | 
| 
       91 
91 
     | 
    
         
             
                end
         
     | 
| 
       92 
92 
     | 
    
         
             
                alias_method :update_indexes, :perform_update_indexes
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                def wait_for_index(index_name=nil, options={})
         
     | 
| 
      
 95 
     | 
    
         
            +
                  args = [index_name].compact
         
     | 
| 
      
 96 
     | 
    
         
            +
                  NoBrainer.run(self.rql_table.index_wait(*args))
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
       93 
98 
     | 
    
         
             
              end
         
     | 
| 
       94 
99 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,11 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module NoBrainer::Document::Persistance
         
     | 
| 
       2 
2 
     | 
    
         
             
              extend ActiveSupport::Concern
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
              included do
         
     | 
| 
       5 
     | 
    
         
            -
                extend ActiveModel::Callbacks
         
     | 
| 
       6 
     | 
    
         
            -
                define_model_callbacks :create, :update, :save, :destroy, :terminator => 'false'
         
     | 
| 
       7 
     | 
    
         
            -
              end
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
4 
     | 
    
         
             
              def _initialize(attrs={}, options={})
         
     | 
| 
       10 
5 
     | 
    
         
             
                @new_record = !options[:from_db]
         
     | 
| 
       11 
6 
     | 
    
         
             
                super
         
     | 
| 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module NoBrainer::Document::Types
         
     | 
| 
       2 
2 
     | 
    
         
             
              extend ActiveSupport::Concern
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
              module  
     | 
| 
      
 4 
     | 
    
         
            +
              module CastUserToDB
         
     | 
| 
       5 
5 
     | 
    
         
             
                extend self
         
     | 
| 
       6 
6 
     | 
    
         
             
                InvalidType = NoBrainer::Error::InvalidType
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
         @@ -60,14 +60,23 @@ module NoBrainer::Document::Types 
     | 
|
| 
       60 
60 
     | 
    
         
             
                end
         
     | 
| 
       61 
61 
     | 
    
         | 
| 
       62 
62 
     | 
    
         
             
                def lookup(type)
         
     | 
| 
       63 
     | 
    
         
            -
                   
     | 
| 
      
 63 
     | 
    
         
            +
                  public_method(type.to_s)
         
     | 
| 
       64 
64 
     | 
    
         
             
                rescue NameError
         
     | 
| 
       65 
65 
     | 
    
         
             
                  proc { raise InvalidType }
         
     | 
| 
       66 
66 
     | 
    
         
             
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
       67 
68 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
      
 69 
     | 
    
         
            +
              module CastDBToUser
         
     | 
| 
      
 70 
     | 
    
         
            +
                extend self
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                def Symbol(value)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  value.to_sym rescue value
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                def lookup(type)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  public_method(type.to_s)
         
     | 
| 
      
 78 
     | 
    
         
            +
                rescue NameError
         
     | 
| 
      
 79 
     | 
    
         
            +
                  nil
         
     | 
| 
       71 
80 
     | 
    
         
             
                end
         
     | 
| 
       72 
81 
     | 
    
         
             
              end
         
     | 
| 
       73 
82 
     | 
    
         | 
| 
         @@ -82,6 +91,11 @@ module NoBrainer::Document::Types 
     | 
|
| 
       82 
91 
     | 
    
         
             
                  end
         
     | 
| 
       83 
92 
     | 
    
         
             
                end
         
     | 
| 
       84 
93 
     | 
    
         
             
                before_validation :add_type_errors
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                # Fast access for db->user cast methods for performance when reading from
         
     | 
| 
      
 96 
     | 
    
         
            +
                # the database.
         
     | 
| 
      
 97 
     | 
    
         
            +
                singleton_class.send(:attr_accessor, :cast_db_to_user_fields)
         
     | 
| 
      
 98 
     | 
    
         
            +
                self.cast_db_to_user_fields = Set.new
         
     | 
| 
       85 
99 
     | 
    
         
             
              end
         
     | 
| 
       86 
100 
     | 
    
         | 
| 
       87 
101 
     | 
    
         
             
              def add_type_errors
         
     | 
| 
         @@ -91,12 +105,27 @@ module NoBrainer::Document::Types 
     | 
|
| 
       91 
105 
     | 
    
         
             
                end
         
     | 
| 
       92 
106 
     | 
    
         
             
              end
         
     | 
| 
       93 
107 
     | 
    
         | 
| 
      
 108 
     | 
    
         
            +
              def assign_attributes(attrs, options={})
         
     | 
| 
      
 109 
     | 
    
         
            +
                super
         
     | 
| 
      
 110 
     | 
    
         
            +
                if options[:from_db]
         
     | 
| 
      
 111 
     | 
    
         
            +
                  self.class.cast_db_to_user_fields.each do |attr|
         
     | 
| 
      
 112 
     | 
    
         
            +
                    field_def = self.class.fields[attr]
         
     | 
| 
      
 113 
     | 
    
         
            +
                    type = field_def[:type]
         
     | 
| 
      
 114 
     | 
    
         
            +
                    value = @_attributes[attr.to_s]
         
     | 
| 
      
 115 
     | 
    
         
            +
                    unless value.nil? || value.is_a?(type)
         
     | 
| 
      
 116 
     | 
    
         
            +
                      @_attributes[attr.to_s] = field_def[:cast_db_to_user].call(value)
         
     | 
| 
      
 117 
     | 
    
         
            +
                    end
         
     | 
| 
      
 118 
     | 
    
         
            +
                  end
         
     | 
| 
      
 119 
     | 
    
         
            +
                end
         
     | 
| 
      
 120 
     | 
    
         
            +
              end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
       94 
122 
     | 
    
         
             
              module ClassMethods
         
     | 
| 
       95 
     | 
    
         
            -
                def  
     | 
| 
       96 
     | 
    
         
            -
                   
     | 
| 
       97 
     | 
    
         
            -
                   
     | 
| 
       98 
     | 
    
         
            -
                   
     | 
| 
       99 
     | 
    
         
            -
                   
     | 
| 
      
 123 
     | 
    
         
            +
                def cast_user_to_db_for(attr, value)
         
     | 
| 
      
 124 
     | 
    
         
            +
                  field_def = fields[attr.to_sym]
         
     | 
| 
      
 125 
     | 
    
         
            +
                  return value if !field_def
         
     | 
| 
      
 126 
     | 
    
         
            +
                  type = field_def[:type]
         
     | 
| 
      
 127 
     | 
    
         
            +
                  return value if value.nil? || type.nil? || value.is_a?(type)
         
     | 
| 
      
 128 
     | 
    
         
            +
                  field_def[:cast_user_to_db].call(value)
         
     | 
| 
       100 
129 
     | 
    
         
             
                rescue NoBrainer::Error::InvalidType => error
         
     | 
| 
       101 
130 
     | 
    
         
             
                  error.type = field_def[:type]
         
     | 
| 
       102 
131 
     | 
    
         
             
                  error.value = value
         
     | 
| 
         @@ -104,13 +133,24 @@ module NoBrainer::Document::Types 
     | 
|
| 
       104 
133 
     | 
    
         
             
                  raise error
         
     | 
| 
       105 
134 
     | 
    
         
             
                end
         
     | 
| 
       106 
135 
     | 
    
         | 
| 
      
 136 
     | 
    
         
            +
                def inherited(subclass)
         
     | 
| 
      
 137 
     | 
    
         
            +
                  super
         
     | 
| 
      
 138 
     | 
    
         
            +
                  subclass.cast_db_to_user_fields = self.cast_db_to_user_fields.dup
         
     | 
| 
      
 139 
     | 
    
         
            +
                end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
       107 
141 
     | 
    
         
             
                def _field(attr, options={})
         
     | 
| 
       108 
142 
     | 
    
         
             
                  super
         
     | 
| 
       109 
143 
     | 
    
         | 
| 
      
 144 
     | 
    
         
            +
                  if options[:cast_db_to_user]
         
     | 
| 
      
 145 
     | 
    
         
            +
                    ([self] + descendants).each do |klass|
         
     | 
| 
      
 146 
     | 
    
         
            +
                      klass.cast_db_to_user_fields << attr
         
     | 
| 
      
 147 
     | 
    
         
            +
                    end
         
     | 
| 
      
 148 
     | 
    
         
            +
                  end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
       110 
150 
     | 
    
         
             
                  inject_in_layer :types do
         
     | 
| 
       111 
151 
     | 
    
         
             
                    define_method("#{attr}=") do |value|
         
     | 
| 
       112 
152 
     | 
    
         
             
                      begin
         
     | 
| 
       113 
     | 
    
         
            -
                        value = self.class. 
     | 
| 
      
 153 
     | 
    
         
            +
                        value = self.class.cast_user_to_db_for(attr, value)
         
     | 
| 
       114 
154 
     | 
    
         
             
                        @pending_type_errors.try(:delete, attr)
         
     | 
| 
       115 
155 
     | 
    
         
             
                      rescue NoBrainer::Error::InvalidType => error
         
     | 
| 
       116 
156 
     | 
    
         
             
                        @pending_type_errors ||= {}
         
     | 
| 
         @@ -125,8 +165,9 @@ module NoBrainer::Document::Types 
     | 
|
| 
       125 
165 
     | 
    
         | 
| 
       126 
166 
     | 
    
         
             
                def field(attr, options={})
         
     | 
| 
       127 
167 
     | 
    
         
             
                  if options[:type]
         
     | 
| 
       128 
     | 
    
         
            -
                     
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
      
 168 
     | 
    
         
            +
                    options = options.merge(
         
     | 
| 
      
 169 
     | 
    
         
            +
                      :cast_user_to_db => NoBrainer::Document::Types::CastUserToDB.lookup(options[:type]),
         
     | 
| 
      
 170 
     | 
    
         
            +
                      :cast_db_to_user => NoBrainer::Document::Types::CastDBToUser.lookup(options[:type]))
         
     | 
| 
       130 
171 
     | 
    
         
             
                  end
         
     | 
| 
       131 
172 
     | 
    
         
             
                  super
         
     | 
| 
       132 
173 
     | 
    
         
             
                end
         
     | 
| 
         @@ -0,0 +1,97 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module NoBrainer::Document::Uniqueness
         
     | 
| 
      
 2 
     | 
    
         
            +
              extend ActiveSupport::Concern
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              def _create(options={})
         
     | 
| 
      
 5 
     | 
    
         
            +
                lock_unique_fields
         
     | 
| 
      
 6 
     | 
    
         
            +
                super
         
     | 
| 
      
 7 
     | 
    
         
            +
              ensure
         
     | 
| 
      
 8 
     | 
    
         
            +
                unlock_unique_fields
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              def _update_only_changed_attrs(options={})
         
     | 
| 
      
 12 
     | 
    
         
            +
                lock_unique_fields
         
     | 
| 
      
 13 
     | 
    
         
            +
                super
         
     | 
| 
      
 14 
     | 
    
         
            +
              ensure
         
     | 
| 
      
 15 
     | 
    
         
            +
                unlock_unique_fields
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              def _lock_key_from_field(field)
         
     | 
| 
      
 19 
     | 
    
         
            +
                value = read_attribute(field).to_s
         
     | 
| 
      
 20 
     | 
    
         
            +
                ['nobrainer', self.class.database_name || NoBrainer.connection.parsed_uri[:db],
         
     | 
| 
      
 21 
     | 
    
         
            +
                 self.class.table_name, field, value.empty? ? 'nil' : value].join(':')
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              def lock_unique_fields
         
     | 
| 
      
 25 
     | 
    
         
            +
                return unless NoBrainer::Config.distributed_lock_class && !self.class.unique_validators.empty?
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                self.class.unique_validators
         
     | 
| 
      
 28 
     | 
    
         
            +
                  .map { |validator| validator.attributes.map { |attr| [attr, validator] } }
         
     | 
| 
      
 29 
     | 
    
         
            +
                  .flatten(1)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  .select { |f, validator| validator.should_validate_uniquess_of?(self, f) }
         
     | 
| 
      
 31 
     | 
    
         
            +
                  .map { |f, options| _lock_key_from_field(f) }
         
     | 
| 
      
 32 
     | 
    
         
            +
                  .sort
         
     | 
| 
      
 33 
     | 
    
         
            +
                  .uniq
         
     | 
| 
      
 34 
     | 
    
         
            +
                  .each do |key|
         
     | 
| 
      
 35 
     | 
    
         
            +
                    lock = NoBrainer::Config.distributed_lock_class.new(key)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    lock.lock
         
     | 
| 
      
 37 
     | 
    
         
            +
                    @locked_unique_fields ||= []
         
     | 
| 
      
 38 
     | 
    
         
            +
                    @locked_unique_fields << lock
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              def unlock_unique_fields
         
     | 
| 
      
 43 
     | 
    
         
            +
                return unless @locked_unique_fields
         
     | 
| 
      
 44 
     | 
    
         
            +
                @locked_unique_fields.pop.unlock until @locked_unique_fields.empty?
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              included do
         
     | 
| 
      
 48 
     | 
    
         
            +
                singleton_class.send(:attr_accessor, :unique_validators)
         
     | 
| 
      
 49 
     | 
    
         
            +
                self.unique_validators = []
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              module ClassMethods
         
     | 
| 
      
 53 
     | 
    
         
            +
                def validates_uniqueness_of(*attr_names)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  validates_with UniquenessValidator, _merge_attributes(attr_names)
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                def inherited(subclass)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  super
         
     | 
| 
      
 59 
     | 
    
         
            +
                  subclass.unique_validators = self.unique_validators.dup
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              class UniquenessValidator < ActiveModel::EachValidator
         
     | 
| 
      
 65 
     | 
    
         
            +
                attr_accessor :scope
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                def setup(klass)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  self.scope = [*options[:scope]]
         
     | 
| 
      
 69 
     | 
    
         
            +
                  ([klass] + klass.descendants).each do |_klass|
         
     | 
| 
      
 70 
     | 
    
         
            +
                    _klass.unique_validators << self
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                def should_validate_uniquess_of?(doc, field)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  (scope + [field]).any? { |f| doc.__send__("#{f}_changed?") }
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                def validate_each(doc, attr, value)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  return true unless should_validate_uniquess_of?(doc, attr)
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  criteria = doc.root_class.unscoped.where(attr => value)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  criteria = apply_scopes(criteria, doc)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  criteria = exclude_doc(criteria, doc) if doc.persisted?
         
     | 
| 
      
 84 
     | 
    
         
            +
                  is_unique = criteria.count == 0
         
     | 
| 
      
 85 
     | 
    
         
            +
                  doc.errors.add(attr, :taken, options.except(:scope).merge(:value => value)) unless is_unique
         
     | 
| 
      
 86 
     | 
    
         
            +
                  is_unique
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                def apply_scopes(criteria, doc)
         
     | 
| 
      
 90 
     | 
    
         
            +
                  criteria.where(scope.map { |k| {k => doc.read_attribute(k)} })
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                def exclude_doc(criteria, doc)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  criteria.where(:id.ne => doc.id)
         
     | 
| 
      
 95 
     | 
    
         
            +
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
              end
         
     | 
| 
      
 97 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -3,6 +3,12 @@ module NoBrainer::Document::Validation 
     | 
|
| 
       3 
3 
     | 
    
         
             
              include ActiveModel::Validations
         
     | 
| 
       4 
4 
     | 
    
         
             
              include ActiveModel::Validations::Callbacks
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
      
 6 
     | 
    
         
            +
              included do
         
     | 
| 
      
 7 
     | 
    
         
            +
                # We don't want before_validation returning false to halt the chain.
         
     | 
| 
      
 8 
     | 
    
         
            +
                define_callbacks :validation, :skip_after_callbacks_if_terminated => true, :scope => [:kind, :name],
         
     | 
| 
      
 9 
     | 
    
         
            +
                                 :terminator => NoBrainer::Document::Callbacks.terminator
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       6 
12 
     | 
    
         
             
              def valid?(context=nil)
         
     | 
| 
       7 
13 
     | 
    
         
             
                super(context || (new_record? ? :create : :update))
         
     | 
| 
       8 
14 
     | 
    
         
             
              end
         
     | 
| 
         @@ -10,31 +16,9 @@ module NoBrainer::Document::Validation 
     | 
|
| 
       10 
16 
     | 
    
         
             
              module ClassMethods
         
     | 
| 
       11 
17 
     | 
    
         
             
                def _field(attr, options={})
         
     | 
| 
       12 
18 
     | 
    
         
             
                  super
         
     | 
| 
       13 
     | 
    
         
            -
                  validates(attr, { :presence =>  
     | 
| 
      
 19 
     | 
    
         
            +
                  validates(attr, { :presence => options[:required] }) if options.has_key?(:required)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  validates(attr, { :uniqueness => options[:unique] }) if options.has_key?(:unique)
         
     | 
| 
       14 
21 
     | 
    
         
             
                  validates(attr, options[:validates]) if options[:validates]
         
     | 
| 
       15 
22 
     | 
    
         
             
                end
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                def validates_uniqueness_of(*attr_names)
         
     | 
| 
       18 
     | 
    
         
            -
                  validates_with UniquenessValidator, _merge_attributes(attr_names)
         
     | 
| 
       19 
     | 
    
         
            -
                end
         
     | 
| 
       20 
     | 
    
         
            -
              end
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
              class UniquenessValidator < ActiveModel::EachValidator
         
     | 
| 
       23 
     | 
    
         
            -
                def validate_each(doc, attr, value)
         
     | 
| 
       24 
     | 
    
         
            -
                  criteria = doc.root_class.unscoped.where(attr => value)
         
     | 
| 
       25 
     | 
    
         
            -
                  criteria = apply_scopes(criteria, doc)
         
     | 
| 
       26 
     | 
    
         
            -
                  criteria = exclude_doc(criteria, doc) if doc.persisted?
         
     | 
| 
       27 
     | 
    
         
            -
                  is_unique = criteria.count == 0
         
     | 
| 
       28 
     | 
    
         
            -
                  doc.errors.add(attr, :taken, options.except(:scope).merge(:value => value)) unless is_unique
         
     | 
| 
       29 
     | 
    
         
            -
                  is_unique
         
     | 
| 
       30 
     | 
    
         
            -
                end
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                def apply_scopes(criteria, doc)
         
     | 
| 
       33 
     | 
    
         
            -
                  criteria.where([*options[:scope]].map { |k| {k => doc.read_attribute(k)} })
         
     | 
| 
       34 
     | 
    
         
            -
                end
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
                def exclude_doc(criteria, doc)
         
     | 
| 
       37 
     | 
    
         
            -
                  criteria.where(:id.ne => doc.id)
         
     | 
| 
       38 
     | 
    
         
            -
                end
         
     | 
| 
       39 
23 
     | 
    
         
             
              end
         
     | 
| 
       40 
24 
     | 
    
         
             
            end
         
     | 
    
        data/lib/no_brainer/error.rb
    CHANGED
    
    | 
         @@ -6,7 +6,7 @@ module NoBrainer::Error 
     | 
|
| 
       6 
6 
     | 
    
         
             
              class CannotUseIndex      < RuntimeError; end
         
     | 
| 
       7 
7 
     | 
    
         
             
              class MissingIndex        < RuntimeError; end
         
     | 
| 
       8 
8 
     | 
    
         
             
              class InvalidType         < RuntimeError; end
         
     | 
| 
       9 
     | 
    
         
            -
              class  
     | 
| 
      
 9 
     | 
    
         
            +
              class AssociationNotPersisted < RuntimeError; end
         
     | 
| 
       10 
10 
     | 
    
         
             
              class ReadonlyField       < RuntimeError; end
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
              class DocumentInvalid < RuntimeError
         
     | 
| 
         @@ -1,6 +1,8 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module NoBrainer::IndexManager
         
     | 
| 
       2 
2 
     | 
    
         
             
              def self.update_indexes(options={})
         
     | 
| 
       3 
     | 
    
         
            -
                 
     | 
| 
       4 
     | 
    
         
            -
                 
     | 
| 
      
 3 
     | 
    
         
            +
                NoBrainer::Document.all.each { |model| model.perform_update_indexes(options.merge(:wait => false)) }
         
     | 
| 
      
 4 
     | 
    
         
            +
                unless options[:wait] == false
         
     | 
| 
      
 5 
     | 
    
         
            +
                  NoBrainer::Document.all.each { |model| model.wait_for_index(nil) }
         
     | 
| 
      
 6 
     | 
    
         
            +
                end
         
     | 
| 
       5 
7 
     | 
    
         
             
              end
         
     | 
| 
       6 
8 
     | 
    
         
             
            end
         
     | 
    
        data/lib/no_brainer/loader.rb
    CHANGED
    
    
| 
         @@ -11,7 +11,7 @@ module NoBrainer::QueryRunner 
     | 
|
| 
       11 
11 
     | 
    
         
             
              end
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
              autoload :Driver, :DatabaseOnDemand, :TableOnDemand, :WriteError,
         
     | 
| 
       14 
     | 
    
         
            -
                       : 
     | 
| 
      
 14 
     | 
    
         
            +
                       :Reconnect, :Selection, :RunOptions, :Logger, :MissingIndex
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
              class << self
         
     | 
| 
       17 
17 
     | 
    
         
             
                attr_accessor :stack
         
     | 
| 
         @@ -27,12 +27,12 @@ module NoBrainer::QueryRunner 
     | 
|
| 
       27 
27 
     | 
    
         
             
              # thread-safe, since require() is ran with a mutex.
         
     | 
| 
       28 
28 
     | 
    
         
             
              self.stack = ::Middleware::Builder.new do
         
     | 
| 
       29 
29 
     | 
    
         
             
                use RunOptions
         
     | 
| 
       30 
     | 
    
         
            -
                use Connection
         
     | 
| 
       31 
30 
     | 
    
         
             
                use WriteError
         
     | 
| 
       32 
31 
     | 
    
         
             
                use MissingIndex
         
     | 
| 
       33 
32 
     | 
    
         
             
                use DatabaseOnDemand
         
     | 
| 
       34 
33 
     | 
    
         
             
                use TableOnDemand
         
     | 
| 
       35 
34 
     | 
    
         
             
                use Logger
         
     | 
| 
      
 35 
     | 
    
         
            +
                use Reconnect
         
     | 
| 
       36 
36 
     | 
    
         
             
                use Driver
         
     | 
| 
       37 
37 
     | 
    
         
             
              end
         
     | 
| 
       38 
38 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,29 +1,35 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class NoBrainer::QueryRunner::Logger < NoBrainer::QueryRunner::Middleware
         
     | 
| 
       2 
2 
     | 
    
         
             
              def call(env)
         
     | 
| 
       3 
3 
     | 
    
         
             
                start_time = Time.now
         
     | 
| 
       4 
     | 
    
         
            -
                 
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
      
 4 
     | 
    
         
            +
                @runner.call(env).tap { log_query(env, start_time) }
         
     | 
| 
      
 5 
     | 
    
         
            +
              rescue Exception => e
         
     | 
| 
      
 6 
     | 
    
         
            +
                log_query(env, start_time, e) rescue nil
         
     | 
| 
      
 7 
     | 
    
         
            +
                raise e
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
      
 10 
     | 
    
         
            +
              private
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              def log_query(env, start_time, exception=nil)
         
     | 
| 
      
 13 
     | 
    
         
            +
                return unless NoBrainer.logger.debug?
         
     | 
| 
       13 
14 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
      
 15 
     | 
    
         
            +
                duration = Time.now - start_time
         
     | 
| 
      
 16 
     | 
    
         
            +
                msg = env[:query].inspect.gsub(/\n/, '').gsub(/ +/, ' ')
         
     | 
| 
       16 
17 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
      
 18 
     | 
    
         
            +
                msg = "(#{env[:db_name]}) #{msg}" if env[:db_name]
         
     | 
| 
      
 19 
     | 
    
         
            +
                msg = "[#{(duration * 1000.0).round(1)}ms] #{msg}"
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                if NoBrainer::Config.colorize_logger
         
     | 
| 
      
 22 
     | 
    
         
            +
                  if exception
         
     | 
| 
      
 23 
     | 
    
         
            +
                    msg = "#{msg} \e[0;31m#{exception.class} #{exception.message.split("\n").first}\e[0m"
         
     | 
| 
      
 24 
     | 
    
         
            +
                  else
         
     | 
| 
       18 
25 
     | 
    
         
             
                    case NoBrainer::Util.rql_type(env[:query])
         
     | 
| 
       19 
26 
     | 
    
         
             
                    when :write      then msg = "\e[1;31m#{msg}\e[0m" # red
         
     | 
| 
       20 
27 
     | 
    
         
             
                    when :read       then msg = "\e[1;32m#{msg}\e[0m" # green
         
     | 
| 
       21 
28 
     | 
    
         
             
                    when :management then msg = "\e[1;33m#{msg}\e[0m" # yellow
         
     | 
| 
       22 
29 
     | 
    
         
             
                    end
         
     | 
| 
       23 
30 
     | 
    
         
             
                  end
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                  NoBrainer.logger.debug(msg)
         
     | 
| 
       26 
31 
     | 
    
         
             
                end
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                NoBrainer.logger.debug(msg)
         
     | 
| 
       28 
34 
     | 
    
         
             
              end
         
     | 
| 
       29 
35 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,69 +1,69 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: nobrainer
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.13. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.13.1
         
     | 
| 
       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- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2014-03-31 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rethinkdb
         
     | 
| 
       15 
15 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       16 
16 
     | 
    
         
             
                requirements:
         
     | 
| 
       17 
     | 
    
         
            -
                - - ~>
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
       18 
18 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       19 
     | 
    
         
            -
                    version: 1. 
     | 
| 
      
 19 
     | 
    
         
            +
                    version: 1.12.0.1
         
     | 
| 
       20 
20 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       21 
21 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       22 
22 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       23 
23 
     | 
    
         
             
                requirements:
         
     | 
| 
       24 
     | 
    
         
            -
                - - ~>
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
       25 
25 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       26 
     | 
    
         
            -
                    version: 1. 
     | 
| 
      
 26 
     | 
    
         
            +
                    version: 1.12.0.1
         
     | 
| 
       27 
27 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       28 
28 
     | 
    
         
             
              name: activesupport
         
     | 
| 
       29 
29 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       30 
30 
     | 
    
         
             
                requirements:
         
     | 
| 
       31 
     | 
    
         
            -
                - -  
     | 
| 
      
 31 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       32 
32 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       33 
33 
     | 
    
         
             
                    version: 4.0.0
         
     | 
| 
       34 
34 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       35 
35 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       36 
36 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       37 
37 
     | 
    
         
             
                requirements:
         
     | 
| 
       38 
     | 
    
         
            -
                - -  
     | 
| 
      
 38 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       39 
39 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       40 
40 
     | 
    
         
             
                    version: 4.0.0
         
     | 
| 
       41 
41 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       42 
42 
     | 
    
         
             
              name: activemodel
         
     | 
| 
       43 
43 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       44 
44 
     | 
    
         
             
                requirements:
         
     | 
| 
       45 
     | 
    
         
            -
                - -  
     | 
| 
      
 45 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       46 
46 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       47 
47 
     | 
    
         
             
                    version: 4.0.0
         
     | 
| 
       48 
48 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       49 
49 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       50 
50 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       51 
51 
     | 
    
         
             
                requirements:
         
     | 
| 
       52 
     | 
    
         
            -
                - -  
     | 
| 
      
 52 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       53 
53 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       54 
54 
     | 
    
         
             
                    version: 4.0.0
         
     | 
| 
       55 
55 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       56 
56 
     | 
    
         
             
              name: middleware
         
     | 
| 
       57 
57 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       58 
58 
     | 
    
         
             
                requirements:
         
     | 
| 
       59 
     | 
    
         
            -
                - - ~>
         
     | 
| 
      
 59 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
       60 
60 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       61 
61 
     | 
    
         
             
                    version: 0.1.0
         
     | 
| 
       62 
62 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       63 
63 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       64 
64 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       65 
65 
     | 
    
         
             
                requirements:
         
     | 
| 
       66 
     | 
    
         
            -
                - - ~>
         
     | 
| 
      
 66 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
       67 
67 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       68 
68 
     | 
    
         
             
                    version: 0.1.0
         
     | 
| 
       69 
69 
     | 
    
         
             
            description: ORM for RethinkDB
         
     | 
| 
         @@ -73,74 +73,75 @@ executables: [] 
     | 
|
| 
       73 
73 
     | 
    
         
             
            extensions: []
         
     | 
| 
       74 
74 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
       75 
75 
     | 
    
         
             
            files:
         
     | 
| 
      
 76 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
      
 77 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 78 
     | 
    
         
            +
            - lib/no_brainer/autoload.rb
         
     | 
| 
      
 79 
     | 
    
         
            +
            - lib/no_brainer/config.rb
         
     | 
| 
      
 80 
     | 
    
         
            +
            - lib/no_brainer/connection.rb
         
     | 
| 
      
 81 
     | 
    
         
            +
            - lib/no_brainer/criteria.rb
         
     | 
| 
      
 82 
     | 
    
         
            +
            - lib/no_brainer/criteria/after_find.rb
         
     | 
| 
      
 83 
     | 
    
         
            +
            - lib/no_brainer/criteria/cache.rb
         
     | 
| 
      
 84 
     | 
    
         
            +
            - lib/no_brainer/criteria/core.rb
         
     | 
| 
      
 85 
     | 
    
         
            +
            - lib/no_brainer/criteria/count.rb
         
     | 
| 
      
 86 
     | 
    
         
            +
            - lib/no_brainer/criteria/delete.rb
         
     | 
| 
      
 87 
     | 
    
         
            +
            - lib/no_brainer/criteria/enumerable.rb
         
     | 
| 
      
 88 
     | 
    
         
            +
            - lib/no_brainer/criteria/first.rb
         
     | 
| 
      
 89 
     | 
    
         
            +
            - lib/no_brainer/criteria/limit.rb
         
     | 
| 
      
 90 
     | 
    
         
            +
            - lib/no_brainer/criteria/order_by.rb
         
     | 
| 
      
 91 
     | 
    
         
            +
            - lib/no_brainer/criteria/preload.rb
         
     | 
| 
      
 92 
     | 
    
         
            +
            - lib/no_brainer/criteria/raw.rb
         
     | 
| 
      
 93 
     | 
    
         
            +
            - lib/no_brainer/criteria/scope.rb
         
     | 
| 
      
 94 
     | 
    
         
            +
            - lib/no_brainer/criteria/update.rb
         
     | 
| 
      
 95 
     | 
    
         
            +
            - lib/no_brainer/criteria/where.rb
         
     | 
| 
      
 96 
     | 
    
         
            +
            - lib/no_brainer/decorated_symbol.rb
         
     | 
| 
      
 97 
     | 
    
         
            +
            - lib/no_brainer/document.rb
         
     | 
| 
      
 98 
     | 
    
         
            +
            - lib/no_brainer/document/association.rb
         
     | 
| 
      
 99 
     | 
    
         
            +
            - lib/no_brainer/document/association/belongs_to.rb
         
     | 
| 
      
 100 
     | 
    
         
            +
            - lib/no_brainer/document/association/core.rb
         
     | 
| 
      
 101 
     | 
    
         
            +
            - lib/no_brainer/document/association/eager_loader.rb
         
     | 
| 
      
 102 
     | 
    
         
            +
            - lib/no_brainer/document/association/has_many.rb
         
     | 
| 
      
 103 
     | 
    
         
            +
            - lib/no_brainer/document/association/has_many_through.rb
         
     | 
| 
       76 
104 
     | 
    
         
             
            - lib/no_brainer/document/association/has_one.rb
         
     | 
| 
       77 
105 
     | 
    
         
             
            - lib/no_brainer/document/association/has_one_through.rb
         
     | 
| 
       78 
     | 
    
         
            -
            - lib/no_brainer/document/ 
     | 
| 
       79 
     | 
    
         
            -
            - lib/no_brainer/document/association/has_many.rb
         
     | 
| 
       80 
     | 
    
         
            -
            - lib/no_brainer/document/association/eager_loader.rb
         
     | 
| 
       81 
     | 
    
         
            -
            - lib/no_brainer/document/association/core.rb
         
     | 
| 
       82 
     | 
    
         
            -
            - lib/no_brainer/document/association/belongs_to.rb
         
     | 
| 
       83 
     | 
    
         
            -
            - lib/no_brainer/document/polymorphic.rb
         
     | 
| 
       84 
     | 
    
         
            -
            - lib/no_brainer/document/store_in.rb
         
     | 
| 
       85 
     | 
    
         
            -
            - lib/no_brainer/document/core.rb
         
     | 
| 
       86 
     | 
    
         
            -
            - lib/no_brainer/document/serialization.rb
         
     | 
| 
       87 
     | 
    
         
            -
            - lib/no_brainer/document/association.rb
         
     | 
| 
      
 106 
     | 
    
         
            +
            - lib/no_brainer/document/attributes.rb
         
     | 
| 
       88 
107 
     | 
    
         
             
            - lib/no_brainer/document/callbacks.rb
         
     | 
| 
       89 
     | 
    
         
            -
            - lib/no_brainer/document/ 
     | 
| 
       90 
     | 
    
         
            -
            - lib/no_brainer/document/ 
     | 
| 
      
 108 
     | 
    
         
            +
            - lib/no_brainer/document/core.rb
         
     | 
| 
      
 109 
     | 
    
         
            +
            - lib/no_brainer/document/criteria.rb
         
     | 
| 
       91 
110 
     | 
    
         
             
            - lib/no_brainer/document/dirty.rb
         
     | 
| 
       92 
     | 
    
         
            -
            - lib/no_brainer/document/ 
     | 
| 
       93 
     | 
    
         
            -
            - lib/no_brainer/document/validation.rb
         
     | 
| 
       94 
     | 
    
         
            -
            - lib/no_brainer/document/attributes.rb
         
     | 
| 
      
 111 
     | 
    
         
            +
            - lib/no_brainer/document/dynamic_attributes.rb
         
     | 
| 
       95 
112 
     | 
    
         
             
            - lib/no_brainer/document/id.rb
         
     | 
| 
      
 113 
     | 
    
         
            +
            - lib/no_brainer/document/index.rb
         
     | 
| 
       96 
114 
     | 
    
         
             
            - lib/no_brainer/document/injection_layer.rb
         
     | 
| 
       97 
115 
     | 
    
         
             
            - lib/no_brainer/document/persistance.rb
         
     | 
| 
      
 116 
     | 
    
         
            +
            - lib/no_brainer/document/polymorphic.rb
         
     | 
| 
       98 
117 
     | 
    
         
             
            - lib/no_brainer/document/readonly.rb
         
     | 
| 
      
 118 
     | 
    
         
            +
            - lib/no_brainer/document/serialization.rb
         
     | 
| 
      
 119 
     | 
    
         
            +
            - lib/no_brainer/document/store_in.rb
         
     | 
| 
      
 120 
     | 
    
         
            +
            - lib/no_brainer/document/timestamps.rb
         
     | 
| 
       99 
121 
     | 
    
         
             
            - lib/no_brainer/document/types.rb
         
     | 
| 
       100 
     | 
    
         
            -
            - lib/no_brainer/document/ 
     | 
| 
      
 122 
     | 
    
         
            +
            - lib/no_brainer/document/uniqueness.rb
         
     | 
| 
      
 123 
     | 
    
         
            +
            - lib/no_brainer/document/validation.rb
         
     | 
| 
      
 124 
     | 
    
         
            +
            - lib/no_brainer/error.rb
         
     | 
| 
      
 125 
     | 
    
         
            +
            - lib/no_brainer/fork.rb
         
     | 
| 
      
 126 
     | 
    
         
            +
            - lib/no_brainer/index_manager.rb
         
     | 
| 
      
 127 
     | 
    
         
            +
            - lib/no_brainer/loader.rb
         
     | 
| 
      
 128 
     | 
    
         
            +
            - lib/no_brainer/locale/en.yml
         
     | 
| 
      
 129 
     | 
    
         
            +
            - lib/no_brainer/query_runner.rb
         
     | 
| 
       101 
130 
     | 
    
         
             
            - lib/no_brainer/query_runner/database_on_demand.rb
         
     | 
| 
       102 
     | 
    
         
            -
            - lib/no_brainer/query_runner/table_on_demand.rb
         
     | 
| 
       103 
     | 
    
         
            -
            - lib/no_brainer/query_runner/write_error.rb
         
     | 
| 
       104 
131 
     | 
    
         
             
            - lib/no_brainer/query_runner/driver.rb
         
     | 
| 
       105 
132 
     | 
    
         
             
            - lib/no_brainer/query_runner/logger.rb
         
     | 
| 
       106 
133 
     | 
    
         
             
            - lib/no_brainer/query_runner/missing_index.rb
         
     | 
| 
      
 134 
     | 
    
         
            +
            - lib/no_brainer/query_runner/reconnect.rb
         
     | 
| 
       107 
135 
     | 
    
         
             
            - lib/no_brainer/query_runner/run_options.rb
         
     | 
| 
       108 
     | 
    
         
            -
            - lib/no_brainer/query_runner/ 
     | 
| 
      
 136 
     | 
    
         
            +
            - lib/no_brainer/query_runner/table_on_demand.rb
         
     | 
| 
      
 137 
     | 
    
         
            +
            - lib/no_brainer/query_runner/write_error.rb
         
     | 
| 
      
 138 
     | 
    
         
            +
            - lib/no_brainer/railtie.rb
         
     | 
| 
       109 
139 
     | 
    
         
             
            - lib/no_brainer/railtie/database.rake
         
     | 
| 
       110 
     | 
    
         
            -
            - lib/no_brainer/index_manager.rb
         
     | 
| 
       111 
     | 
    
         
            -
            - lib/no_brainer/loader.rb
         
     | 
| 
       112 
     | 
    
         
            -
            - lib/no_brainer/locale/en.yml
         
     | 
| 
       113 
     | 
    
         
            -
            - lib/no_brainer/fork.rb
         
     | 
| 
       114 
     | 
    
         
            -
            - lib/no_brainer/connection.rb
         
     | 
| 
       115 
     | 
    
         
            -
            - lib/no_brainer/query_runner.rb
         
     | 
| 
       116 
140 
     | 
    
         
             
            - lib/no_brainer/util.rb
         
     | 
| 
       117 
     | 
    
         
            -
            - lib/ 
     | 
| 
       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
         
     | 
| 
       132 
     | 
    
         
            -
            - lib/no_brainer/railtie.rb
         
     | 
| 
       133 
     | 
    
         
            -
            - lib/no_brainer/config.rb
         
     | 
| 
       134 
     | 
    
         
            -
            - lib/no_brainer/document.rb
         
     | 
| 
       135 
     | 
    
         
            -
            - lib/no_brainer/criteria.rb
         
     | 
| 
       136 
     | 
    
         
            -
            - lib/no_brainer/error.rb
         
     | 
| 
       137 
     | 
    
         
            -
            - lib/no_brainer/autoload.rb
         
     | 
| 
      
 141 
     | 
    
         
            +
            - lib/nobrainer.rb
         
     | 
| 
       138 
142 
     | 
    
         
             
            - lib/rails/generators/nobrainer.rb
         
     | 
| 
       139 
143 
     | 
    
         
             
            - lib/rails/generators/nobrainer/model/model_generator.rb
         
     | 
| 
       140 
144 
     | 
    
         
             
            - lib/rails/generators/nobrainer/model/templates/model.rb.tt
         
     | 
| 
       141 
     | 
    
         
            -
            - lib/nobrainer.rb
         
     | 
| 
       142 
     | 
    
         
            -
            - README.md
         
     | 
| 
       143 
     | 
    
         
            -
            - LICENSE
         
     | 
| 
       144 
145 
     | 
    
         
             
            homepage: http://nobrainer.io
         
     | 
| 
       145 
146 
     | 
    
         
             
            licenses:
         
     | 
| 
       146 
147 
     | 
    
         
             
            - LGPLv3
         
     | 
| 
         @@ -151,17 +152,17 @@ require_paths: 
     | 
|
| 
       151 
152 
     | 
    
         
             
            - lib
         
     | 
| 
       152 
153 
     | 
    
         
             
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
       153 
154 
     | 
    
         
             
              requirements:
         
     | 
| 
       154 
     | 
    
         
            -
              - -  
     | 
| 
      
 155 
     | 
    
         
            +
              - - ">="
         
     | 
| 
       155 
156 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       156 
157 
     | 
    
         
             
                  version: 1.9.0
         
     | 
| 
       157 
158 
     | 
    
         
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
       158 
159 
     | 
    
         
             
              requirements:
         
     | 
| 
       159 
     | 
    
         
            -
              - -  
     | 
| 
      
 160 
     | 
    
         
            +
              - - ">="
         
     | 
| 
       160 
161 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       161 
162 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       162 
163 
     | 
    
         
             
            requirements: []
         
     | 
| 
       163 
164 
     | 
    
         
             
            rubyforge_project: 
         
     | 
| 
       164 
     | 
    
         
            -
            rubygems_version: 2. 
     | 
| 
      
 165 
     | 
    
         
            +
            rubygems_version: 2.2.2
         
     | 
| 
       165 
166 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       166 
167 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       167 
168 
     | 
    
         
             
            summary: ORM for RethinkDB
         
     |