easyredis 0.0.5 → 0.0.6
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.
- data/Manifest +1 -1
- data/README.md +16 -19
- data/Rakefile +12 -10
- data/easyredis.gemspec +5 -5
- data/lib/easyredis.rb +175 -95
- data/tests/{test.rb → man.rb} +2 -2
- metadata +5 -5
    
        data/Manifest
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -14,9 +14,7 @@ Or, you can get the source with git: | |
| 14 14 |  | 
| 15 15 | 
             
                $ git clone git://github.com/alecbenzer/easyredis.git
         | 
| 16 16 |  | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
            Once you have the source, you can run:
         | 
| 17 | 
            +
            and run:
         | 
| 20 18 |  | 
| 21 19 | 
             
                $ rake manifest
         | 
| 22 20 | 
             
                $ rake build_gemspec
         | 
| @@ -53,17 +51,16 @@ Or, we can choose our own ids: | |
| 53 51 |  | 
| 54 52 | 
             
                p = Post.new("coolpost")
         | 
| 55 53 | 
             
                p.title = "A Cool Post"
         | 
| 56 | 
            -
                p.body = "This post has a high level of  | 
| 54 | 
            +
                p.body = "This post has a high level of coolness."
         | 
| 57 55 |  | 
| 58 56 | 
             
                p2 = Post.find("coolpost")  # this is a very fast lookup
         | 
| 59 57 | 
             
                p2.title  # => "A Cool Post"
         | 
| 60 58 |  | 
| 61 59 | 
             
            We also get a created_at field for free that we can sort by.
         | 
| 62 60 |  | 
| 63 | 
            -
                p.created_at | 
| 64 | 
            -
                Post.all  #  | 
| 65 | 
            -
                Post | 
| 66 | 
            -
                Post[41]  # the 42nd (0-based indexing) post that was created
         | 
| 61 | 
            +
                p.created_at              # a ruby Time object
         | 
| 62 | 
            +
                Post.all :order => :desc  # all posts ordered by descending time
         | 
| 63 | 
            +
                Post[n]                   # the nth (0-based indexing) post that was created
         | 
| 67 64 |  | 
| 68 65 | 
             
            ## Searching and Sorting
         | 
| 69 66 |  | 
| @@ -85,18 +82,18 @@ And also search: | |
| 85 82 | 
             
                Post.search_by :title, "A common title"  # all posts with this title
         | 
| 86 83 | 
             
                Post.find_by :title, "My First Post"  # just one post
         | 
| 87 84 |  | 
| 88 | 
            -
            ##  | 
| 85 | 
            +
            ## Implicit References
         | 
| 89 86 |  | 
| 90 | 
            -
             | 
| 87 | 
            +
            You may have noticed fields have not been given any types. EasyRedis automatically tracks the type of a field based on the type of data you assign it.
         | 
| 91 88 |  | 
| 92 | 
            -
             | 
| 93 | 
            -
                  field :title
         | 
| 94 | 
            -
                  field :body
         | 
| 89 | 
            +
            This works for references, too:
         | 
| 95 90 |  | 
| 96 | 
            -
             | 
| 91 | 
            +
                class Comment < EasyRedis::Model
         | 
| 92 | 
            +
                  field :text
         | 
| 93 | 
            +
                  field :post
         | 
| 97 94 | 
             
                end
         | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
                 | 
| 102 | 
            -
                 | 
| 95 | 
            +
                
         | 
| 96 | 
            +
                c = Comment.new
         | 
| 97 | 
            +
                c.text = "A comment!"
         | 
| 98 | 
            +
                
         | 
| 99 | 
            +
                c.post = Post[0]
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -2,9 +2,9 @@ require 'rubygems' | |
| 2 2 | 
             
            require 'rake'
         | 
| 3 3 | 
             
            require 'echoe'
         | 
