BrianTheCoder-cool_breeze 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 1.0.0 / 2009-03-21
2
+
3
+ * 1 major enhancement
4
+ * Birthday!
data/README.txt ADDED
@@ -0,0 +1,56 @@
1
+ cool_breeze
2
+ by Brian Smith
3
+ http://brianthecoder.com
4
+ brian@46blocks.com
5
+
6
+ == DESCRIPTION:
7
+
8
+ The most awesomest thing ever
9
+
10
+ == FEATURES/PROBLEMS:
11
+
12
+ * need to write tests for queries
13
+ * uniqueness validator
14
+ * finish up indexes
15
+ * allow other data stores (bit table, simple db, couch?)
16
+
17
+ == SYNOPSIS:
18
+
19
+ * coming soon
20
+
21
+ == REQUIREMENTS:
22
+
23
+ * guid
24
+ * extlib
25
+ * validatable
26
+ * redis
27
+ * rufus-tokyo (ruby-tokyotyrant when its ready)
28
+
29
+ == INSTALL:
30
+
31
+ * its a gem on github, you should know the routine by now
32
+
33
+ == LICENSE:
34
+
35
+ (The MIT License)
36
+
37
+ Copyright (c) 2008 FIXME (different license?)
38
+
39
+ Permission is hereby granted, free of charge, to any person obtaining
40
+ a copy of this software and associated documentation files (the
41
+ 'Software'), to deal in the Software without restriction, including
42
+ without limitation the rights to use, copy, modify, merge, publish,
43
+ distribute, sublicense, and/or sell copies of the Software, and to
44
+ permit persons to whom the Software is furnished to do so, subject to
45
+ the following conditions:
46
+
47
+ The above copyright notice and this permission notice shall be
48
+ included in all copies or substantial portions of the Software.
49
+
50
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
51
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
52
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
53
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
54
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
55
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
56
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "cool_breeze"
8
+ gem.summary = %Q{A new type of orm utilizing two different storage mechanisms to the best of their abilities}
9
+ gem.email = "wbsmith83@gmail.com"
10
+ gem.homepage = "http://github.com/BrianTheCoder/cool_breeze"
11
+ gem.authors = ["brianthecoder"]
12
+
13
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
+ end
15
+ rescue LoadError
16
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
17
+ end
18
+
19
+ require 'rake/testtask'
20
+ Rake::TestTask.new(:test) do |test|
21
+ test.libs << 'lib' << 'test'
22
+ test.pattern = 'test/**/*_test.rb'
23
+ test.verbose = false
24
+ end
25
+
26
+ begin
27
+ require 'rcov/rcovtask'
28
+ Rcov::RcovTask.new do |test|
29
+ test.libs << 'test'
30
+ test.pattern = 'test/**/*_test.rb'
31
+ test.verbose = true
32
+ end
33
+ rescue LoadError
34
+ task :rcov do
35
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
36
+ end
37
+ end
38
+
39
+
40
+ task :default => :test
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ if File.exist?('VERSION.yml')
45
+ config = YAML.load(File.read('VERSION.yml'))
46
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
47
+ else
48
+ version = ""
49
+ end
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "Cool Breeze #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
56
+
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 3
3
+ :patch: 0
4
+ :major: 0
data/bin/cool_breeze ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ puts "Its getting cold in here"
3
+
4
+ system("redis-server redis.conf")
5
+
6
+ puts "Redis started"
7
+ ROOT = File.expand_path(File.join(File.dirname(__FILE__)),'..')
8
+
9
+ TokyoConfig = {
10
+ :port => 45000,
11
+ :data_file => File.join(ROOT,'log','tokyo.tct'),
12
+ :pid_file => File.join(ROOT,'log','tokyo.pid'),
13
+ :log_file => File.join(ROOT,'log','tokyo.log')
14
+ }
15
+
16
+ system("ttserver -dmn -port #{TokyoConfig[:port]} -log #{TokyoConfig[:log_file]} -pid #{TokyoConfig[:pid_file]} #{TokyoConfig[:data_file]}")
17
+
18
+ puts "Tokyo server started"
19
+ puts "Lets rock and roll!"
data/bin/redis.conf ADDED
@@ -0,0 +1,66 @@
1
+ # Redis configuration file example
2
+
3
+ # By default Redis does not run as a daemon. Use 'yes' if you need it.
4
+ # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
5
+ daemonize yes
6
+
7
+ # Accept connections on the specified port, default is 6379
8
+ port 6379
9
+
10
+ # If you want you can bind a single interface, if the bind option is not
11
+ # specified all the interfaces will listen for connections.
12
+ #
13
+ # bind 127.0.0.1
14
+
15
+ # Close the connection after a client is idle for N seconds
16
+ timeout 300
17
+
18
+ # Save the DB on disk:
19
+ #
20
+ # save <seconds> <changes>
21
+ #
22
+ # Will save the DB if both the given number of seconds and the given
23
+ # number of write operations against the DB occurred.
24
+ #
25
+ # In the example below the behaviour will be to save:
26
+ # after 900 sec (15 min) if at least 1 key changed
27
+ # after 300 sec (5 min) if at least 10 keys changed
28
+ # after 60 sec if at least 10000 keys changed
29
+ save 900 1
30
+ save 300 10
31
+ save 60 10000
32
+
33
+ # For default save/load DB in/from the working directory
34
+ # Note that you must specify a directory not a file name.
35
+ dir ./
36
+
37
+ # Set server verbosity to 'debug'
38
+ # it can be one of:
39
+ # debug (a lot of information, useful for development/testing)
40
+ # notice (moderately verbose, what you want in production probably)
41
+ # warning (only very important / critical messages are logged)
42
+ loglevel debug
43
+
44
+ # Specify the log file name. Also 'stdout' can be used to force
45
+ # the demon to log on the standard output. Note that if you use standard
46
+ # output for logging but daemonize, logs will be sent to /dev/null
47
+ logfile stdout
48
+
49
+ # Set the number of databases.
50
+ databases 16
51
+
52
+ ################################# REPLICATION #################################
53
+
54
+ # Master-Slave replication. Use slaveof to make a Redis instance a copy of
55
+ # another Redis server. Note that the configuration is local to the slave
56
+ # so for example it is possible to configure the slave to save the DB with a
57
+ # different interval, or to listen to another port, and so on.
58
+
59
+ # slaveof <masterip> <masterport>
60
+
61
+ ############################### ADVANCED CONFIG ###############################
62
+
63
+ # Glue small output buffers together in order to send small replies in a
64
+ # single TCP packet. Uses a bit more CPU but most of the times it is a win
65
+ # in terms of number of queries per second. Use 'yes' if unsure.
66
+ glueoutputbuf yes
@@ -0,0 +1,52 @@
1
+ require 'extlib'
2
+ require 'guid'
3
+ require 'validatable'
4
+
5
+ module CoolBreeze
6
+
7
+ # :stopdoc:
8
+ VERSION = '0.2.0'
9
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
10
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
11
+ # :startdoc:
12
+
13
+ # Returns the version string for the library.
14
+ #
15
+ def self.version
16
+ VERSION
17
+ end
18
+
19
+ # Returns the library path for the module. If any arguments are given,
20
+ # they will be joined to the end of the libray path using
21
+ # <tt>File.join</tt>.
22
+ #
23
+ def self.libpath( *args )
24
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
25
+ end
26
+
27
+ # Returns the lpath for the module. If any arguments are given,
28
+ # they will be joined to the end of the path using
29
+ # <tt>File.join</tt>.
30
+ #
31
+ def self.path( *args )
32
+ args.empty? ? PATH : ::File.join(PATH, args.flatten)
33
+ end
34
+
35
+ # Utility method used to require all files ending in .rb that lie in the
36
+ # directory below this file that has the same name as the filename passed
37
+ # in. Optionally, a specific _directory_ name can be passed in such that
38
+ # the _filename_ does not have to be equivalent to the directory.
39
+ #
40
+ def self.require_all_libs_relative_to( fname, dir = nil )
41
+ dir ||= ::File.basename(fname, '.*')
42
+ search_me = ::File.expand_path(
43
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
44
+
45
+ Dir.glob(search_me).sort.each {|rb| require rb}
46
+ end
47
+
48
+ end # module CoolBreeze
49
+
50
+ CoolBreeze.require_all_libs_relative_to(__FILE__)
51
+
52
+ # EOF
@@ -0,0 +1,52 @@
1
+ module CoolBreeze
2
+ class Association
3
+ include Enumerable
4
+
5
+ def initialize(klass, name, options = {})
6
+ @list_name = "#{name}_list"
7
+ @klass = klass
8
+ klass.instance_index :"#{name}_list", :list
9
+ end
10
+
11
+ def for(instance)
12
+ @list = instance.method(@list_name)
13
+ self
14
+ end
15
+
16
+ def add(obj)
17
+ @list.call.push(obj.key)
18
+ end
19
+
20
+ def remove(obj)
21
+ @list.call.remove(1,obj.key)
22
+ end
23
+
24
+ def destroy(obj)
25
+ remove(obj)
26
+ obj.destroy
27
+ end
28
+
29
+ def get(start = 0, stop = -1)
30
+ keys = @list.call.range(start, stop)
31
+ return [] if keys.blank?
32
+ keys.map{|k| @klass.get k}
33
+ end
34
+
35
+ def size
36
+ @list.call.length
37
+ end
38
+
39
+ def first
40
+ key = @list.call.range(0,1)
41
+ @klass.get(key) unless key.blank?
42
+ end
43
+
44
+ def each
45
+ values = @list.call.range(0,-1)
46
+ return if values.blank?
47
+ values.each do |val|
48
+ yield @klass.get val
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,81 @@
1
+ class Symbol
2
+ def eq
3
+ [self.to_s,:eq]
4
+ end
5
+
6
+ def includes
7
+ [self.to_s,:includes]
8
+ end
9
+
10
+ def starts_with
11
+ [self.to_s,:starts_with]
12
+ end
13
+
14
+ def ends_with
15
+ [self.to_s,:ends_with]
16
+ end
17
+
18
+ def and
19
+ [self.to_s,:and]
20
+ end
21
+
22
+ def or
23
+ [self.to_s,:or]
24
+ end
25
+
26
+ def stroreq
27
+ [self.to_s,:stroreq]
28
+ end
29
+
30
+ def matches
31
+ [self.to_s,:matches]
32
+ end
33
+
34
+ def gt
35
+ [self.to_s,:gt]
36
+ end
37
+
38
+ def gte
39
+ [self.to_s,:gte]
40
+ end
41
+
42
+ def lt
43
+ [self.to_s,:lt]
44
+ end
45
+
46
+ def lte
47
+ [self.to_s,:lte]
48
+ end
49
+
50
+ def between
51
+ [self.to_s,:between]
52
+ end
53
+
54
+ def numoreq
55
+ [self.to_s,:numoreq]
56
+ end
57
+
58
+ def strasc
59
+ [self.to_s,:strasc]
60
+ end
61
+
62
+ def strdesc
63
+ [self.to_s,:strdesc]
64
+ end
65
+
66
+ def asc
67
+ [self.to_s,:asc]
68
+ end
69
+
70
+ def desc
71
+ [self.to_s,:desc]
72
+ end
73
+
74
+ def numasc
75
+ [self.to_s,:numasc]
76
+ end
77
+
78
+ def numdesc
79
+ [self.to_s,:numdesc]
80
+ end
81
+ end
@@ -0,0 +1,10 @@
1
+ module CoolBreeze
2
+ class Connections
3
+ class_inheritable_accessor(:adapters)
4
+ self.adapters ||= {}
5
+
6
+ def self.setup(name, instance)
7
+ adapters[name] = instance
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ module CoolBreeze
2
+ module Index
3
+ class Abstract
4
+ attr_accessor :name, :type
5
+ def initialize(name,type)
6
+ @name = name
7
+ @type = type
8
+ end
9
+
10
+ def get_key(klass)
11
+ @get_key ||= "#{klass.to_s.downcase}:#{@name}"
12
+ end
13
+
14
+ def type_klass
15
+ @type_klass ||= Module.find_const("CoolBreeze::Indices::#{@type.to_s.to_const_string}")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,6 @@
1
+ module CoolBreeze
2
+ module Index
3
+ class ClassIndex < Abstract
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ module CoolBreeze
2
+ module Index
3
+ class InstanceIndex < Abstract
4
+ def get_key(klass)
5
+ "#{klass.class.to_s.downcase}:#{klass.key}:#{@name}"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ module CoolBreeze
2
+ module Mixins
3
+ module Associations
4
+ def self.included(base)
5
+ base.class_eval <<-EOS, __FILE__, __LINE__
6
+ class_inheritable_accessor(:associations)
7
+ self.associations = {}
8
+ EOS
9
+
10
+ base.extend(ClassMethods)
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+ def many(name, options = {})
16
+ associations[name] = CoolBreeze::Association.new(self,name,options = {})
17
+ class_eval <<-EOS, __FILE__, __LINE__
18
+ def #{name}
19
+ self.class.associations[:"#{name}"].for(self)
20
+ end
21
+ EOS
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,55 @@
1
+ module CoolBreeze
2
+ module Mixins
3
+ module Indices
4
+ def self.included(base)
5
+ base.class_eval <<-EOS, __FILE__, __LINE__
6
+ class_inheritable_accessor(:index_types)
7
+ class_inheritable_accessor(:class_indices)
8
+ class_inheritable_accessor(:instance_indices)
9
+ self.index_types = %w(value list set counter)
10
+ self.class_indices = {}
11
+ self.instance_indices = {}
12
+ EOS
13
+
14
+ base.extend(ClassMethods)
15
+
16
+ def destroy
17
+ instance_indices.each{|idx| idx.destroy }
18
+ super
19
+ end
20
+ end
21
+
22
+ module ClassMethods
23
+ def class_indicies
24
+ @class_indicies
25
+ end
26
+
27
+ def instance_indicies
28
+ @instance_indicies
29
+ end
30
+
31
+ def class_index(name,type)
32
+ klass = Module.find_const("CoolBreeze::Types::#{type.to_s.to_const_string}")
33
+ instance_eval <<-RUBY, __FILE__, __LINE__
34
+ class_indices[name] = klass.new("#{self.to_s.downcase}:#{name}")
35
+ def #{name}(opts = {})
36
+ class_indices[:"#{name}"]
37
+ end
38
+ RUBY
39
+ end
40
+
41
+ def instance_index(name,type)
42
+ klass = Module.find_const("CoolBreeze::Types::#{type.to_s.to_const_string}")
43
+ class_eval do
44
+ define_method name do
45
+ if instance_indices[name].nil?
46
+ instance_indices[name] = klass.new("#{self.key}:#{name}")
47
+ end
48
+ instance_indices[name]
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,140 @@
1
+ module CoolBreeze
2
+ module Model
3
+ def self.included(model)
4
+ model.send(:include, InstanceMethods)
5
+ model.send(:include, Validatable)
6
+ model.send(:include, Extlib::Hook)
7
+ model.send(:include, CoolBreeze::Mixins::Indices)
8
+ model.send(:include, CoolBreeze::Mixins::Associations)
9
+ model.class_inheritable_accessor(:default_conditions)
10
+ model.extend(ClassMethods)
11
+ model.class_eval do
12
+ self.default_conditions = {:model_type => self.to_s.downcase}
13
+ end
14
+ end
15
+ module ClassMethods
16
+ def get(id)
17
+ attrs = data_store[id]
18
+ cast(attrs) unless attrs.blank?
19
+ end
20
+
21
+ alias :[] :get
22
+
23
+ def find(query = {})
24
+ rs = CoolBreeze::Query.new(self,query).run
25
+ l = LazyArray.new
26
+ l = rs.to_a
27
+ end
28
+
29
+ def first(query = {})
30
+ attrs = find(query.merge(default_conditions.merge(:limit => 1))).first
31
+ cast(attrs) unless attrs.blank?
32
+ end
33
+
34
+ def index_store
35
+ adapter(:redis)
36
+ end
37
+
38
+ def data_store
39
+ adapter(:tokyo)
40
+ end
41
+
42
+ def all(query = {})
43
+ attrs = find(query.merge(default_conditions))
44
+ attrs.map{|a| cast(a)} unless attrs.blank?
45
+ end
46
+
47
+ def adapter(name)
48
+ Connections.adapters[name]
49
+ end
50
+
51
+ def create(data = {})
52
+ m = self.new(data)
53
+ m.save
54
+ end
55
+
56
+ def timestamps!
57
+ before :save do
58
+ self.created_at = Time.now if new?
59
+ self.updated_at = Time.now
60
+ end
61
+ end
62
+
63
+ def count(query = {})
64
+ find(query.merge(default_conditions)).size
65
+ end
66
+
67
+ protected
68
+
69
+ def cast(attrs)
70
+ key = attrs.delete(:pk)
71
+ m = self.new(attrs)
72
+ m.key = key
73
+ m
74
+ end
75
+ end
76
+
77
+ module InstanceMethods
78
+ def initialize(data = {})
79
+ @index_store = self.class.index_store
80
+ @data_store = self.class.data_store
81
+ @data = {}
82
+ data.each do |k,v|
83
+ self.send(:"#{k}=",v.to_s)
84
+ end
85
+ end
86
+
87
+ def properties
88
+ @data.keys
89
+ end
90
+
91
+ def key
92
+ @key ||= "#{self.class.to_s.downcase}:#{Guid.new.to_s}"
93
+ end
94
+
95
+ def key=(k)
96
+ @key = k
97
+ end
98
+
99
+ def new?
100
+ @data_store[key].nil?
101
+ end
102
+
103
+ alias :new_record? :new?
104
+
105
+ def [](key)
106
+ @data[key]
107
+ end
108
+
109
+ def []=(key,val)
110
+ @data[key] = val.to_s
111
+ end
112
+
113
+ def save
114
+ unless @data.has_key?(:model_type)
115
+ self.model_type = self.class.to_s.downcase
116
+ end
117
+ @data_store[key] = @data
118
+ return @data_store[key] == @data
119
+ end
120
+
121
+ def destroy
122
+ @data_store.delete(key)
123
+ end
124
+
125
+ def method_missing(method_symbol, *arguments)
126
+ method_name = method_symbol.to_s
127
+
128
+ case method_name[-1..-1]
129
+ when "="
130
+ @data[method_name[0..-2]] = arguments.first.to_s
131
+ when "?"
132
+ @data[method_name[0..-2]] == true
133
+ else
134
+ # Returns nil on failure so forms will work
135
+ @data.has_key?(method_name) ? @data[method_name] : nil
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,36 @@
1
+ module CoolBreeze
2
+ class Query
3
+ def initialize(klass,conditions = {})
4
+ @klass = klass
5
+ @query = Rufus::Tokyo::TableQuery.new(CoolBreeze::Connections.adapters[:tokyo])
6
+ parse_conditions(conditions)
7
+ end
8
+
9
+ def parse_conditions(conds)
10
+ # check for order condtion
11
+ order = conds.delete(:order_by)
12
+ @query.order_by(*order) unless order.nil?
13
+ # check for limit condition
14
+ offset = conds.delete(:offset)
15
+ limit = conds.delete(:limit)
16
+ @query.limit(limit, offset || -1) unless limit.nil?
17
+ # take conditions from :prop.op => val to add(prop, op, value)
18
+ conds.each do |key, val|
19
+ key = [key,:eq] if key.is_a?(Symbol)
20
+ if key.last == :eq
21
+ if val.is_a? Numeric
22
+ key[1] = :numeq
23
+ else val.is_a? String
24
+ key[1] = :streq
25
+ end
26
+ end
27
+ key[0] = key.first.to_s
28
+ @query.add *(key + [val.to_s])
29
+ end
30
+
31
+ def run
32
+ @query.run
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ module CoolBreeze
2
+ module Types
3
+ class Abstract
4
+ attr_accessor :key, :index_store
5
+ def initialize(key)
6
+ @key = key
7
+ @index_store = CoolBreeze::Connections.adapters[:redis]
8
+ end
9
+
10
+ def get
11
+ @index_store[@key]
12
+ end
13
+
14
+ def destroy
15
+ @index_store.delete(@key)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module CoolBreeze
2
+ module Types
3
+ class Counter < Abstract
4
+ def incr
5
+ @index_store.incr(@key)
6
+ end
7
+
8
+ def decr
9
+ @index_store.decr(@key)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,41 @@
1
+ module CoolBreeze
2
+ module Types
3
+ class List < Abstract
4
+ def length
5
+ @index_store.list_length(@key)
6
+ end
7
+
8
+ def push(val)
9
+ @index_store.push_tail(@key, val)
10
+ end
11
+
12
+ def pop
13
+ @index_store.pop_tail(@key)
14
+ end
15
+
16
+ def unshift
17
+ @index_store.pop_head(@key)
18
+ end
19
+
20
+ def shift(val)
21
+ @index_store.push_head(@key, val)
22
+ end
23
+
24
+ def trim(start, stop)
25
+ @index_store.list_trim(@key, start, stop)
26
+ end
27
+
28
+ def range(start, stop)
29
+ @index_store.list_range(@key, start, stop)
30
+ end
31
+
32
+ def index(index)
33
+ @index_store.list_index(@key, index)
34
+ end
35
+
36
+ def remove(count, value)
37
+ @index_store.list_rm(@key, count, value)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,29 @@
1
+ module CoolBreeze
2
+ module Types
3
+ class Set < Abstract
4
+ def get
5
+ @index_store.set_members(@key)
6
+ end
7
+
8
+ def add(val)
9
+ @index_store.set_add(@key,val)
10
+ end
11
+
12
+ def size
13
+ @index_store.set_count(@key)
14
+ end
15
+
16
+ def include?(val)
17
+ @index_store.set_member?(@key, val)
18
+ end
19
+
20
+ def remove(val)
21
+ @index_store.set_delete(@key, val)
22
+ end
23
+
24
+ def intersect(key)
25
+ @index_store.set_intersect(@key, key)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ module CoolBreeze
2
+ module Types
3
+ class Value < Abstract
4
+ def set(val)
5
+ @index_store[@key] = val
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,35 @@
1
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
2
+
3
+ describe "Associations" do
4
+ before do
5
+ @user = User.new
6
+ end
7
+
8
+ it "defines the method on a instance" do
9
+ @user.respond_to?(:messages).should be_true
10
+ end
11
+
12
+ it "has a destroy method" do
13
+ @user.messages.respond_to?(:destroy).should be_true
14
+ end
15
+
16
+ it "has an add method" do
17
+ @user.messages.respond_to?(:add).should be_true
18
+ end
19
+
20
+ it "has a remove method" do
21
+ @user.messages.respond_to?(:remove).should be_true
22
+ end
23
+
24
+ it "has a get method" do
25
+ @user.messages.respond_to?(:get).should be_true
26
+ end
27
+
28
+ it "responds to each" do
29
+ @user.messages.respond_to?(:each).should be_true
30
+ end
31
+
32
+ it "responds to first" do
33
+ @user.messages.respond_to?(:first).should be_true
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
2
+
3
+ describe "Class Index" do
4
+ before do
5
+ end
6
+ end
7
+
8
+ describe "Instance Index" do
9
+ before do
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
2
+
3
+ describe "CoolBreeze::Model" do
4
+ before do
5
+ @data = {
6
+ "profile_image_url" => "http://s3.amazonaws.com/twitter_production/profile_images/74591615/01-30-09_2327_normal.jpg",
7
+ "created_at" => "Sun, 22 Mar 2009 00:13:11 +0000",
8
+ "from_user" => "pbrendel",
9
+ "text" => "first time i've noticed not having digital antenna. don't get austin cbs anymore, so no horns. (internet tv to the rescue)",
10
+ "to_user_id" => nil,
11
+ "id" => 1368224751,
12
+ "from_user_id" => 4205104,
13
+ "iso_language_code" => "en",
14
+ "source" => "&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"
15
+ }
16
+ end
17
+ it 'should take an optional paramter to new and set the data' do
18
+ m = Message.new(@data)
19
+ m.data.should == @data.each{|k,v| @data[k] = v.to_s}
20
+ end
21
+ end
22
+
23
+ # EOF
@@ -0,0 +1,12 @@
1
+ class Message
2
+ include CoolBreeze::Model
3
+
4
+ def key
5
+ @key ||= "message:#{self['id']}"
6
+ end
7
+
8
+ timestamps!
9
+
10
+ class_index :count, :counter
11
+ instance_index :tags, :set
12
+ end
@@ -0,0 +1,5 @@
1
+ class User
2
+ include CoolBreeze::Model
3
+
4
+ many :messages
5
+ end
@@ -0,0 +1,6 @@
1
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
2
+
3
+ describe "Queries" do
4
+ before do
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'spec' # Satisfies Autotest and anyone else not using the Rake tasks
3
+ require 'redis'
4
+ require 'rufus/tokyo'
5
+
6
+
7
+ require File.expand_path(
8
+ File.join(File.dirname(__FILE__), %w[.. lib cool_breeze]))
9
+
10
+ Dir[File.expand_path(File.join(File.dirname(__FILE__), 'models','*'))].each{|m| require m}
11
+
12
+ Spec::Runner.configure do |config|
13
+ CoolBreeze::Connections.setup(:redis, Redis.new)
14
+ CoolBreeze::Connections.setup(:tokyo, Rufus::Tokyo::Table.new('log/test.tct'))
15
+ # == Mock Framework
16
+ #
17
+ # RSpec uses it's own mocking framework by default. If you prefer to
18
+ # use mocha, flexmock or RR, uncomment the appropriate line:
19
+ #
20
+ # config.mock_with :mocha
21
+ # config.mock_with :flexmock
22
+ # config.mock_with :rr
23
+ end
24
+
25
+ # EOF
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: BrianTheCoder-cool_breeze
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - brianthecoder
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-15 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: wbsmith83@gmail.com
18
+ executables:
19
+ - cool_breeze
20
+ - redis.conf
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - README.txt
25
+ files:
26
+ - History.txt
27
+ - README.txt
28
+ - Rakefile
29
+ - VERSION.yml
30
+ - bin/cool_breeze
31
+ - bin/redis.conf
32
+ - lib/cool_breeze.rb
33
+ - lib/cool_breeze/association.rb
34
+ - lib/cool_breeze/conditions.rb
35
+ - lib/cool_breeze/connections.rb
36
+ - lib/cool_breeze/index/abstract.rb
37
+ - lib/cool_breeze/index/class_index.rb
38
+ - lib/cool_breeze/index/instance_index.rb
39
+ - lib/cool_breeze/mixins/associations.rb
40
+ - lib/cool_breeze/mixins/indices.rb
41
+ - lib/cool_breeze/model.rb
42
+ - lib/cool_breeze/query.rb
43
+ - lib/cool_breeze/types/abstract.rb
44
+ - lib/cool_breeze/types/counter.rb
45
+ - lib/cool_breeze/types/list.rb
46
+ - lib/cool_breeze/types/set.rb
47
+ - lib/cool_breeze/types/value.rb
48
+ - spec/association_spec.rb
49
+ - spec/index_spec.rb
50
+ - spec/model_spec.rb
51
+ - spec/models/message.rb
52
+ - spec/models/user.rb
53
+ - spec/query_spec.rb
54
+ - spec/spec_helper.rb
55
+ has_rdoc: true
56
+ homepage: http://github.com/BrianTheCoder/cool_breeze
57
+ post_install_message:
58
+ rdoc_options:
59
+ - --charset=UTF-8
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ version:
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.2.0
78
+ signing_key:
79
+ specification_version: 2
80
+ summary: A new type of orm utilizing two different storage mechanisms to the best of their abilities
81
+ test_files:
82
+ - spec/association_spec.rb
83
+ - spec/index_spec.rb
84
+ - spec/model_spec.rb
85
+ - spec/models/message.rb
86
+ - spec/models/user.rb
87
+ - spec/query_spec.rb
88
+ - spec/spec_helper.rb