plucky 0.6.3 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +1 -3
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -4
- data/Gemfile +6 -5
- data/Gemfile.lock +84 -0
- data/LICENSE +1 -1
- data/README.md +17 -75
- data/Rakefile +0 -3
- data/examples/query.rb +8 -7
- data/lib/plucky.rb +1 -0
- data/lib/plucky/criteria_hash.rb +78 -62
- data/lib/plucky/extensions/symbol.rb +8 -0
- data/lib/plucky/normalizers/criteria_hash_value.rb +3 -1
- data/lib/plucky/normalizers/fields_value.rb +3 -3
- data/lib/plucky/normalizers/hash_key.rb +19 -0
- data/lib/plucky/normalizers/options_hash_value.rb +5 -7
- data/lib/plucky/normalizers/sort_value.rb +8 -6
- data/lib/plucky/options_hash.rb +9 -3
- data/lib/plucky/pagination.rb +1 -1
- data/lib/plucky/pagination/{decorator.rb → collection.rb} +10 -1
- data/lib/plucky/query.rb +56 -21
- data/lib/plucky/transformer.rb +14 -0
- data/lib/plucky/version.rb +1 -1
- data/plucky.gemspec +4 -5
- data/script/bootstrap +21 -0
- data/script/release +42 -0
- data/script/test +20 -0
- data/spec/functional/options_hash_spec.rb +41 -0
- data/spec/helper.rb +12 -4
- data/spec/plucky/criteria_hash_spec.rb +68 -4
- data/spec/plucky/normalizers/criteria_hash_value_spec.rb +1 -1
- data/spec/plucky/normalizers/fields_value_spec.rb +5 -5
- data/spec/plucky/normalizers/hash_key_spec.rb +15 -0
- data/spec/plucky/normalizers/options_hash_value_spec.rb +2 -2
- data/spec/plucky/normalizers/sort_value_spec.rb +24 -20
- data/spec/plucky/options_hash_spec.rb +2 -2
- data/spec/plucky/pagination/{decorator_spec.rb → collection_spec.rb} +8 -5
- data/spec/plucky/query_spec.rb +92 -35
- data/spec/plucky_spec.rb +5 -5
- data/spec/symbol_operator_spec.rb +18 -1
- metadata +37 -36
- data/lib/plucky/normalizers/options_hash_key.rb +0 -23
- data/script/criteria_hash.rb +0 -21
- data/spec/plucky/normalizers/options_hash_key_spec.rb +0 -23
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: e6482980490f769425d02c3e26483021ce5d22839f733c9d46fcfb30eb762928
         | 
| 4 | 
            +
              data.tar.gz: 0564b1238d7cb08823fedaadc7d3090349580967942750f5021dfd7b24f28cc8
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: 033bfdd0c0bee0b7b25ece80fa54d4bf8f229deec703b63bdcff772a7a0d82cd8b1f3d6e83c6f773f9100bccf655cf5d5da165a58dc276ae78ac5dcb5fe7883d
         | 
| 7 | 
            +
              data.tar.gz: b83627ae90f345dac4587654d8b74434a384473caddf3512f0c2de978a08997e2778b489b3217905ac5c2e5c2ef4ab05b29b1b5b18834719d01d952a0da77d7f
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.rspec
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            --color
         | 
    
        data/.ruby-version
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            ruby-2.7.1
         | 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/Gemfile
    CHANGED
    
    | @@ -1,16 +1,17 @@ | |
| 1 1 | 
             
            source 'https://rubygems.org'
         | 
| 2 2 | 
             
            gemspec
         | 
| 3 3 |  | 
| 4 | 
            -
            gem 'bson_ext', '~> 1.5'
         | 
| 5 4 | 
             
            gem 'rake'
         | 
| 6 5 |  | 
| 7 | 
            -
            group :performance do
         | 
| 8 | 
            -
              gem 'perftools.rb', :require => 'perftools'
         | 
| 9 | 
            -
            end
         | 
| 10 | 
            -
             | 
| 11 6 | 
             
            group(:test) do
         | 
| 12 7 | 
             
              gem 'rspec'
         | 