| 4 4 |  | 
| 5 | 
            -
            Echoe.new('easyredis','0.0. | 
| 5 | 
            +
            Echoe.new('easyredis','0.0.6') do |p|
         | 
| 6 6 | 
             
              p.description = "framework designed to make using redis as a database simpler"
         | 
| 7 | 
            -
              p.url = " | 
| 7 | 
            +
              p.url = "http://alecbenzer.github.com/easyredis/"
         | 
| 8 8 | 
             
              p.author = "Alec Benzer"
         | 
| 9 9 | 
             
              p.email = "alecbezer @nospam@ gmail.com"
         | 
| 10 10 | 
             
              p.ignore_pattern = ["*.rdb"]
         | 
| @@ -13,7 +13,7 @@ end | |
| 13 13 |  | 
| 14 14 |  | 
| 15 15 | 
             
            require 'benchmark'
         | 
| 16 | 
            -
            require './tests/ | 
| 16 | 
            +
            require './tests/man'
         | 
| 17 17 |  | 
| 18 18 | 
             
            def rand_name(length=2)
         | 
| 19 19 | 
             
              chars = []
         | 
| @@ -24,14 +24,14 @@ end | |
| 24 24 |  | 
| 25 25 | 
             
            namespace :bm do
         | 
| 26 26 | 
             
              task :clear do
         | 
| 27 | 
            -
                puts "destroying #{Man.count} previous entries"
         | 
| 27 | 
            +
                puts "destroying #{Man.count} previous entries (sec)"
         | 
| 28 28 | 
             
                time = Benchmark.measure { Man.destroy_all }
         | 
| 29 29 | 
             
                puts time.format
         | 
| 30 30 | 
             
              end
         | 
| 31 31 |  | 
| 32 32 | 
             
              task :add do
         | 
| 33 33 | 
             
                count = ENV["count"] ? ENV["count"].to_i : 25000
         | 
| 34 | 
            -
                puts "adding #{count} new entries"
         | 
| 34 | 
            +
                puts "adding #{count} new entries (sec)"
         | 
| 35 35 | 
             
                time = Benchmark::Tms.new
         | 
| 36 36 | 
             
                length = Math.log(3*count,26).round
         | 
| 37 37 | 
             
                count.times do
         | 
| @@ -49,7 +49,7 @@ namespace :bm do | |
| 49 49 | 
             
                name = Man.rand.name
         | 
| 50 50 | 
             
                count = -1
         | 
| 51 51 | 
             
                time = Benchmark.measure { count = Man.search_by(:name,name).count }
         | 
| 52 | 
            -
                puts "retrived #{count} records in:"
         | 
| 52 | 
            +
                puts "retrived #{count} records in (ms):"
         | 
| 53 53 | 
             
                puts (time*1000).format
         | 
| 54 54 | 
             
              end
         | 
| 55 55 |  | 
| @@ -59,9 +59,9 @@ namespace :bm do | |
| 59 59 | 
             
                age = rand(100)
         | 
| 60 60 | 
             
                t1 = Benchmark.measure { Man.search(:age => age) }
         | 
| 61 61 | 
             
                t2 = Benchmark.measure { Man.search_by(:age,age) }
         | 
| 62 | 
            -
                puts "Model#search:"
         | 
| 62 | 
            +
                puts "Model#search (ms):"
         | 
| 63 63 | 
             
                puts (t1*1000).format
         | 
| 64 | 
            -
                puts "Model#search_by:"
         | 
| 64 | 
            +
                puts "Model#search_by (ms):"
         | 
| 65 65 | 
             
                puts (t2*1000).format
         | 
| 66 66 | 
             
                puts "search is #{((t1.real/t2.real) - 1)*100}% slower"
         | 
| 67 67 | 
             
              end
         | 
| @@ -72,15 +72,17 @@ namespace :bm do | |
| 72 72 | 
             
                age = man.age
         | 
| 73 73 | 
             
                count = 0
         | 
| 74 74 | 
             
                time = Benchmark.measure { count = Man.search(:name => name, :age => age).size }
         | 
| 75 | 
            -
                puts "retrived #{count} out of #{Man.count} entries in:"
         | 
| 75 | 
            +
                puts "retrived #{count} out of #{Man.count} entries in (ms):"
         | 
| 76 76 | 
             
                puts (time*1000).format
         | 
| 77 77 | 
             
              end
         | 
| 78 78 |  | 
| 79 79 | 
             
              task :find do
         | 
| 80 | 
            -
                puts "finding one of #{Man.count} entries by name"
         | 
| 80 | 
            +
                puts "finding one of #{Man.count} entries by name (ms)"
         | 
| 81 81 | 
             
                name = Man.rand.name
         | 
| 82 82 | 
             
                time = Benchmark.measure { Man.find_by(:name,name) }
         | 
| 83 83 | 
             
                puts (time*1000).format
         | 
| 84 84 | 
             
              end
         | 
| 85 85 |  | 
| 86 | 
            +
              task :all => [:populate, :search, :multisearch, :find]
         | 
| 87 | 
            +
             | 
| 86 88 | 
             
            end
         | 
    
        data/easyredis.gemspec
    CHANGED
    
    | @@ -2,20 +2,20 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            Gem::Specification.new do |s|
         | 
| 4 4 | 
             
              s.name = %q{easyredis}
         | 
| 5 | 
            -
              s.version = "0.0. | 
| 5 | 
            +
              s.version = "0.0.6"
         | 
| 6 6 |  | 
| 7 7 | 
             
              s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
         | 
| 8 8 | 
             
              s.authors = ["Alec Benzer"]
         | 
| 9 | 
            -
              s.date = %q{2011- | 
| 9 | 
            +
              s.date = %q{2011-05-16}
         | 
| 10 10 | 
             
              s.description = %q{framework designed to make using redis as a database simpler}
         | 
| 11 11 | 
             
              s.email = %q{alecbezer @nospam@ gmail.com}
         | 
| 12 12 | 
             
              s.extra_rdoc_files = ["LICENSE", "README.md", "lib/easyredis.rb"]
         | 
| 13 | 
            -
              s.files = ["LICENSE", "Manifest", "README.md", "Rakefile", "easyredis.gemspec", "lib/easyredis.rb", "tests/benchmark.rb", "tests/ | 
| 14 | 
            -
              s.homepage = %q{ | 
| 13 | 
            +
              s.files = ["LICENSE", "Manifest", "README.md", "Rakefile", "easyredis.gemspec", "lib/easyredis.rb", "tests/benchmark.rb", "tests/man.rb"]
         | 
| 14 | 
            +
              s.homepage = %q{http://alecbenzer.github.com/easyredis/}
         | 
| 15 15 | 
             
              s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Easyredis", "--main", "README.md"]
         | 
| 16 16 | 
             
              s.require_paths = ["lib"]
         | 
| 17 17 | 
             
              s.rubyforge_project = %q{easyredis}
         | 
| 18 | 
            -
              s.rubygems_version = %q{1. | 
| 18 | 
            +
              s.rubygems_version = %q{1.6.2}
         | 
| 19 19 | 
             
              s.summary = %q{framework designed to make using redis as a database simpler}
         | 
| 20 20 |  | 
| 21 21 | 
             
              if s.respond_to? :specification_version then
         | 
    
        data/lib/easyredis.rb
    CHANGED
    
    | @@ -12,7 +12,7 @@ require 'set' | |
| 12 12 | 
             
            # main EasyRedis module which
         | 
| 13 13 | 
             
            # holds all classes and helper methods
         | 
| 14 14 | 
             
            module EasyRedis
         | 
| 15 | 
            -
             | 
| 15 | 
            +
             | 
| 16 16 | 
             
              # generate a 'score' for a string
         | 
| 17 17 | 
             
              # used for storing it in a sorted set
         | 
| 18 18 | 
             
              #
         | 
| @@ -81,10 +81,10 @@ module EasyRedis | |
| 81 81 | 
             
                end
         | 
| 82 82 | 
             
              end
         | 
| 83 83 |  | 
| 84 | 
            -
              # exception that indicates that the given field has not been indexed for  | 
| 85 | 
            -
              class  | 
| 84 | 
            +
              # exception that indicates that the given field has not been indexed for sorting/searching
         | 
| 85 | 
            +
              class FieldNotSearchable < RuntimeError
         | 
| 86 86 | 
             
                def initialize(field)
         | 
| 87 | 
            -
                  @message = "field '#{field.to_s}' not  | 
| 87 | 
            +
                  @message = "field '#{field.to_s}' not searchable"
         | 
| 88 88 | 
             
                end
         | 
| 89 89 |  | 
| 90 90 | 
             
                def to_s
         | 
| @@ -92,6 +92,17 @@ module EasyRedis | |
| 92 92 | 
             
                end
         | 
| 93 93 | 
             
              end
         | 
| 94 94 |  | 
| 95 | 
            +
              # exception that indicates that the given field has not been indexed for text-searching
         | 
| 96 | 
            +
              # class FieldNotTextSearchable < RuntimeError
         | 
| 97 | 
            +
              #  def initialize(field)
         | 
| 98 | 
            +
              #    @message = "field '#{field.to_s}' not text-searchable"
         | 
| 99 | 
            +
              #  end
         | 
| 100 | 
            +
              #  
         | 
| 101 | 
            +
              #  def to_s
         | 
| 102 | 
            +
              #    @message
         | 
| 103 | 
            +
              #  end
         | 
| 104 | 
            +
              # end
         | 
| 105 | 
            +
             | 
| 95 106 | 
             
              # exception that indicated an unknown ordering option was encountered
         | 
| 96 107 | 
             
              class UnknownOrderOption < RuntimeError
         | 
| 97 108 | 
             
                def initialize(opt)
         | 
| @@ -107,6 +118,10 @@ module EasyRedis | |
| 107 118 | 
             
              class Collection
         | 
| 108 119 | 
             
                include Enumerable
         | 
| 109 120 |  | 
| 121 | 
            +
                def initialize(&p)
         | 
| 122 | 
            +
                  @access = p
         | 
| 123 | 
            +
                end
         | 
| 124 | 
            +
             | 
| 110 125 | 
             
                # access elements in this sort
         | 
| 111 126 | 
             
                #
         | 
| 112 127 | 
             
                # Work's like an Array's [] method. It can take a specific index, a range, or an offset and an amount/limit.
         | 
| @@ -151,71 +166,33 @@ module EasyRedis | |
| 151 166 | 
             
                  end
         | 
| 152 167 | 
             
                end
         | 
| 153 168 |  | 
| 154 | 
            -
                private
         | 
| 155 | 
            -
             | 
| 156 | 
            -
                # access the elements corresponding to the given range
         | 
| 157 | 
            -
                #
         | 
| 158 | 
            -
                # meant to be overridden in child classes
         | 
| 159 | 
            -
                def access(range)
         | 
| 160 | 
            -
                  []
         | 
| 161 | 
            -
                end
         | 
| 162 | 
            -
             | 
| 163 | 
            -
              end
         | 
| 164 | 
            -
             | 
| 165 | 
            -
              # class representing a sort
         | 
| 166 | 
            -
              class Sort < Collection
         | 
| 167 | 
            -
             | 
| 168 | 
            -
                # initialize the sort with a specific field, ordering option, and model
         | 
| 169 | 
            -
                #
         | 
| 170 | 
            -
                # @param [Symbol] field a symbol corresponding to a field of klass
         | 
| 171 | 
            -
                # @param [:asc, :desc] order a symbol specifying to sort in either ascending or descending order
         | 
| 172 | 
            -
                # @param [Class] klass the klass whose entries we are accessing
         | 
| 173 | 
            -
                def initialize(field,order,klass)
         | 
| 174 | 
            -
                  raise EasyRedis::FieldNotSortable, field  unless klass.sortable?(field) 
         | 
| 175 | 
            -
                  raise EasyRedis::UnknownOrderOption, order  unless [:asc,:desc].member? order
         | 
| 176 | 
            -
                  @field = field
         | 
| 177 | 
            -
                  @order = order
         | 
| 178 | 
            -
                  @klass = klass
         | 
| 179 | 
            -
                end
         | 
| 180 | 
            -
             | 
| 181 | 
            -
                # return the number of elements in this sort
         | 
| 182 | 
            -
                #
         | 
| 183 | 
            -
                # As of now, idential to the Model's count method.
         | 
| 184 | 
            -
                # This method is explicility defined here to overwrite the default one in Enumerable, which iterates through all the entries to count them, which is much slower than a ZCARD command
         | 
| 185 | 
            -
                def count
         | 
| 186 | 
            -
                  @count ||= EasyRedis.redis.zcard(@klass.sort_key(@field))
         | 
| 187 | 
            -
                  @count
         | 
| 188 | 
            -
                end
         | 
| 189 | 
            -
             | 
| 190 169 | 
             
                def inspect
         | 
| 191 | 
            -
                  "#<EasyRedis:: | 
| 170 | 
            +
                  "#<EasyRedis::Collection>"
         | 
| 192 171 | 
             
                end
         | 
| 193 172 |  | 
| 194 173 | 
             
                private
         | 
| 195 174 |  | 
| 196 | 
            -
                #  | 
| 175 | 
            +
                # access the elements corresponding to the given range
         | 
| 176 | 
            +
                #
         | 
| 177 | 
            +
                # meant to be overridden in child classes
         | 
| 197 178 | 
             
                def access(range)
         | 
| 198 | 
            -
                   | 
| 199 | 
            -
             | 
| 200 | 
            -
                   | 
| 201 | 
            -
             | 
| 202 | 
            -
                  if @order == :asc
         | 
| 203 | 
            -
                    ids = EasyRedis.redis.zrange(@klass.sort_key(@field),a,b)
         | 
| 204 | 
            -
                  elsif @order == :desc
         | 
| 205 | 
            -
                    ids = EasyRedis.redis.zrevrange(@klass.sort_key(@field),a,b)
         | 
| 179 | 
            +
                  if @access
         | 
| 180 | 
            +
                    @access[range]
         | 
| 181 | 
            +
                  else
         | 
| 182 | 
            +
                    []
         | 
| 206 183 | 
             
                  end
         | 
| 207 | 
            -
                  ids.map{|i|@klass.build(i)}
         | 
| 208 184 | 
             
                end
         | 
| 209 185 |  | 
| 210 186 | 
             
              end
         | 
| 211 187 |  | 
| 212 | 
            -
             | 
| 213 188 | 
             
              # class representing a data model
         | 
| 214 189 | 
             
              # you want to store in redis
         | 
| 215 190 | 
             
              class Model
         | 
| 216 191 |  | 
| 217 192 | 
             
                @@sorts = []
         | 
| 218 | 
            -
                @@ | 
| 193 | 
            +
                @@searches = []
         | 
| 194 | 
            +
                @@types = {}
         | 
| 195 | 
            +
                # @@text_searches = []
         | 
| 219 196 |  | 
| 220 197 | 
             
                # add a field to the model
         | 
| 221 198 | 
             
                #
         | 
| @@ -233,42 +210,77 @@ module EasyRedis | |
| 233 210 | 
             
                    if prev
         | 
| 234 211 | 
             
                      prev
         | 
| 235 212 | 
             
                    else
         | 
| 236 | 
            -
                       | 
| 213 | 
            +
                      data = EasyRedis.redis.hget(key_name,name)
         | 
| 214 | 
            +
                      type = get_type(name)
         | 
| 215 | 
            +
                      if type == 'int'
         | 
| 216 | 
            +
                        data = data.to_i
         | 
| 217 | 
            +
                      elsif type == 'flt'
         | 
| 218 | 
            +
                        data = data.to_f
         | 
| 219 | 
            +
                      elsif type == 'str'
         | 
| 220 | 
            +
                        data = data.to_s
         | 
| 221 | 
            +
                      elsif type.match /^model:/
         | 
| 222 | 
            +
                        klass = eval(type[6..-1])
         | 
| 223 | 
            +
                        data = klass.find(data)
         | 
| 224 | 
            +
                      end
         | 
| 225 | 
            +
                      instance_variable_set(instance_var,data)
         | 
| 237 226 | 
             
                    end
         | 
| 238 227 | 
             
                  end
         | 
| 239 228 |  | 
| 240 229 | 
             
                  define_method setter.to_sym do |val|
         | 
| 241 | 
            -
                    EasyRedis.redis.hset(key_name,name,Marshal.dump(val))
         | 
| 242 230 | 
             
                    instance_variable_set(instance_var,val)
         | 
| 231 | 
            +
                    if val.is_a? Fixnum
         | 
| 232 | 
            +
                      set_type(name,'int')
         | 
| 233 | 
            +
                    elsif val.is_a? Float
         | 
| 234 | 
            +
                      set_type(name,'flt')
         | 
| 235 | 
            +
                    elsif val.is_a? String
         | 
| 236 | 
            +
                      set_type(name,'str')
         | 
| 237 | 
            +
                    elsif val.is_a? EasyRedis::Model
         | 
| 238 | 
            +
                      set_type(name,"model:#{val.class.name}")
         | 
| 239 | 
            +
                      val = val.id
         | 
| 240 | 
            +
                    end # TODO: else.... marshall it
         | 
| 241 | 
            +
                    EasyRedis.redis.hset(key_name,name,val)
         | 
| 243 242 |  | 
| 244 243 | 
             
                    if self.class.sortable? name.to_sym
         | 
| 245 244 | 
             
                      EasyRedis.redis.zadd(sort_key(name),EasyRedis.score(val),@id)
         | 
| 246 245 | 
             
                    end
         | 
| 247 246 |  | 
| 248 | 
            -
                    if self.class. | 
| 249 | 
            -
                       | 
| 250 | 
            -
                        EasyRedis.redis.zadd term_key(name,term), created_at.to_i, id
         | 
| 251 | 
            -
                        EasyRedis.redis.zadd terms_key(name), EasyRedis.score(term), term
         | 
| 252 | 
            -
                      end
         | 
| 247 | 
            +
                    if self.class.searchable? name
         | 
| 248 | 
            +
                      EasyRedis.redis.sadd(search_key(name,val),@id)
         | 
| 253 249 | 
             
                    end
         | 
| 250 | 
            +
             | 
| 251 | 
            +
                    #if self.class.text_search? name.to_sym
         | 
| 252 | 
            +
                    #  val.split.each do |term|
         | 
| 253 | 
            +
                    #    EasyRedis.redis.zadd term_key(name,term), created_at.to_i, id
         | 
| 254 | 
            +
                    #    EasyRedis.redis.zadd terms_key(name), EasyRedis.score(term), term
         | 
| 255 | 
            +
                    #  end
         | 
| 256 | 
            +
                    #end
         | 
| 254 257 | 
             
                  end
         | 
| 255 258 | 
             
                end
         | 
| 256 259 |  | 
| 257 | 
            -
                # index a field to be sorted | 
| 260 | 
            +
                # index a field to be sorted
         | 
| 258 261 | 
             
                #
         | 
| 259 262 | 
             
                # @param (see #field)
         | 
| 260 263 | 
             
                def self.sort_on(field)
         | 
| 261 264 | 
             
                  @@sorts << field.to_sym
         | 
| 265 | 
            +
                  nil
         | 
| 262 266 | 
             
                end
         | 
| 263 267 |  | 
| 264 | 
            -
                # index a field  | 
| 268 | 
            +
                # index a field to be searched (with exact matches)
         | 
| 265 269 | 
             
                #
         | 
| 266 270 | 
             
                # @param (see #field)
         | 
| 267 | 
            -
                def self. | 
| 268 | 
            -
                  @@ | 
| 269 | 
            -
                   | 
| 271 | 
            +
                def self.search_on(field)
         | 
| 272 | 
            +
                  @@searches << field.to_sym
         | 
| 273 | 
            +
                  nil
         | 
| 270 274 | 
             
                end
         | 
| 271 275 |  | 
| 276 | 
            +
                # index a field for text searching
         | 
| 277 | 
            +
                #
         | 
| 278 | 
            +
                # @param (see #field)
         | 
| 279 | 
            +
                # def self.text_search(field)
         | 
| 280 | 
            +
                #  @@text_searches << field.to_sym
         | 
| 281 | 
            +
                #  sort_on(field) unless sortable? field
         | 
| 282 | 
            +
                # end
         | 
| 283 | 
            +
             | 
| 272 284 | 
             
                # returns number of instances of this model
         | 
| 273 285 | 
             
                def self.count
         | 
| 274 286 | 
             
                  EasyRedis.redis.zcard(prefix)
         | 
| @@ -296,10 +308,15 @@ module EasyRedis | |
| 296 308 | 
             
                end
         | 
| 297 309 |  | 
| 298 310 | 
             
                # find an entry of this model based on its id
         | 
| 311 | 
            +
                # OR, find an entry based on field/value pairs in a hash
         | 
| 312 | 
            +
                # (current only works with one pair)
         | 
| 299 313 | 
             
                #
         | 
| 300 | 
            -
                # @param [Integer] id the id of the entry to retrive
         | 
| 314 | 
            +
                # @param [Integer,Hash] id the id of the entry to retrive, or a hash of field/value pairs
         | 
| 301 315 | 
             
                def self.find(id)
         | 
| 302 | 
            -
                  if  | 
| 316 | 
            +
                  if id.is_a? Hash
         | 
| 317 | 
            +
                    pair = id.to_a.first
         | 
| 318 | 
            +
                    self.find_by(pair[0],pair[1]) # TODO: add support for multiple field/value pairs
         | 
| 319 | 
            +
                  elsif EasyRedis.redis.zscore(prefix,id)
         | 
| 303 320 | 
             
                    build(id)
         | 
| 304 321 | 
             
                  else
         | 
| 305 322 | 
             
                    nil
         | 
| @@ -318,10 +335,10 @@ module EasyRedis | |
| 318 335 | 
             
                # @param [Symbol] field a symbol representing the field to search on
         | 
| 319 336 | 
             
                # @param val the value of field to search for
         | 
| 320 337 | 
             
                def self.search_by(field, val, options = {})
         | 
| 321 | 
            -
                   | 
| 322 | 
            -
                  scr = EasyRedis.score(val)
         | 
| 338 | 
            +
                  # scr = EasyRedis.score(val)
         | 
| 323 339 | 
             
                  # options[:limit] = [0,options[:limit]] if options[:limit]
         | 
| 324 | 
            -
                  ids = EasyRedis.redis.zrangebyscore(sort_key(field),scr,scr,proc_options(options))
         | 
| 340 | 
            +
                  # ids = EasyRedis.redis.zrangebyscore(sort_key(field),scr,scr,proc_options(options))
         | 
| 341 | 
            +
                  ids = EasyRedis.redis.smembers(search_key(field,val))
         | 
| 325 342 | 
             
                  ids.map{|i| build(i) }
         | 
| 326 343 | 
             
                end
         | 
| 327 344 |  | 
| @@ -329,67 +346,92 @@ module EasyRedis | |
| 329 346 | 
             
                #
         | 
| 330 347 | 
             
                # @param (see #search_by)
         | 
| 331 348 | 
             
                def self.find_by(field,val)
         | 
| 332 | 
            -
                   | 
| 349 | 
            +
                  i = EasyRedis.redis.srandmember(search_key(field,val))
         | 
| 350 | 
            +
                  build(i) if i
         | 
| 333 351 | 
             
                end
         | 
| 334 352 |  | 
| 335 353 | 
             
                # search the model based on multiple parameters
         | 
| 336 354 | 
             
                #
         | 
| 337 355 | 
             
                # @param [Hash] params a hash of field => value pairs
         | 
| 338 356 | 
             
                def self.search(params)
         | 
| 339 | 
            -
                  return search_by(*params.first) if params.size == 1 | 
| 340 | 
            -
                   | 
| 341 | 
            -
             | 
| 342 | 
            -
                     | 
| 343 | 
            -
             | 
| 344 | 
            -
                    result_set =  | 
| 357 | 
            +
                  return search_by(*params.first) if params.size == 1
         | 
| 358 | 
            +
                  if params.all? {|f,v| searchable? f }
         | 
| 359 | 
            +
                    ids = EasyRedis.redis.sinter(*params.map{|k,v|search_key(k,v)})
         | 
| 360 | 
            +
                    ids.map{|i|build(i)}
         | 
| 361 | 
            +
                  elsif params.all? {|f,v| sortable? f}
         | 
| 362 | 
            +
                    result_set = nil
         | 
| 363 | 
            +
                    params.each do |field,value|
         | 
| 364 | 
            +
                      scr = EasyRedis.score(value)
         | 
| 365 | 
            +
                      ids = EasyRedis.redis.zrangebyscore(sort_key(field),scr,scr)
         | 
| 366 | 
            +
                      result_set = result_set ? (result_set & Set.new(ids)) : Set.new(ids)
         | 
| 367 | 
            +
                    end
         | 
| 368 | 
            +
                    result_set.map{|i|build(i)}
         | 
| 369 | 
            +
                  else
         | 
| 370 | 
            +
                    raise "fields must all be searchable or all be sortable"
         | 
| 345 371 | 
             
                  end
         | 
| 346 | 
            -
                  result_set.map{|i|build(i)}
         | 
| 347 372 | 
             
                end
         | 
| 348 373 |  | 
| 349 374 | 
             
                # get all entries, sorted by the given field
         | 
| 350 375 | 
             
                def self.sort_by(field,options = {:order => :asc})
         | 
| 351 | 
            -
                  EasyRedis:: | 
| 376 | 
            +
                  raise EasyRedis::FieldNotSortable unless self.sortable? field
         | 
| 377 | 
            +
                  EasyRedis::Collection.new do |range|
         | 
| 378 | 
            +
                    a = range.begin
         | 
| 379 | 
            +
                    b = range.end
         | 
| 380 | 
            +
                    b -= 1 if range.exclude_end?
         | 
| 381 | 
            +
                    ids = []
         | 
| 382 | 
            +
                    if options[:order] == :asc
         | 
| 383 | 
            +
                      ids = EasyRedis.redis.zrange(sort_key(field),a,b)
         | 
| 384 | 
            +
                    elsif options[:order] == :desc
         | 
| 385 | 
            +
                      ids = EasyRedis.redis.zrevrange(sort_key(field),a,b)
         | 
| 386 | 
            +
                    end
         | 
| 387 | 
            +
                    ids.map{|i| build(i)}
         | 
| 388 | 
            +
                  end
         | 
| 352 389 | 
             
                end
         | 
| 353 390 |  | 
| 354 391 | 
             
                # gives all values for the given field that begin with str
         | 
| 355 392 | 
             
                #
         | 
| 356 393 | 
             
                # @param [Symbol] field a symbol representing a field indexed with text_search.
         | 
| 357 | 
            -
                def self.matches(field,str)
         | 
| 358 | 
            -
             | 
| 359 | 
            -
             | 
| 360 | 
            -
             | 
| 361 | 
            -
             | 
| 362 | 
            -
                end
         | 
| 394 | 
            +
                # def self.matches(field,str)
         | 
| 395 | 
            +
                #  raise EasyRedis::FieldNotTextSearchable, field unless self.text_search? field
         | 
| 396 | 
            +
                #  scr = EasyRedis.score(str)
         | 
| 397 | 
            +
                #  a,b = scr, scr+1/(27.0**str.size)
         | 
| 398 | 
            +
                #  EasyRedis.redis.zrangebyscore(terms_key(field), "#{a}", "(#{b}")
         | 
| 399 | 
            +
                # end
         | 
| 363 400 |  | 
| 364 401 | 
             
                # searches for all entries where field contains the string str
         | 
| 365 402 | 
             
                #
         | 
| 366 403 | 
             
                # The string must appear exactly as a term in field's value. To search based on the beginning of a term, you can combine this method with matches.
         | 
| 367 404 | 
             
                # The field must have been indexed with text_search.
         | 
| 368 | 
            -
                def self.match(field,str, options = {})
         | 
| 369 | 
            -
             | 
| 370 | 
            -
             | 
| 371 | 
            -
             | 
| 372 | 
            -
                end
         | 
| 405 | 
            +
                # def self.match(field,str, options = {})
         | 
| 406 | 
            +
                #  raise EasyRedis::FieldNotTextSearchable, filename unless text_search? field
         | 
| 407 | 
            +
                #  ids = EasyRedis.redis.zrange(term_key(field,str), 0, -1, proc_options(options))
         | 
| 408 | 
            +
                #  ids.map{|i| build(i)}
         | 
| 409 | 
            +
                # end
         | 
| 373 410 |  | 
| 374 411 | 
             
                # indicates whether field has been indexed with sort_on
         | 
| 375 412 | 
             
                def self.sortable?(field)
         | 
| 376 413 | 
             
                  @@sorts and (@@sorts.member? field or field.to_sym == :created_at)
         | 
| 377 414 | 
             
                end
         | 
| 378 415 |  | 
| 379 | 
            -
                # indicates whether field has been indexed with  | 
| 380 | 
            -
                def self. | 
| 381 | 
            -
                  @@ | 
| 416 | 
            +
                # indicates whether field has been indexed with sort_on
         | 
| 417 | 
            +
                def self.searchable?(field)
         | 
| 418 | 
            +
                  @@searches and @@searches.member? field.to_sym
         | 
| 382 419 | 
             
                end
         | 
| 383 420 |  | 
| 421 | 
            +
                # indicates whether field has been indexed with text_search
         | 
| 422 | 
            +
                # def self.text_search?(field)
         | 
| 423 | 
            +
                #  @@text_searches and @@text_searches.member?(field)
         | 
| 424 | 
            +
                # end
         | 
| 425 | 
            +
             | 
| 384 426 | 
             
                # destroy all instances of this model
         | 
| 385 427 | 
             
                def self.destroy_all
         | 
| 386 428 | 
             
                  all.each {|x| x.destroy}
         | 
| 387 429 | 
             
                  @@sorts.each {|field| EasyRedis.redis.del(sort_key(field)) }
         | 
| 388 | 
            -
                  @@text_searches.each {|field| EasyRedis.redis.del(terms_key(field)) }
         | 
| 430 | 
            +
                  # @@text_searches.each {|field| EasyRedis.redis.del(terms_key(field)) }
         | 
| 389 431 | 
             
                  EasyRedis.redis.del(prefix)
         | 
| 390 432 | 
             
                  EasyRedis.redis.del(prefix + ":next_id")
         | 
| 391 433 | 
             
                end
         | 
| 392 | 
            -
             | 
| 434 | 
            +
             | 
| 393 435 |  | 
| 394 436 | 
             
                # the id of this entry
         | 
| 395 437 | 
             
                attr_reader :id
         | 
| @@ -489,6 +531,10 @@ module EasyRedis | |
| 489 531 | 
             
                  end
         | 
| 490 532 | 
             
                end
         | 
| 491 533 |  | 
| 534 | 
            +
                def self.search_key(field,value)
         | 
| 535 | 
            +
                  "#{prefix}:search_#{field}:#{value}"
         | 
| 536 | 
            +
                end
         | 
| 537 | 
            +
             | 
| 492 538 | 
             
                def self.terms_key(field)
         | 
| 493 539 | 
             
                  "#{prefix}:terms_#{field.to_s}"
         | 
| 494 540 | 
             
                end
         | 
| @@ -497,6 +543,23 @@ module EasyRedis | |
| 497 543 | 
             
                  "#{prefix}:term_#{field}:#{term}"
         | 
| 498 544 | 
             
                end
         | 
| 499 545 |  | 
| 546 | 
            +
                def self.type_key(field)
         | 
| 547 | 
            +
                  "#{prefix}:type_#{field}"
         | 
| 548 | 
            +
                end
         | 
| 549 | 
            +
             | 
| 550 | 
            +
                def self.get_type(field)
         | 
| 551 | 
            +
                  if @@types[field]
         | 
| 552 | 
            +
                    @@types[field]
         | 
| 553 | 
            +
                  else
         | 
| 554 | 
            +
                    @@types[field] = EasyRedis.redis.get(type_key(field))
         | 
| 555 | 
            +
                  end
         | 
| 556 | 
            +
                end
         | 
| 557 | 
            +
             | 
| 558 | 
            +
                def self.set_type(field,type)
         | 
| 559 | 
            +
                  EasyRedis.redis.set(type_key(field),type)
         | 
| 560 | 
            +
                  @@types[field] = type
         | 
| 561 | 
            +
                end
         | 
| 562 | 
            +
             | 
| 500 563 | 
             
                def prefix
         | 
| 501 564 | 
             
                  self.class.prefix
         | 
| 502 565 | 
             
                end
         | 
| @@ -505,6 +568,10 @@ module EasyRedis | |
| 505 568 | 
             
                  self.class.sort_key(field)
         | 
| 506 569 | 
             
                end
         | 
| 507 570 |  | 
| 571 | 
            +
                def search_key(field,val)
         | 
| 572 | 
            +
                  self.class.search_key(field,val)
         | 
| 573 | 
            +
                end
         | 
| 574 | 
            +
             | 
| 508 575 | 
             
                def terms_key(field)
         | 
| 509 576 | 
             
                  self.class.terms_key(field)
         | 
| 510 577 | 
             
                end
         | 
| @@ -512,5 +579,18 @@ module EasyRedis | |
| 512 579 | 
             
                def term_key(field,term)
         | 
| 513 580 | 
             
                  self.class.term_key(field,term)
         | 
| 514 581 | 
             
                end
         | 
| 582 | 
            +
             | 
| 583 | 
            +
                def type_key(field)
         | 
| 584 | 
            +
                  self.class.type_key(field)
         | 
| 585 | 
            +
                end
         | 
| 586 | 
            +
             | 
| 587 | 
            +
                def get_type(field)
         | 
| 588 | 
            +
                  self.class.get_type(field)
         | 
| 589 | 
            +
                end
         | 
| 590 | 
            +
             | 
| 591 | 
            +
                def set_type(field,type)
         | 
| 592 | 
            +
                  self.class.set_type(field,type)
         | 
| 593 | 
            +
                end
         | 
| 594 | 
            +
             | 
| 515 595 | 
             
              end
         | 
| 516 596 | 
             
            end
         | 
    
        data/tests/{test.rb → man.rb}
    RENAMED
    
    
    
        metadata
    CHANGED
    
    | @@ -2,7 +2,7 @@ | |
| 2 2 | 
             
            name: easyredis
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 4 | 
             
              prerelease: 
         | 
| 5 | 
            -
              version: 0.0. | 
| 5 | 
            +
              version: 0.0.6
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors: 
         | 
| 8 8 | 
             
            - Alec Benzer
         | 
| @@ -10,7 +10,7 @@ autorequire: | |
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 12 |  | 
| 13 | 
            -
            date: 2011- | 
| 13 | 
            +
            date: 2011-05-16 00:00:00 -04:00
         | 
| 14 14 | 
             
            default_executable: 
         | 
| 15 15 | 
             
            dependencies: 
         | 
| 16 16 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| @@ -42,9 +42,9 @@ files: | |
| 42 42 | 
             
            - easyredis.gemspec
         | 
| 43 43 | 
             
            - lib/easyredis.rb
         | 
| 44 44 | 
             
            - tests/benchmark.rb
         | 
| 45 | 
            -
            - tests/ | 
| 45 | 
            +
            - tests/man.rb
         | 
| 46 46 | 
             
            has_rdoc: true
         | 
| 47 | 
            -
            homepage:  | 
| 47 | 
            +
            homepage: http://alecbenzer.github.com/easyredis/
         | 
| 48 48 | 
             
            licenses: []
         | 
| 49 49 |  | 
| 50 50 | 
             
            post_install_message: 
         | 
| @@ -72,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 72 72 | 
             
            requirements: []
         | 
| 73 73 |  | 
| 74 74 | 
             
            rubyforge_project: easyredis
         | 
| 75 | 
            -
            rubygems_version: 1. | 
| 75 | 
            +
            rubygems_version: 1.6.2
         | 
| 76 76 | 
             
            signing_key: 
         | 
| 77 77 | 
             
            specification_version: 3
         | 
| 78 78 | 
             
            summary: framework designed to make using redis as a database simpler
         |