flocks 0.0.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 +7 -0
 - data/.gitignore +17 -0
 - data/Gemfile +4 -0
 - data/LICENSE.txt +25 -0
 - data/README.md +142 -0
 - data/Rakefile +11 -0
 - data/flocks.gemspec +26 -0
 - data/lib/flocks.rb +23 -0
 - data/lib/flocks/configuration.rb +113 -0
 - data/lib/flocks/ordering.rb +33 -0
 - data/lib/flocks/relationships.rb +87 -0
 - data/lib/flocks/search.rb +37 -0
 - data/lib/flocks/version.rb +3 -0
 - data/test/flocks/configuration_test.rb +23 -0
 - data/test/flocks/flocks_test.rb +10 -0
 - data/test/flocks/ordering_test.rb +12 -0
 - data/test/flocks/relationships_test.rb +55 -0
 - data/test/flocks/search_test.rb +36 -0
 - data/test/test_helper.rb +28 -0
 - metadata +124 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 9670cef0827448591a9929ae6b1e29e9a10907d8
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: f44b3a80e9ba291f79472cb32f207de3e3fd2fda
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: b1bee72695582429793848aa7ae8694c6f05e5f8710ae2cf14e9f79baf0ecf62afc395e4fc1c316676f57a393f70a0dbc74413ddc7167480e630b3c9b56c460d
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: ac2b6281eb80f9853680c5312358035be1af26e6794aafa4f25695470a7ccd1d69e9fe4722ca45f5ab7e6c8b1963fe1e374771f40e5aa1cff145744132cc768b
         
     | 
    
        data/.gitignore
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE.txt
    ADDED
    
    | 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) 2014, Byliner, Inc
         
     | 
| 
      
 2 
     | 
    
         
            +
            All rights reserved.
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            Redistribution and use in source and binary forms, with or without modification,
         
     | 
| 
      
 5 
     | 
    
         
            +
            are permitted provided that the following conditions are met:
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            * Redistributions of source code must retain the above copyright notice, this
         
     | 
| 
      
 8 
     | 
    
         
            +
              list of conditions and the following disclaimer.
         
     | 
| 
      
 9 
     | 
    
         
            +
            * Redistributions in binary form must reproduce the above copyright notice, this
         
     | 
| 
      
 10 
     | 
    
         
            +
              list of conditions and the following disclaimer in the documentation and/or
         
     | 
| 
      
 11 
     | 
    
         
            +
              other materials provided with the distribution.
         
     | 
| 
      
 12 
     | 
    
         
            +
            * Neither the name of the DUO Interactive, LLC nor the names of its contributors
         
     | 
| 
      
 13 
     | 
    
         
            +
              may be used to endorse or promote products derived from this software without
         
     | 
| 
      
 14 
     | 
    
         
            +
              specific prior written permission.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
         
     | 
| 
      
 17 
     | 
    
         
            +
            ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
         
     | 
| 
      
 18 
     | 
    
         
            +
            WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
         
     | 
| 
      
 19 
     | 
    
         
            +
            DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
         
     | 
| 
      
 20 
     | 
    
         
            +
            FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
         
     | 
| 
      
 21 
     | 
    
         
            +
            DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
         
     | 
| 
      
 22 
     | 
    
         
            +
            SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
         
     | 
| 
      
 23 
     | 
    
         
            +
            CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
         
     | 
| 
      
 24 
     | 
    
         
            +
            OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
         
     | 
| 
      
 25 
     | 
    
         
            +
            OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,142 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Flocks
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Flocks is a lightweight searchable social graph that tracks a user's followers, who they are following, and who they have blocked.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Flocks uses [Redis](http://redis.io/documentation) to store the relationships.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            User lists are sorted alphabetically and can be searched!
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            Flocks uses usernames (or any unique string identifier) when following in order to sort the following/followers lists.
         
     | 
| 
      
 10 
     | 
    
         
            +
            By requiring usernames when establishing relationships, Flocks becomes searchable.
         
     | 
| 
      
 11 
     | 
    
         
            +
            Flocks will return all user ids with user_ids matching the query string.
         
     | 
| 
      
 12 
     | 
    
         
            +
            Flocks search capabilities can be used to autocomplete text fields with usernames in a user's social graph.
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            For example, if a user is following: 'Adam', 'Aaron', 'Addison', and 'John'
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            Searching for 'a' will return the ids associated with Adam, Aaron, and Addison
         
     | 
| 
      
 17 
     | 
    
         
            +
            Searching for 'ad' will return the id associated with Adam
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            Add this line to your application's Gemfile:
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                gem 'flocks'
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            And then execute:
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                $ bundle
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            Or install it yourself as:
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                $ gem install flocks
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            ## Usage
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            Configure flocks:
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 39 
     | 
    
         
            +
            Flocks.configure do |configuration|
         
     | 