| 13 8 | 
             
              gem 'log_buddy'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              if RUBY_ENGINE == "ruby" && RUBY_VERSION >= '2.3'
         | 
| 11 | 
            +
                platforms :mri do
         | 
| 12 | 
            +
                  gem 'byebug'
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 14 15 | 
             
            end
         | 
| 15 16 |  | 
| 16 17 | 
             
            group(:guard) do
         | 
    
        data/Gemfile.lock
    ADDED
    
    | @@ -0,0 +1,84 @@ | |
| 1 | 
            +
            PATH
         | 
| 2 | 
            +
              remote: .
         | 
| 3 | 
            +
              specs:
         | 
| 4 | 
            +
                plucky (0.8.0)
         | 
| 5 | 
            +
                  mongo (~> 2.0)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            GEM
         | 
| 8 | 
            +
              remote: https://rubygems.org/
         | 
| 9 | 
            +
              specs:
         | 
| 10 | 
            +
                bson (4.10.0)
         | 
| 11 | 
            +
                byebug (11.1.3)
         | 
| 12 | 
            +
                coderay (1.1.3)
         | 
| 13 | 
            +
                diff-lcs (1.4.4)
         | 
| 14 | 
            +
                ffi (1.13.1)
         | 
| 15 | 
            +
                formatador (0.2.5)
         | 
| 16 | 
            +
                guard (2.16.2)
         | 
| 17 | 
            +
                  formatador (>= 0.2.4)
         | 
| 18 | 
            +
                  listen (>= 2.7, < 4.0)
         | 
| 19 | 
            +
                  lumberjack (>= 1.0.12, < 2.0)
         | 
| 20 | 
            +
                  nenv (~> 0.1)
         | 
| 21 | 
            +
                  notiffany (~> 0.0)
         | 
| 22 | 
            +
                  pry (>= 0.9.12)
         | 
| 23 | 
            +
                  shellany (~> 0.0)
         | 
| 24 | 
            +
                  thor (>= 0.18.1)
         | 
| 25 | 
            +
                guard-bundler (3.0.0)
         | 
| 26 | 
            +
                  bundler (>= 2.1, < 3)
         | 
| 27 | 
            +
                  guard (~> 2.2)
         | 
| 28 | 
            +
                  guard-compat (~> 1.1)
         | 
| 29 | 
            +
                guard-compat (1.2.1)
         | 
| 30 | 
            +
                guard-rspec (4.7.3)
         | 
| 31 | 
            +
                  guard (~> 2.1)
         | 
| 32 | 
            +
                  guard-compat (~> 1.1)
         | 
| 33 | 
            +
                  rspec (>= 2.99.0, < 4.0)
         | 
| 34 | 
            +
                listen (3.2.1)
         | 
| 35 | 
            +
                  rb-fsevent (~> 0.10, >= 0.10.3)
         | 
| 36 | 
            +
                  rb-inotify (~> 0.9, >= 0.9.10)
         | 
| 37 | 
            +
                log_buddy (0.7.0)
         | 
| 38 | 
            +
                lumberjack (1.2.8)
         | 
| 39 | 
            +
                method_source (1.0.0)
         | 
| 40 | 
            +
                mongo (2.13.0)
         | 
| 41 | 
            +
                  bson (>= 4.8.2, < 5.0.0)
         | 
| 42 | 
            +
                nenv (0.3.0)
         | 
| 43 | 
            +
                notiffany (0.1.3)
         | 
| 44 | 
            +
                  nenv (~> 0.1)
         | 
| 45 | 
            +
                  shellany (~> 0.0)
         | 
| 46 | 
            +
                pry (0.13.1)
         | 
| 47 | 
            +
                  coderay (~> 1.1)
         | 
| 48 | 
            +
                  method_source (~> 1.0)
         | 
| 49 | 
            +
                rake (13.0.1)
         | 
| 50 | 
            +
                rb-fsevent (0.10.4)
         | 
| 51 | 
            +
                rb-inotify (0.10.1)
         | 
| 52 | 
            +
                  ffi (~> 1.0)
         | 
| 53 | 
            +
                rspec (3.9.0)
         | 
| 54 | 
            +
                  rspec-core (~> 3.9.0)
         | 
| 55 | 
            +
                  rspec-expectations (~> 3.9.0)
         | 
| 56 | 
            +
                  rspec-mocks (~> 3.9.0)
         | 
| 57 | 
            +
                rspec-core (3.9.2)
         | 
| 58 | 
            +
                  rspec-support (~> 3.9.3)
         | 
| 59 | 
            +
                rspec-expectations (3.9.2)
         | 
| 60 | 
            +
                  diff-lcs (>= 1.2.0, < 2.0)
         | 
| 61 | 
            +
                  rspec-support (~> 3.9.0)
         | 
| 62 | 
            +
                rspec-mocks (3.9.1)
         | 
| 63 | 
            +
                  diff-lcs (>= 1.2.0, < 2.0)
         | 
| 64 | 
            +
                  rspec-support (~> 3.9.0)
         | 
| 65 | 
            +
                rspec-support (3.9.3)
         | 
| 66 | 
            +
                shellany (0.0.1)
         | 
| 67 | 
            +
                thor (1.0.1)
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            PLATFORMS
         | 
| 70 | 
            +
              ruby
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            DEPENDENCIES
         | 
| 73 | 
            +
              byebug
         | 
| 74 | 
            +
              guard
         | 
| 75 | 
            +
              guard-bundler
         | 
| 76 | 
            +
              guard-rspec
         | 
| 77 | 
            +
              log_buddy
         | 
| 78 | 
            +
              plucky!
         | 
| 79 | 
            +
              rake
         | 
| 80 | 
            +
              rb-fsevent
         | 
| 81 | 
            +
              rspec
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            BUNDLED WITH
         | 
| 84 | 
            +
               2.1.4
         | 
    
        data/LICENSE
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -1,6 +1,8 @@ | |
| 1 1 | 
             
            # Plucky
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 3 | 
            +
            A thin layer over the ruby driver that allows you to quickly grab hold of your data (pluck it!).
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Used as a query selector inside of MongoMapper.
         | 
| 4 6 |  | 
| 5 7 | 
             
            ## Install
         | 
| 6 8 |  | 
| @@ -10,79 +12,7 @@ gem install plucky | |
| 10 12 |  | 
| 11 13 | 
             
            ## Examples
         | 
| 12 14 |  | 
| 13 | 
            -
             | 
| 14 | 
            -
            connection = Mongo::MongoClient.new
         | 
| 15 | 
            -
            db = connection.db('test')
         | 
| 16 | 
            -
            collection = db['users']
         | 
| 17 | 
            -
            collection.remove # clear out the collection
         | 
| 18 | 
            -
             | 
| 19 | 
            -
            collection.insert({'_id' => 'chris', 'age' => 26, 'name' => 'Chris'})
         | 
| 20 | 
            -
            collection.insert({'_id' => 'steve', 'age' => 29, 'name' => 'Steve'})
         | 
| 21 | 
            -
            collection.insert({'_id' => 'john',  'age' => 28, 'name' => 'John'})
         | 
| 22 | 
            -
             | 
| 23 | 
            -
            # initialize query with collection
         | 
| 24 | 
            -
            query = Plucky::Query.new(collection)
         | 
| 25 | 
            -
             | 
| 26 | 
            -
            puts 'Querying'
         | 
| 27 | 
            -
            pp query.where(:name => 'John').first
         | 
| 28 | 
            -
            pp query.first(:name => 'John')
         | 
| 29 | 
            -
            pp query.where(:name => 'John').all
         | 
| 30 | 
            -
            pp query.all(:name => 'John')
         | 
| 31 | 
            -
             | 
| 32 | 
            -
            puts 'Find by _id'
         | 
| 33 | 
            -
            pp query.find('chris')
         | 
| 34 | 
            -
            pp query.find('chris', 'steve')
         | 
| 35 | 
            -
            pp query.find(['chris', 'steve'])
         | 
| 36 | 
            -
             | 
| 37 | 
            -
            puts 'Sort'
         | 
| 38 | 
            -
            pp query.sort(:age).all
         | 