| 
      
 40 
     | 
    
         
            +
              configuration.redis = Redis.new
         
     | 
| 
      
 41 
     | 
    
         
            +
              configuration.namespace = 'flocks'
         
     | 
| 
      
 42 
     | 
    
         
            +
              configuration.following_key = 'following'
         
     | 
| 
      
 43 
     | 
    
         
            +
              configuration.followers_key = 'followers'
         
     | 
| 
      
 44 
     | 
    
         
            +
              configuration.blocked_key = 'blocked'
         
     | 
| 
      
 45 
     | 
    
         
            +
              configuration.page_size = 25
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
      
 47 
     | 
    
         
            +
            ```
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            Use flocks:
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 52 
     | 
    
         
            +
            require 'flocks'
         
     | 
| 
      
 53 
     | 
    
         
            +
            => true
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            Flocks.configure do |configuration|
         
     | 
| 
      
 56 
     | 
    
         
            +
              configuration.redis = Redis.new
         
     | 
| 
      
 57 
     | 
    
         
            +
              configuration.namespace = 'flocks'
         
     | 
| 
      
 58 
     | 
    
         
            +
              configuration.following_key = 'following'
         
     | 
| 
      
 59 
     | 
    
         
            +
              configuration.followers_key = 'followers'
         
     | 
| 
      
 60 
     | 
    
         
            +
              configuration.blocked_key = 'blocked'
         
     | 
| 
      
 61 
     | 
    
         
            +
              configuration.page_size = 25
         
     | 
| 
      
 62 
     | 
    
         
            +
            end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            Flocks.new(1, 'username').follow(11, 'other_username')
         
     | 
| 
      
 65 
     | 
    
         
            +
            => true
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            Flocks.new(1, 'username').following?(11)
         
     | 
| 
      
 68 
     | 
    
         
            +
            => true
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            Flocks.new(11, 'other_username').following?(1)
         
     | 
| 
      
 71 
     | 
    
         
            +
            => false
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            Flocks.new(11, 'other_username').follow(1, 'username')
         
     | 
| 
      
 74 
     | 
    
         
            +
            => true
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            Flocks.new(11, 'other_username').following?(1)
         
     | 
| 
      
 77 
     | 
    
         
            +
            => true
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            Flocks.new(1, 'username').following_count
         
     | 
| 
      
 80 
     | 
    
         
            +
            => 1
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            Flocks.new(1, 'username').followers_count
         
     | 
| 
      
 83 
     | 
    
         
            +
            => 1
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            Flocks.new(11, 'other_username').unfollow(1)
         
     | 
| 
      
 86 
     | 
    
         
            +
            => true
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
            Flocks.new(11, 'other_username').following_count
         
     | 
| 
      
 89 
     | 
    
         
            +
            => 0
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
            Flocks.new(1, 'username').following_count
         
     | 
| 
      
 92 
     | 
    
         
            +
            => 1
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
            Flocks.new(1, 'username').following
         
     | 
| 
      
 95 
     | 
    
         
            +
            => ["11"]
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
            Flocks.new(1, 'username').block(11)
         
     | 
| 
      
 98 
     | 
    
         
            +
            => true
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
            Flocks.new(11, 'username').following?(1)
         
     | 
| 
      
 101 
     | 
    
         
            +
            => false
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
            Flocks.new(1, 'username').blocked?(11)
         
     | 
| 
      
 104 
     | 
    
         
            +
            => true
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
            Flocks.new(11, 'other_username').follow(1)
         
     | 
| 
      
 107 
     | 
    
         
            +
            => nil
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            Flocks.new(1, 'username').unblock(11)
         
     | 
| 
      
 110 
     | 
    
         
            +
            => true
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
            Flocks.new(1, 'username').blocked?(11)
         
     | 
| 
      
 113 
     | 
    
         
            +
            => false
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
            Flocks.new(11, 'other_username').follow(1)
         
     | 
| 
      
 116 
     | 
    
         
            +
            => true
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
            Flocks.new(1, 'username').follow(11)
         
     | 
| 
      
 119 
     | 
    
         
            +
            => true
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
            Flocks.new(1, 'username').search_following('other')
         
     | 
| 
      
 122 
     | 
    
         
            +
            => ["11"]
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
            Flocks.new(1, 'username').search_followers('other')
         
     | 
| 
      
 125 
     | 
    
         
            +
            => ["11"]
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
            Flocks.new(1, 'username').search_graph('other')
         
     | 
| 
      
 128 
     | 
    
         
            +
            => ["11"]
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
            ```
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
            ## Thanks
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
            Many thanks to [amico](https://github.com/agoragames/amico) creator [agoragames](https://github.com/agoragames).  A lot of the code used was inspired by the [amico gem](https://github.com/agoragames/amico).
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
            ## Contributing
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
            1. Fork it ( http://github.com/<my-github-username>/flocks/fork )
         
     | 
| 
      
 139 
     | 
    
         
            +
            2. Create your feature branch (`git checkout -b my-new-feature`)
         
     | 
| 
      
 140 
     | 
    
         
            +
            3. Commit your changes (`git commit -am 'Add some feature'`)
         
     | 
| 
      
 141 
     | 
    
         
            +
            4. Push to the branch (`git push origin my-new-feature`)
         
     | 
| 
      
 142 
     | 
    
         
            +
            5. Create new Pull Request
         
     | 
    
        data/Rakefile
    ADDED
    
    
    
        data/flocks.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # coding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            lib = File.expand_path('../lib', __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'flocks/version'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 7 
     | 
    
         
            +
              spec.name          = "flocks"
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.version       = Flocks::VERSION
         
     | 
| 
      
 9 
     | 
    
         
            +
              spec.authors       = ["Adam Ryan"]
         
     | 
| 
      
 10 
     | 
    
         
            +
              spec.email         = ["adam.g.ryan@gmail.com"]
         
     | 
| 
      
 11 
     | 
    
         
            +
              spec.summary       = %q{Single node social relationships using redis.}
         
     | 
| 
      
 12 
     | 
    
         
            +
              spec.description   = %q{Single node social relationships using redis.}
         
     | 
| 
      
 13 
     | 
    
         
            +
              spec.homepage      = "https://github.com/byliner/flocks"
         
     | 
| 
      
 14 
     | 
    
         
            +
              spec.license       = "BSD"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              spec.files         = `git ls-files`.split($/)
         
     | 
| 
      
 17 
     | 
    
         
            +
              spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
         
     | 
| 
      
 18 
     | 
    
         
            +
              spec.test_files    = spec.files.grep(%r{^(test)/})
         
     | 
| 
      
 19 
     | 
    
         
            +
              spec.require_paths = ["lib"]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              spec.add_dependency "redis"
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              spec.add_development_dependency "bundler", "~> 1.5"
         
     | 
| 
      
 24 
     | 
    
         
            +
              spec.add_development_dependency "rake"
         
     | 
| 
      
 25 
     | 
    
         
            +
              spec.add_development_dependency "minitest"
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/flocks.rb
    ADDED
    
    | 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'redis'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'flocks/configuration'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'flocks/ordering'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'flocks/relationships'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'flocks/search'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'flocks/version'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module Flocks
         
     | 
| 
      
 9 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 10 
     | 
    
         
            +
                include Configuration
         
     | 
| 
      
 11 
     | 
    
         
            +
                include Ordering
         
     | 
| 
      
 12 
     | 
    
         
            +
                include Search
         
     | 
| 
      
 13 
     | 
    
         
            +
                include Relationships
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                attr_accessor :user_id, :username_score
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def new(user_id, username = nil)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  self.user_id = user_id
         
     | 
| 
      
 19 
     | 
    
         
            +
                  self.username_score = rank_username(username)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  self
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,113 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Flocks
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Configuration settings for Flocks.
         
     | 
| 
      
 3 
     | 
    
         
            +
              module Configuration
         
     | 
| 
      
 4 
     | 
    
         
            +
                # Redis instance.
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_accessor :redis
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                # Flocks namespace for Redis.
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_writer :namespace
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                # Key used in Redis for tracking who an individual is following.
         
     | 
| 
      
 11 
     | 
    
         
            +
                attr_writer :following_key
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                # Key used in Redis for tracking the followers of an individual.
         
     | 
| 
      
 14 
     | 
    
         
            +
                attr_writer :followers_key
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                # Key used in Redis for tracking who an individual blocks.
         
     | 
| 
      
 17 
     | 
    
         
            +
                attr_writer :blocked_key
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                # Key used in Redis for tracking who has blocked an individual.
         
     | 
| 
      
 20 
     | 
    
         
            +
                attr_writer :blocked_by_key
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                # Key used in Redis for tracking who has reciprocated a follow for an individual.
         
     | 
| 
      
 23 
     | 
    
         
            +
                attr_writer :reciprocated_key
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                # Key used in Redis for tracking pending follow relationships for an individual.
         
     | 
| 
      
 26 
     | 
    
         
            +
                attr_writer :pending_key
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                # Key used in Redis for tracking who an individual is awaiting approval from.
         
     | 
| 
      
 29 
     | 
    
         
            +
                attr_writer :pending_with_key
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                # Key used to indicate whether or not a follow should be pending or not.
         
     | 
| 
      
 32 
     | 
    
         
            +
                attr_writer :pending_follow
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                # Page size to be used when paging through the various types of relationships.
         
     | 
| 
      
 35 
     | 
    
         
            +
                attr_writer :page_size
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                # Set the percision for relationship sorting granularity
         
     | 
| 
      
 38 
     | 
    
         
            +
                attr_writer :string_score_percision
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                # Yield self to be able to configure Flocks with block-style configuration.
         
     | 
| 
      
 41 
     | 
    
         
            +
                #
         
     | 
| 
      
 42 
     | 
    
         
            +
                # Example:
         
     | 
| 
      
 43 
     | 
    
         
            +
                #
         
     | 
| 
      
 44 
     | 
    
         
            +
                #   Flocks.configure do |configuration|
         
     | 
| 
      
 45 
     | 
    
         
            +
                #     configuration.redis = Redis.new
         
     | 
| 
      
 46 
     | 
    
         
            +
                #     configuration.namespace = 'flocks'
         
     | 
| 
      
 47 
     | 
    
         
            +
                #     configuration.following_key = 'following'
         
     | 
| 
      
 48 
     | 
    
         
            +
                #     configuration.followers_key = 'followers'
         
     | 
| 
      
 49 
     | 
    
         
            +
                #     configuration.blocked_key = 'blocked'
         
     | 
| 
      
 50 
     | 
    
         
            +
                #     configuration.blocked_by_key = 'blocked_by'
         
     | 
| 
      
 51 
     | 
    
         
            +
                #     configuration.page_size = 25
         
     | 
| 
      
 52 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 53 
     | 
    
         
            +
                def configure
         
     | 
| 
      
 54 
     | 
    
         
            +
                  yield self
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                # Flocks namespace for Redis.
         
     | 
| 
      
 58 
     | 
    
         
            +
                #
         
     | 
| 
      
 59 
     | 
    
         
            +
                # @return the Flocks namespace or the default of 'flocks' if not set.
         
     | 
| 
      
 60 
     | 
    
         
            +
                def namespace
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @namespace ||= 'flocks'
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                # Key used in Redis for tracking who an individual is following.
         
     | 
| 
      
 65 
     | 
    
         
            +
                #
         
     | 
| 
      
 66 
     | 
    
         
            +
                # @return the key used in Redis for tracking who an individual is following or the default of 'following' if not set.
         
     | 
| 
      
 67 
     | 
    
         
            +
                def following_key
         
     | 
| 
      
 68 
     | 
    
         
            +
                  @following_key ||= 'following'
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                # Key used in Redis for tracking the followers of an individual.
         
     | 
| 
      
 72 
     | 
    
         
            +
                #
         
     | 
| 
      
 73 
     | 
    
         
            +
                # @return the key used in Redis for tracking the followers of an individual or the default of 'followers' if not set.
         
     | 
| 
      
 74 
     | 
    
         
            +
                def followers_key
         
     | 
| 
      
 75 
     | 
    
         
            +
                  @followers_key ||= 'followers'
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                # Key used in Redis for tracking who an individual blocks.
         
     | 
| 
      
 79 
     | 
    
         
            +
                #
         
     | 
| 
      
 80 
     | 
    
         
            +
                # @return the key used in Redis for tracking who an individual blocks or the default of 'blocked' if not set.
         
     | 
| 
      
 81 
     | 
    
         
            +
                def blocked_key
         
     | 
| 
      
 82 
     | 
    
         
            +
                  @blocked_key ||= 'blocked'
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                # Key used in Redis for tracking who has blocked an individual.
         
     | 
| 
      
 86 
     | 
    
         
            +
                #
         
     | 
| 
      
 87 
     | 
    
         
            +
                # @return the key used in Redis for tracking who has blocked an individual or the default of 'blocked_by' if not set.
         
     | 
| 
      
 88 
     | 
    
         
            +
                def blocked_by_key
         
     | 
| 
      
 89 
     | 
    
         
            +
                  @blocked_by_key ||= 'blocked_by'
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                # Key used in Redis for tracking who has reciprocated a follow for an individual.
         
     | 
| 
      
 93 
     | 
    
         
            +
                #
         
     | 
| 
      
 94 
     | 
    
         
            +
                # @return the key used in Redis for tracking who has reciprocated a follow for an individual or the default of 'reciprocated' if not set.
         
     | 
| 
      
 95 
     | 
    
         
            +
                def reciprocated_key
         
     | 
| 
      
 96 
     | 
    
         
            +
                  @reciprocated_key ||= 'reciprocated'
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                # Page size to be used when paging through the various types of relationships.
         
     | 
| 
      
 100 
     | 
    
         
            +
                #
         
     | 
| 
      
 101 
     | 
    
         
            +
                # @return the page size to be used when paging through the various types of relationships or the default of 25 if not set.
         
     | 
| 
      
 102 
     | 
    
         
            +
                def page_size
         
     | 
| 
      
 103 
     | 
    
         
            +
                  @page_size ||= 25
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                # Number of characters to be used when scoring a username for indexing in redis
         
     | 
| 
      
 107 
     | 
    
         
            +
                #
         
     | 
| 
      
 108 
     | 
    
         
            +
                # @return the scoring percision
         
     | 
| 
      
 109 
     | 
    
         
            +
                def string_score_percision
         
     | 
| 
      
 110 
     | 
    
         
            +
                  @string_score_percision ||= 5
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
              end
         
     | 
| 
      
 113 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Flocks
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Ordering
         
     | 
| 
      
 3 
     | 
    
         
            +
                def rank_username(username)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  # Selects the number of characters to be evaluated for sorting
         
     | 
| 
      
 5 
     | 
    
         
            +
                  percision_index = string_score_percision - 1
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  # Base score
         
     | 
| 
      
 8 
     | 
    
         
            +
                  score = 0
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  # Get the first 5 characters in an array
         
     | 
| 
      
 11 
     | 
    
         
            +
                  characters = username.to_s.downcase[0..percision_index].split('')
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  # If the username is short, tack on the lowest ascii value
         
     | 
| 
      
 14 
     | 
    
         
            +
                  characters << '0' until characters.size == string_score_percision
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  # Reverse them for easy multiplication scoring
         
     | 
| 
      
 17 
     | 
    
         
            +
                  characters.reverse.each_with_index do |char, i|
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    # Use the mutiplier, increase magnitude for weighting first letters more
         
     | 
| 
      
 20 
     | 
    
         
            +
                    # multiplier = (character_multiplier[0..(i + 1)].to_i)
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    multiplier = 10 ** i
         
     | 
| 
      
 23 
     | 
    
         
            +
                    # Square the multiplier to avoid large ascii values from thwrowing off calculations
         
     | 
| 
      
 24 
     | 
    
         
            +
                    char_score = "#{char}"[0].ord * multiplier * multiplier
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    # Aggregate the swcore
         
     | 
| 
      
 27 
     | 
    
         
            +
                    score += char_score
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  score
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,87 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Flocks
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Relationships
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def relationship_following_key
         
     | 
| 
      
 5 
     | 
    
         
            +
                  "#{following_key}/#{user_id}"
         
     | 
| 
      
 6 
     | 
    
         
            +
                end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                def relationship_followers_key(id = user_id)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  "#{followers_key}/#{id}"
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def relationship_blocked_key
         
     | 
| 
      
 13 
     | 
    
         
            +
                  "#{blocked_key}/#{user_id}"
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def follow(other_user_id, other_username)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  return if (user_id == other_user_id) || (blocked? other_user_id)
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  other_username_score = rank_username(other_username)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  redis.zadd relationship_following_key, other_username_score, other_user_id
         
     | 
| 
      
 21 
     | 
    
         
            +
                  redis.zadd relationship_followers_key(other_user_id), username_score, user_id
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def unfollow(other_user_id)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  redis.zrem relationship_following_key, other_user_id
         
     | 
| 
      
 26 
     | 
    
         
            +
                  redis.zrem relationship_followers_key(other_user_id), user_id
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def following(page = 0, limit = 0)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  # Without arguments returns the full set
         
     | 
| 
      
 31 
     | 
    
         
            +
                  start, stop = bounds(page, limit)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  redis.zrange relationship_following_key, start, stop
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def followers(page = 0, limit= 0)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  start, stop = bounds(page, limit)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  redis.zrange relationship_followers_key(user_id), start, stop
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def following?(other_user_id)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  following.include? other_user_id.to_s
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def following_count
         
     | 
| 
      
 45 
     | 
    
         
            +
                  redis.zcard relationship_following_key
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def followers_count
         
     | 
| 
      
 49 
     | 
    
         
            +
                  redis.zcard relationship_followers_key
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def following_page_count(limit = page_size)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  (following_count.to_f / limit.to_f).ceil
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def followers_page_count(limit = page_size)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  (followers_count.to_f / limit.to_f).ceil
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def block(other_user_id)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  # Unfollow
         
     | 
| 
      
 62 
     | 
    
         
            +
                  unfollow other_user_id
         
     | 
| 
      
 63 
     | 
    
         
            +
                  self.new(other_user_id).unfollow user_id
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  # Block
         
     | 
| 
      
 66 
     | 
    
         
            +
                  redis.sadd relationship_blocked_key, other_user_id
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                def unblock(other_user_id)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  redis.srem relationship_blocked_key, other_user_id
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def blocked
         
     | 
| 
      
 74 
     | 
    
         
            +
                  redis.smembers relationship_blocked_key
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                def blocked?(other_user_id)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  blocked.include? other_user_id.to_s
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                protected
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                def bounds(page, limit)
         
     | 
| 
      
 84 
     | 
    
         
            +
                  [(page - 1) * limit, (page * limit) - 1]
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
              end
         
     | 
| 
      
 87 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Flocks
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Search
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                # Search a user's list of following
         
     | 
| 
      
 5 
     | 
    
         
            +
                def search_following(query)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  redis.zrangebyscore relationship_following_key, start_score(query), stop_score(query)
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # Search a user's list of followers
         
     | 
| 
      
 10 
     | 
    
         
            +
                def search_followers(query)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  redis.zrangebyscore relationship_followers_key, start_score(query), stop_score(query)
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                # Search a user's entire social graph
         
     | 
| 
      
 15 
     | 
    
         
            +
                def search_graph(query)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  (search_following(query) + search_followers(query)).uniq
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                protected
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                # Set constraints to return relevent results
         
     | 
| 
      
 22 
     | 
    
         
            +
                # Starting score for redis zrangebyscore
         
     | 
| 
      
 23 
     | 
    
         
            +
                def start_score(query)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  rank_username(query)
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                # 'aaa' -> 'aab'
         
     | 
| 
      
 28 
     | 
    
         
            +
                # Ending score for redis zrangebyscore
         
     | 
| 
      
 29 
     | 
    
         
            +
                def stop_score(query)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  query_array = query.chars
         
     | 
| 
      
 31 
     | 
    
         
            +
                  last_char = (query_array.pop.ord + 1).chr
         
     | 
| 
      
 32 
     | 
    
         
            +
                  stop_name = query_array.push(last_char).join('')
         
     | 
| 
      
 33 
     | 
    
         
            +
                  rank_username(stop_name)
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'test_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class ConfigurationTest < MiniTest::Test
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              def test_configuration
         
     | 
| 
      
 6 
     | 
    
         
            +
                Flocks.configure do |config|
         
     | 
| 
      
 7 
     | 
    
         
            +
                  config.redis = Redis.new
         
     | 
| 
      
 8 
     | 
    
         
            +
                  config.namespace = 'flocks_test'
         
     | 
| 
      
 9 
     | 
    
         
            +
                  config.following_key = 'following_test'
         
     | 
| 
      
 10 
     | 
    
         
            +
                  config.followers_key = 'followers_test'
         
     | 
| 
      
 11 
     | 
    
         
            +
                  config.blocked_key = 'blocked_test'
         
     | 
| 
      
 12 
     | 
    
         
            +
                  config.blocked_by_key = 'blocked_by_test'
         
     | 
| 
      
 13 
     | 
    
         
            +
                  config.page_size = 50
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                assert_equal 'flocks_test', Flocks.namespace
         
     | 
| 
      
 17 
     | 
    
         
            +
                assert_equal 'following_test', Flocks.following_key
         
     | 
| 
      
 18 
     | 
    
         
            +
                assert_equal 'followers_test', Flocks.followers_key
         
     | 
| 
      
 19 
     | 
    
         
            +
                assert_equal 'blocked_test', Flocks.blocked_key
         
     | 
| 
      
 20 
     | 
    
         
            +
                assert_equal 'blocked_by_test', Flocks.blocked_by_key
         
     | 
| 
      
 21 
     | 
    
         
            +
                assert_equal  50, Flocks.page_size
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,12 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'test_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class OrderingTest < MiniTest::Test
         
     | 
| 
      
 4 
     | 
    
         
            +
              include Flocks::Ordering
         
     | 
| 
      
 5 
     | 
    
         
            +
              include Flocks::Configuration
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              def test_score_string_extension
         
     | 
| 
      
 8 
     | 
    
         
            +
                # ASCII 'd' == 100, summed up in the scorer == 10101010100
         
     | 
| 
      
 9 
     | 
    
         
            +
                assert_equal 10101010100, rank_username('ddddd')
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,55 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'test_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class RelationshipsTest < MiniTest::Test
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              def test_follow_and_unfollow
         
     | 
| 
      
 6 
     | 
    
         
            +
                flock = Flocks.new(1, 'username')
         
     | 
| 
      
 7 
     | 
    
         
            +
                flock.follow(2, 'other_username')
         
     | 
| 
      
 8 
     | 
    
         
            +
                assert flock.following?(2)
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                flock.unfollow(2)
         
     | 
| 
      
 11 
     | 
    
         
            +
                refute flock.following?(2)
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              def test_following_and_following_count
         
     | 
| 
      
 15 
     | 
    
         
            +
                flock = Flocks.new(1, 'username')
         
     | 
| 
      
 16 
     | 
    
         
            +
                flock.follow(2, 'other_username')
         
     | 
| 
      
 17 
     | 
    
         
            +
                assert_equal ['2'], flock.following
         
     | 
| 
      
 18 
     | 
    
         
            +
                assert_equal 1, flock.following_count
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              def test_followers_and_followers_count
         
     | 
| 
      
 22 
     | 
    
         
            +
                flock = Flocks.new(1, 'username')
         
     | 
| 
      
 23 
     | 
    
         
            +
                flock.follow(2, 'other_username')
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                other_flock = Flocks.new(2, 'other_username')
         
     | 
| 
      
 26 
     | 
    
         
            +
                assert_equal ['1'], other_flock.followers
         
     | 
| 
      
 27 
     | 
    
         
            +
                assert_equal 1, other_flock.followers_count
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              def test_following_page_count
         
     | 
| 
      
 31 
     | 
    
         
            +
                flock = Flocks.new(1, 'username')
         
     | 
| 
      
 32 
     | 
    
         
            +
                (2..40).to_a.each { |i| flock.follow(i, "#{i}") }
         
     | 
| 
      
 33 
     | 
    
         
            +
                assert_equal 2, flock.following_page_count
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              def test_followers_page_count
         
     | 
| 
      
 37 
     | 
    
         
            +
                (2..40).to_a.each { |i| Flocks.new(i, "#{i}").follow(1, "username") }
         
     | 
| 
      
 38 
     | 
    
         
            +
                flock = Flocks.new(1, 'username')
         
     | 
| 
      
 39 
     | 
    
         
            +
                assert_equal 2, flock.followers_page_count
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              def test_block_blocked_and_unblock
         
     | 
| 
      
 43 
     | 
    
         
            +
                flock = Flocks.new(1, 'username')
         
     | 
| 
      
 44 
     | 
    
         
            +
                flock.follow(2, 'other_username')
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                flock.block(2)
         
     | 
| 
      
 47 
     | 
    
         
            +
                assert_equal ['2'], flock.blocked
         
     | 
| 
      
 48 
     | 
    
         
            +
                assert flock.blocked? 2
         
     | 
| 
      
 49 
     | 
    
         
            +
                refute Flocks.new(2).following? 1
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                flock.unblock(2)
         
     | 
| 
      
 52 
     | 
    
         
            +
                assert_equal ([]), flock.blocked
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'test_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class SearchTest < MiniTest::Test
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              def test_search_following
         
     | 
| 
      
 6 
     | 
    
         
            +
                flock = Flocks.new(1, 'username')
         
     | 
| 
      
 7 
     | 
    
         
            +
                flock.follow(2, 'other_username')
         
     | 
| 
      
 8 
     | 
    
         
            +
                flock.follow(3, 'other_username2')
         
     | 
| 
      
 9 
     | 
    
         
            +
                flock.follow(4, 'dissimilar_username')
         
     | 
| 
      
 10 
     | 
    
         
            +
                results = flock.search_following('other')
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                assert_equal ['2', '3'], results
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              def test_search_followers
         
     | 
| 
      
 16 
     | 
    
         
            +
                Flocks.new(2, 'other_username').follow(1, 'username')
         
     | 
| 
      
 17 
     | 
    
         
            +
                Flocks.new(3, 'other_username2').follow(1, 'username')
         
     | 
| 
      
 18 
     | 
    
         
            +
                Flocks.new(4, 'disssimilar_username').follow(1, 'username')
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                flock = Flocks.new(1, 'username')
         
     | 
| 
      
 21 
     | 
    
         
            +
                results = flock.search_followers('other')
         
     | 
| 
      
 22 
     | 
    
         
            +
                assert_equal ['2', '3'], results
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              def test_search_graph
         
     | 
| 
      
 26 
     | 
    
         
            +
                Flocks.new(1, 'username').follow(2, 'other_username')
         
     | 
| 
      
 27 
     | 
    
         
            +
                Flocks.new(2, 'other_username').follow(1, 'username')
         
     | 
| 
      
 28 
     | 
    
         
            +
                Flocks.new(1, 'username').follow(3, 'other_username3')
         
     | 
| 
      
 29 
     | 
    
         
            +
                Flocks.new(4, 'other_username4').follow(1, 'username')
         
     | 
| 
      
 30 
     | 
    
         
            +
                Flocks.new(5, 'disssimilar_username').follow(1, 'username')
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                flock = Flocks.new(1, 'username')
         
     | 
| 
      
 33 
     | 
    
         
            +
                results = flock.search_graph('other')
         
     | 
| 
      
 34 
     | 
    
         
            +
                assert_equal ['2', '3', '4'], results
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
    
        data/test/test_helper.rb
    ADDED
    
    | 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'bundler'
         
     | 
| 
      
 3 
     | 
    
         
            +
            Bundler.require :test
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require 'minitest/autorun'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'redis'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'flocks'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            # Support files
         
     | 
| 
      
 10 
     | 
    
         
            +
            Dir["#{File.expand_path(File.dirname(__FILE__))}/support/*.rb"].each do |file|
         
     | 
| 
      
 11 
     | 
    
         
            +
              require file
         
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            class MiniTest::Test
         
     | 
| 
      
 15 
     | 
    
         
            +
              def setup
         
     | 
| 
      
 16 
     | 
    
         
            +
                Flocks.configure do |config|
         
     | 
| 
      
 17 
     | 
    
         
            +
                  config.redis = Redis.new
         
     | 
| 
      
 18 
     | 
    
         
            +
                  config.namespace = 'flocks'
         
     | 
| 
      
 19 
     | 
    
         
            +
                  config.following_key = 'following'
         
     | 
| 
      
 20 
     | 
    
         
            +
                  config.followers_key = 'followers'
         
     | 
| 
      
 21 
     | 
    
         
            +
                  config.blocked_key = 'blocked'
         
     | 
| 
      
 22 
     | 
    
         
            +
                  config.blocked_by_key = 'blocked_by'
         
     | 
| 
      
 23 
     | 
    
         
            +
                  config.page_size = 25
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                Flocks.redis.flushdb
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,124 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: flocks
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.1
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Adam Ryan
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2014-05-07 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: redis
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: bundler
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '1.5'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '1.5'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 44 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 45 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 46 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 48 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 49 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 55 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 56 
     | 
    
         
            +
              name: minitest
         
     | 
| 
      
 57 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 58 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 59 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 60 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 62 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 63 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 64 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 65 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 66 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 67 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 69 
     | 
    
         
            +
            description: Single node social relationships using redis.
         
     | 
| 
      
 70 
     | 
    
         
            +
            email:
         
     | 
| 
      
 71 
     | 
    
         
            +
            - adam.g.ryan@gmail.com
         
     | 
| 
      
 72 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 73 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 74 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 75 
     | 
    
         
            +
            files:
         
     | 
| 
      
 76 
     | 
    
         
            +
            - ".gitignore"
         
     | 
| 
      
 77 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 78 
     | 
    
         
            +
            - LICENSE.txt
         
     | 
| 
      
 79 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 80 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 81 
     | 
    
         
            +
            - flocks.gemspec
         
     | 
| 
      
 82 
     | 
    
         
            +
            - lib/flocks.rb
         
     | 
| 
      
 83 
     | 
    
         
            +
            - lib/flocks/configuration.rb
         
     | 
| 
      
 84 
     | 
    
         
            +
            - lib/flocks/ordering.rb
         
     | 
| 
      
 85 
     | 
    
         
            +
            - lib/flocks/relationships.rb
         
     | 
| 
      
 86 
     | 
    
         
            +
            - lib/flocks/search.rb
         
     | 
| 
      
 87 
     | 
    
         
            +
            - lib/flocks/version.rb
         
     | 
| 
      
 88 
     | 
    
         
            +
            - test/flocks/configuration_test.rb
         
     | 
| 
      
 89 
     | 
    
         
            +
            - test/flocks/flocks_test.rb
         
     | 
| 
      
 90 
     | 
    
         
            +
            - test/flocks/ordering_test.rb
         
     | 
| 
      
 91 
     | 
    
         
            +
            - test/flocks/relationships_test.rb
         
     | 
| 
      
 92 
     | 
    
         
            +
            - test/flocks/search_test.rb
         
     | 
| 
      
 93 
     | 
    
         
            +
            - test/test_helper.rb
         
     | 
| 
      
 94 
     | 
    
         
            +
            homepage: https://github.com/byliner/flocks
         
     | 
| 
      
 95 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 96 
     | 
    
         
            +
            - BSD
         
     | 
| 
      
 97 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 98 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 99 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 100 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 101 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 102 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 103 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 104 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 105 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 106 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 107 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 108 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 109 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 110 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 111 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 112 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 113 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 114 
     | 
    
         
            +
            rubygems_version: 2.2.0
         
     | 
| 
      
 115 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 116 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 117 
     | 
    
         
            +
            summary: Single node social relationships using redis.
         
     | 
| 
      
 118 
     | 
    
         
            +
            test_files:
         
     | 
| 
      
 119 
     | 
    
         
            +
            - test/flocks/configuration_test.rb
         
     | 
| 
      
 120 
     | 
    
         
            +
            - test/flocks/flocks_test.rb
         
     | 
| 
      
 121 
     | 
    
         
            +
            - test/flocks/ordering_test.rb
         
     | 
| 
      
 122 
     | 
    
         
            +
            - test/flocks/relationships_test.rb
         
     | 
| 
      
 123 
     | 
    
         
            +
            - test/flocks/search_test.rb
         
     | 
| 
      
 124 
     | 
    
         
            +
            - test/test_helper.rb
         
     |