| 39 | 
            -
            pp query.sort(:age.asc).all # same as above
         | 
| 40 | 
            -
            pp query.sort(:age.desc).all
         | 
| 41 | 
            -
            pp query.sort(:age).last # steve
         | 
| 42 | 
            -
             | 
| 43 | 
            -
            puts 'Counting'
         | 
| 44 | 
            -
            pp query.count # 3
         | 
| 45 | 
            -
            pp query.size # 3
         | 
| 46 | 
            -
            pp query.count(:name => 'John')       # 1
         | 
| 47 | 
            -
            pp query.where(:name => 'John').count # 1
         | 
| 48 | 
            -
            pp query.where(:name => 'John').size  # 1
         | 
| 49 | 
            -
             | 
| 50 | 
            -
            puts 'Distinct'
         | 
| 51 | 
            -
            pp query.distinct(:age) # [26, 29, 28]
         | 
| 52 | 
            -
             | 
| 53 | 
            -
            puts 'Select only certain fields'
         | 
| 54 | 
            -
            pp query.fields(:age).find('chris')   # {"_id"=>"chris", "age"=>26}
         | 
| 55 | 
            -
            pp query.only(:age).find('chris')     # {"_id"=>"chris", "age"=>26}
         | 
| 56 | 
            -
            pp query.ignore(:name).find('chris')  # {"_id"=>"chris", "age"=>26}
         | 
| 57 | 
            -
             | 
| 58 | 
            -
            puts 'Pagination, yeah we got that'
         | 
| 59 | 
            -
            pp query.sort(:age).paginate(:per_page => 1, :page => 2)
         | 
| 60 | 
            -
            pp query.sort(:age).per_page(1).paginate(:page => 2)
         | 
| 61 | 
            -
             | 
| 62 | 
            -
            pp query.sort(:age).limit(2).to_a           # [chris, john]
         | 
| 63 | 
            -
            pp query.sort(:age).skip(1).limit(2).to_a   # [john, steve]
         | 
| 64 | 
            -
            pp query.sort(:age).offset(1).limit(2).to_a # [john, steve]
         | 
| 65 | 
            -
             | 
| 66 | 
            -
            puts 'Using a cursor'
         | 
| 67 | 
            -
            cursor = query.find_each(:sort => :age) do |doc|
         | 
| 68 | 
            -
              pp doc
         | 
| 69 | 
            -
            end
         | 
| 70 | 
            -
            pp cursor
         | 
| 71 | 
            -
             | 
| 72 | 
            -
            puts 'Symbol Operators'
         | 
| 73 | 
            -
            pp query.where(:age.gt => 28).count       # 1 (steve)
         | 
| 74 | 
            -
            pp query.where(:age.lt => 28).count       # 1 (chris)
         | 
| 75 | 
            -
            pp query.where(:age.in => [26, 28]).to_a  # [chris, john]
         | 
| 76 | 
            -
            pp query.where(:age.nin => [26, 28]).to_a  # [steve]
         | 
| 77 | 
            -
             | 
| 78 | 
            -
            puts 'Removing'
         | 
| 79 | 
            -
            query.remove(:name => 'John')
         | 
| 80 | 
            -
            pp query.count # 2
         | 
| 81 | 
            -
            query.where(:name => 'Chris').remove
         | 
| 82 | 
            -
            pp query.count # 1
         | 
| 83 | 
            -
            query.remove
         | 
| 84 | 
            -
            pp query.count # 0
         | 
| 85 | 
            -
            ```
         | 
| 15 | 
            +
            See `examples/query.rb`.
         | 
| 86 16 |  | 
| 87 17 | 
             
            ## Help
         | 
| 88 18 |  | 
| @@ -98,4 +28,16 @@ https://groups.google.com/forum/#!forum/mongomapper | |
| 98 28 |  | 
| 99 29 | 
             
            ## Copyright
         | 
| 100 30 |  | 
| 101 | 
            -
            Copyright (c) 2010  | 
| 31 | 
            +
            Copyright (c) 2010-2020 MongoMapper. See LICENSE for details.
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            ## Contributors
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            MongoMapper/Plucky is:
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            * John Nunemaker
         | 
| 38 | 
            +
            * Chris Heald
         | 
| 39 | 
            +
            * Scott Taylor
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            With contributions from:
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            * Frederick Cheung
         | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/examples/query.rb
    CHANGED
    
    | @@ -7,18 +7,19 @@ lib_path  = root_path.join('lib') | |
| 7 7 | 
             
            $:.unshift(lib_path)
         | 
| 8 8 | 
             
            require 'plucky'
         | 
| 9 9 |  | 
| 10 | 
            -
            connection = Mongo:: | 
| 11 | 
            -
            db = connection. | 
| 10 | 
            +
            connection = Mongo::Client.new(["127.0.0.1"], :logger => Logger.new('/dev/null'))
         | 
| 11 | 
            +
            db = connection.use('test').database
         | 
| 12 12 | 
             
            collection = db['users']
         | 
| 13 | 
            -
            collection.remove # clear out the collection
         | 
| 14 | 
            -
             | 
| 15 | 
            -
            collection.insert({'_id' => 'chris', 'age' => 26, 'name' => 'Chris'})
         | 
| 16 | 
            -
            collection.insert({'_id' => 'steve', 'age' => 29, 'name' => 'Steve'})
         | 
| 17 | 
            -
            collection.insert({'_id' => 'john',  'age' => 28, 'name' => 'John'})
         | 
| 18 13 |  | 
| 19 14 | 
             
            # initialize query with collection
         | 
| 20 15 | 
             
            query = Plucky::Query.new(collection)
         | 
| 21 16 |  | 
| 17 | 
            +
            query.remove # clear out the collection
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            query.insert({'_id' => 'chris', 'age' => 26, 'name' => 'Chris'})
         | 
| 20 | 
            +
            query.insert({'_id' => 'steve', 'age' => 29, 'name' => 'Steve'})
         | 
| 21 | 
            +
            query.insert({'_id' => 'john',  'age' => 28, 'name' => 'John'})
         | 
| 22 | 
            +
             | 
| 22 23 | 
             
            puts 'Querying'
         | 
| 23 24 | 
             
            pp query.where(:name => 'John').first
         | 
| 24 25 | 
             
            pp query.first(:name => 'John')
         | 
    
        data/lib/plucky.rb
    CHANGED
    
    
    
        data/lib/plucky/criteria_hash.rb
    CHANGED
    
    | @@ -77,58 +77,9 @@ module Plucky | |
| 77 77 | 
             
                  @source
         | 
| 78 78 | 
             
                end
         | 
| 79 79 |  | 
| 80 | 
            -
                # Public | 
| 80 | 
            +
                # Public
         | 
| 81 81 | 
             
                def merge(other)
         | 
| 82 | 
            -
                   | 
| 83 | 
            -
                  other.source.each_key do |key|
         | 
| 84 | 
            -
                    value, other_value = target[key], other[key]
         | 
| 85 | 
            -
                    target[key] =
         | 
| 86 | 
            -
                      if target.key?(key)
         | 
| 87 | 
            -
                        value_is_hash = value.is_a?(Hash)
         | 
| 88 | 
            -
                        other_is_hash = other_value.is_a?(Hash)
         | 
| 89 | 
            -
             | 
| 90 | 
            -
                        if value_is_hash && other_is_hash
         | 
| 91 | 
            -
                          value.update(other_value) do |key, old_value, new_value|
         | 
| 92 | 
            -
                            if old_value.is_a?(Hash) && new_value.is_a?(Hash)
         | 
| 93 | 
            -
                              self.class.new(old_value).merge(self.class.new(new_value)).to_hash
         | 
| 94 | 
            -
                            else
         | 
| 95 | 
            -
                              merge_values_into_array(old_value, new_value)
         | 
| 96 | 
            -
                            end
         | 
| 97 | 
            -
                          end
         | 
| 98 | 
            -
                        elsif value_is_hash && !other_is_hash
         | 
| 99 | 
            -
                          if modifier_key = value.keys.detect { |k| Plucky.modifier?(k) }
         | 
| 100 | 
            -
                            current_value = value[modifier_key]
         | 
| 101 | 
            -
                            value[modifier_key] = current_value.concat(array(other_value)).uniq
         | 
| 102 | 
            -
                          else
         | 
| 103 | 
            -
                            # kaboom! Array(value).concat(Array(other_value)).uniq
         | 
| 104 | 
            -
                          end
         | 
| 105 | 
            -
                        elsif other_is_hash && !value_is_hash
         | 
| 106 | 
            -
                          if modifier_key = other_value.keys.detect { |k| Plucky.modifier?(k) }
         | 
| 107 | 
            -
                            current_value = other_value[modifier_key]
         | 
| 108 | 
            -
                            other_value[modifier_key] = current_value.concat(array(value)).uniq
         | 
| 109 | 
            -
                          else
         | 
| 110 | 
            -
                            # kaboom! Array(value).concat(Array(other_value)).uniq
         | 
| 111 | 
            -
                          end
         | 
| 112 | 
            -
                        else
         | 
| 113 | 
            -
                          merge_values_into_array(value, other_value)
         | 
| 114 | 
            -
                        end
         | 
| 115 | 
            -
                      else
         | 
| 116 | 
            -
                        other_value
         | 
| 117 | 
            -
                      end
         | 
| 118 | 
            -
                  end
         | 
| 119 | 
            -
                  self.class.new(target)
         | 
| 120 | 
            -
                end
         | 
| 121 | 
            -
             | 
| 122 | 
            -
                # Private
         | 
| 123 | 
            -
                def merge_values_into_array(value, other_value)
         | 
| 124 | 
            -
                  array(value).concat(array(other_value)).uniq
         | 
| 125 | 
            -
                end
         | 
| 126 | 
            -
             | 
| 127 | 
            -
                # Private: Array(BSON::ObjectId) returns the byte array or what not instead
         | 
| 128 | 
            -
                # of the object id. This makes sure it is an array of object ids, not the
         | 
| 129 | 
            -
                # guts of the object id.
         | 
| 130 | 
            -
                def array(value)
         | 
| 131 | 
            -
                  value.is_a?(BSON::ObjectId) ? [value] : Array(value)
         | 
| 82 | 
            +
                  self.class.new hash_merge(@source, other.source)
         | 
| 132 83 | 
             
                end
         | 
| 133 84 |  | 
| 134 85 | 
             
                # Public
         | 
| @@ -139,17 +90,6 @@ module Plucky | |
| 139 90 | 
             
                  self
         | 
| 140 91 | 
             
                end
         | 
| 141 92 |  | 
| 142 | 
            -
                # Private
         | 
| 143 | 
            -
                def object_ids
         | 
| 144 | 
            -
                  @options[:object_ids] ||= []
         | 
| 145 | 
            -
                end
         | 
| 146 | 
            -
             | 
| 147 | 
            -
                # Private
         | 
| 148 | 
            -
                def object_ids=(value)
         | 
| 149 | 
            -
                  raise ArgumentError unless value.is_a?(Array)
         | 
| 150 | 
            -
                  @options[:object_ids] = value.flatten
         | 
| 151 | 
            -
                end
         | 
| 152 | 
            -
             | 
| 153 93 | 
             
                # Public: The definition of simple is querying by only _id or _id and _type.
         | 
| 154 94 | 
             
                # If this is the case, you can use IdentityMap in library to not perform
         | 
| 155 95 | 
             
                # query and instead just return from map.
         | 
| @@ -165,6 +105,82 @@ module Plucky | |
| 165 105 | 
             
                  object_ids.include?(key.to_sym)
         | 
| 166 106 | 
             
                end
         | 
| 167 107 |  | 
| 108 | 
            +
                # Private
         | 
| 109 | 
            +
                def object_ids
         | 
| 110 | 
            +
                  @options[:object_ids] ||= []
         | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                # Private
         | 
| 114 | 
            +
                def object_ids=(value)
         | 
| 115 | 
            +
                  raise ArgumentError unless value.is_a?(Array)
         | 
| 116 | 
            +
                  @options[:object_ids] = value.flatten
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                private
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                # Private
         | 
| 122 | 
            +
                def hash_merge(oldhash, newhash)
         | 
| 123 | 
            +
                  merge_compound_or_clauses!(oldhash, newhash)
         | 
| 124 | 
            +
                  oldhash.merge(newhash) do |key, oldval, newval|
         | 
| 125 | 
            +
                    old_is_hash = oldval.instance_of? Hash
         | 
| 126 | 
            +
                    new_is_hash = newval.instance_of? Hash
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                    if oldval == newval
         | 
| 129 | 
            +
                      oldval
         | 
| 130 | 
            +
                    elsif old_is_hash && new_is_hash
         | 
| 131 | 
            +
                      hash_merge(oldval, newval)
         | 
| 132 | 
            +
                    elsif old_is_hash
         | 
| 133 | 
            +
                      modifier_merge(oldval, newval)
         | 
| 134 | 
            +
                    elsif new_is_hash
         | 
| 135 | 
            +
                      modifier_merge(newval, oldval)
         | 
| 136 | 
            +
                    else
         | 
| 137 | 
            +
                      merge_values_into_array(oldval, newval)
         | 
| 138 | 
            +
                    end
         | 
| 139 | 
            +
                  end
         | 
| 140 | 
            +
                end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                def merge_compound_or_clauses!(oldhash, newhash)
         | 
| 143 | 
            +
                  old_or = oldhash[:$or]
         | 
| 144 | 
            +
                  new_or = newhash[:$or]
         | 
| 145 | 
            +
                  if old_or && new_or
         | 
| 146 | 
            +
                    oldhash[:$and] ||= []
         | 
| 147 | 
            +
                    oldhash[:$and] << {:$or => oldhash.delete(:$or)}
         | 
| 148 | 
            +
                    oldhash[:$and] << {:$or => newhash.delete(:$or)}
         | 
| 149 | 
            +
                  elsif new_or && oldhash[:$and]
         | 
| 150 | 
            +
                    if oldhash[:$and].any? {|v| v.key? :$or }
         | 
| 151 | 
            +
                      oldhash[:$and] << {:$or => newhash.delete(:$or)}
         | 
| 152 | 
            +
                    end
         | 
| 153 | 
            +
                  elsif old_or && newhash[:$and]
         | 
| 154 | 
            +
                    if newhash[:$and].any? {|v| v.key? :$or }
         | 
| 155 | 
            +
                      newhash[:$and] << {:$or => oldhash.delete(:$or)}
         | 
| 156 | 
            +
                    end
         | 
| 157 | 
            +
                  end
         | 
| 158 | 
            +
                end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                # Private
         | 
| 161 | 
            +
                def modifier_merge(hash, value)
         | 
| 162 | 
            +
                  if modifier_key = hash.keys.detect { |k| Plucky.modifier?(k) }
         | 
| 163 | 
            +
                    hash[modifier_key].concat( array(value) ).uniq
         | 
| 164 | 
            +
                  end
         | 
| 165 | 
            +
                end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                # Private
         | 
| 168 | 
            +
                def merge_values_into_array(value, other_value)
         | 
| 169 | 
            +
                  array(value).concat(array(other_value)).uniq
         | 
| 170 | 
            +
                end
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                # Private: Array(BSON::ObjectId) returns the byte array or what not instead
         | 
| 173 | 
            +
                # of the object id. This makes sure it is an array of object ids, not the
         | 
| 174 | 
            +
                # guts of the object id.
         | 
| 175 | 
            +
                def array(value)
         | 
| 176 | 
            +
                  case value
         | 
| 177 | 
            +
                  when nil, BSON::ObjectId
         | 
| 178 | 
            +
                    [value]
         | 
| 179 | 
            +
                  else
         | 
| 180 | 
            +
                    Array(value)
         | 
| 181 | 
            +
                  end
         | 
| 182 | 
            +
                end
         | 
| 183 | 
            +
             | 
| 168 184 | 
             
                # Private
         | 
| 169 185 | 
             
                def normalized_key(key)
         | 
| 170 186 | 
             
                  key_normalizer.call(key)
         |