benhoskings-ambitious-activerecord 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest ADDED
@@ -0,0 +1,22 @@
1
+ lib/ambition/adapters/active_record/base.rb
2
+ lib/ambition/adapters/active_record/query.rb
3
+ lib/ambition/adapters/active_record/select.rb
4
+ lib/ambition/adapters/active_record/slice.rb
5
+ lib/ambition/adapters/active_record/sort.rb
6
+ lib/ambition/adapters/active_record/statements.rb
7
+ lib/ambition/adapters/active_record/context.rb
8
+ lib/ambition/adapters/active_record.rb
9
+ test/benchmark.rb
10
+ test/chaining_test.rb
11
+ test/count_test.rb
12
+ test/enumerable_test.rb
13
+ test/helper.rb
14
+ test/join_test.rb
15
+ test/profiler.rb
16
+ test/ruby_test.rb
17
+ test/select_test.rb
18
+ test/slice_test.rb
19
+ test/sort_test.rb
20
+ test/source_test.rb
21
+ test/types_test.rb
22
+ Manifest
@@ -0,0 +1,72 @@
1
+
2
+ # Gem::Specification for Ambitious-activerecord-0.1.3
3
+ # Originally generated by Echoe
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{ambitious-activerecord}
7
+ s.version = "0.1.3"
8
+
9
+ s.specification_version = 2 if s.respond_to? :specification_version=
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.authors = ["Chris Wanstrath"]
13
+ s.date = %q{2008-04-26}
14
+ s.description = %q{An ambitious adapter for ActiveRecord}
15
+ s.email = %q{chris@ozmm.org}
16
+ s.extra_rdoc_files = ["lib/ambition/adapters/active_record/base.rb", "lib/ambition/adapters/active_record/query.rb", "lib/ambition/adapters/active_record/select.rb", "lib/ambition/adapters/active_record/slice.rb", "lib/ambition/adapters/active_record/sort.rb", "lib/ambition/adapters/active_record/statements.rb", "lib/ambition/adapters/active_record.rb"]
17
+ s.files = ["lib/ambition/adapters/active_record/base.rb", "lib/ambition/adapters/active_record/query.rb", "lib/ambition/adapters/active_record/select.rb", "lib/ambition/adapters/active_record/slice.rb", "lib/ambition/adapters/active_record/sort.rb", "lib/ambition/adapters/active_record/statements.rb", "lib/ambition/adapters/active_record.rb", "test/benchmark.rb", "test/chaining_test.rb", "test/count_test.rb", "test/enumerable_test.rb", "test/helper.rb", "test/join_test.rb", "test/profiler.rb", "test/ruby_test.rb", "test/select_test.rb", "test/slice_test.rb", "test/sort_test.rb", "test/source_test.rb", "test/types_test.rb", "Manifest", "ambitious-activerecord.gemspec"]
18
+ s.has_rdoc = true
19
+ s.homepage = %q{http://ambition.rubyforge.org/}
20
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Ambitious-activerecord", "--main", "README"]
21
+ s.require_paths = ["lib"]
22
+ s.rubyforge_project = %q{ambition}
23
+ s.rubygems_version = %q{1.3.1}
24
+ s.summary = %q{An ambitious adapter for ActiveRecord}
25
+ s.test_files = ["test/chaining_test.rb", "test/count_test.rb", "test/enumerable_test.rb", "test/join_test.rb", "test/ruby_test.rb", "test/select_test.rb", "test/slice_test.rb", "test/sort_test.rb", "test/source_test.rb", "test/types_test.rb"]
26
+
27
+ s.add_dependency(%q<activerecord>, [">= 1.15.6"])
28
+ s.add_dependency(%q<ambition>, [">= 0.5.3"])
29
+ end
30
+
31
+
32
+ # # Original Rakefile source (requires the Echoe gem):
33
+ #
34
+ # require 'rake'
35
+ #
36
+ # Version = '0.1.3'
37
+ #
38
+ # begin
39
+ # require 'rubygems'
40
+ # gem 'echoe', '>=2.7'
41
+ # ENV['RUBY_FLAGS'] = ""
42
+ # require 'echoe'
43
+ #
44
+ # Echoe.new('ambitious-activerecord') do |p|
45
+ # p.dependencies << 'activerecord >=1.15.6'
46
+ # p.summary = "An ambitious adapter for ActiveRecord"
47
+ # p.author = 'Chris Wanstrath'
48
+ # p.email = "chris@ozmm.org"
49
+ #
50
+ # p.project = 'ambition'
51
+ # p.url = "http://ambition.rubyforge.org/"
52
+ # p.test_pattern = 'test/*_test.rb'
53
+ # p.version = Version
54
+ # p.dependencies << 'ambition >=0.5.3'
55
+ # end
56
+ #
57
+ # rescue LoadError
58
+ # puts "Not doing any of the Echoe gemmy stuff, because you don't have the specified gem versions"
59
+ #
60
+ # require 'rake/testtask'
61
+ # Rake::TestTask.new do |t|
62
+ # t.pattern = "test/*_test.rb"
63
+ # end
64
+ # end
65
+ #
66
+ # desc 'Install as a gem'
67
+ # task :install_gem do
68
+ # puts `rake manifest package && gem install pkg/ambitious-activerecord-#{Version}.gem`
69
+ # end
70
+ #
71
+ # task :default => :test
72
+ #
@@ -0,0 +1,12 @@
1
+ require 'ambition'
2
+ require 'active_record'
3
+ require 'ambition/adapters/active_record/query'
4
+ require 'ambition/adapters/active_record/base'
5
+ require 'ambition/adapters/active_record/select'
6
+ require 'ambition/adapters/active_record/sort'
7
+ require 'ambition/adapters/active_record/slice'
8
+ require 'ambition/adapters/active_record/statements'
9
+ require 'ambition/adapters/active_record/context'
10
+
11
+ ActiveRecord::Base.extend Ambition::API
12
+ ActiveRecord::Base.ambition_adapter = Ambition::Adapters::ActiveRecord
@@ -0,0 +1,53 @@
1
+ require 'active_record/connection_adapters/abstract/quoting'
2
+
3
+ module Ambition
4
+ module Adapters
5
+ module ActiveRecord
6
+ class Base
7
+ include ::ActiveRecord::ConnectionAdapters::Quoting
8
+
9
+ def sanitize(value)
10
+ if value.is_a? Array
11
+ return value.map { |v| sanitize(v) }.join(', ')
12
+ end
13
+
14
+ case value
15
+ when true, 'true'
16
+ '1'
17
+ when false, 'false'
18
+ '0'
19
+ when Regexp
20
+ "'#{value.source}'"
21
+ else
22
+ if owner.connected?
23
+ ::ActiveRecord::Base.connection.quote(value)
24
+ else
25
+ quote(value)
26
+ end
27
+ end
28
+ rescue
29
+ "'#{value}'"
30
+ end
31
+
32
+ def quote_column_name(value)
33
+ if owner.connected?
34
+ ::ActiveRecord::Base.connection.quote_column_name(value)
35
+ else
36
+ value.to_s
37
+ end
38
+ end
39
+
40
+ def dbadapter_name
41
+ ::ActiveRecord::Base.connection.adapter_name
42
+ rescue ::ActiveRecord::ConnectionNotEstablished
43
+ 'Abstract'
44
+ end
45
+
46
+ def statement(*args)
47
+ @statement_instance ||= DatabaseStatements.const_get(dbadapter_name).new
48
+ @statement_instance.send(*args)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,75 @@
1
+ module Ambition
2
+ module Adapters
3
+ module ActiveRecord
4
+ class Query
5
+ @@select = 'SELECT * FROM %s %s'
6
+
7
+ def kick
8
+ owner.find(:all, to_hash)
9
+ end
10
+
11
+ def size
12
+ owner.count(to_hash)
13
+ end
14
+ alias_method :length, :size
15
+
16
+ def to_hash
17
+ hash = {}
18
+
19
+ unless (joins = stash[:joins]).blank?
20
+ hash[:joins] = joins
21
+ stash[:include] -= stash[:joins] unless stash[:include].blank?
22
+ end
23
+
24
+ unless (where = clauses[:select]).blank?
25
+ hash[:conditions] = Array(where)
26
+ hash[:conditions] *= ' AND '
27
+ end
28
+
29
+ unless (order = clauses[:sort]).blank?
30
+ hash[:order] = order.join(', ')
31
+ end
32
+
33
+ if Array(clauses[:slice]).last =~ /LIMIT (\d+)/
34
+ hash[:limit] = $1.to_i
35
+ end
36
+
37
+ if Array(clauses[:slice]).last =~ /OFFSET (\d+)/
38
+ hash[:offset] = $1.to_i
39
+ end
40
+
41
+ hash[:include] = stash[:include] if stash[:include]
42
+
43
+ hash
44
+ end
45
+
46
+ def to_s
47
+ hash = to_hash
48
+
49
+ raise "Sorry, I can't construct SQL with complex joins (yet)" unless hash[:include].blank?
50
+
51
+ sql = []
52
+ sql << joins_sql(hash[:joins]) unless hash[:joins].blank?
53
+ sql << "WHERE #{hash[:conditions]}" unless hash[:conditions].blank?
54
+ sql << "ORDER BY #{hash[:order]}" unless hash[:order].blank?
55
+ sql << clauses[:slice].last unless hash[:slice].blank?
56
+
57
+ @@select % [ owner.table_name, sql.join(' ') ]
58
+ end
59
+ alias_method :to_sql, :to_s
60
+
61
+ private
62
+
63
+ def joins_sql(joins)
64
+ joins.map {|join|
65
+ ::ActiveRecord::Associations::ClassMethods::InnerJoinDependency.
66
+ new(owner, join, nil).
67
+ join_associations.
68
+ map(&:association_join).
69
+ join(' ')
70
+ }
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,99 @@
1
+ module Ambition
2
+ module Adapters
3
+ module ActiveRecord
4
+ class Select < Base
5
+ def call(method)
6
+ "#{owner.table_name}.#{quote_column_name method}"
7
+ end
8
+
9
+ def chained_call(*methods)
10
+ if reflection = owner.reflections[methods.first]
11
+ stash[:include] ||= []
12
+ stash[:include] << methods.first
13
+ "#{reflection.table_name}.#{quote_column_name methods.last}"
14
+ elsif respond_to? methods[1]
15
+ send(methods[1], methods.first)
16
+ else
17
+ raise "I don't understand: #{methods.inspect}"
18
+ end
19
+ end
20
+
21
+ def both(left, right)
22
+ "(#{left} AND #{right})"
23
+ end
24
+
25
+ def either(left, right)
26
+ "(#{left} OR #{right})"
27
+ end
28
+
29
+ def ==(left, right)
30
+ if right.nil?
31
+ "#{left} IS NULL"
32
+ else
33
+ "#{left} = #{sanitize right}"
34
+ end
35
+ end
36
+
37
+ # !=
38
+ def not_equal(left, right)
39
+ if right.nil?
40
+ "#{left} IS NOT NULL"
41
+ else
42
+ "#{left} <> #{sanitize right}"
43
+ end
44
+ end
45
+
46
+ def =~(left, right)
47
+ if right.is_a? Regexp
48
+ "#{left} #{statement(:regexp, right)} #{sanitize right}"
49
+ else
50
+ "#{left} LIKE #{sanitize right}"
51
+ end
52
+ end
53
+
54
+ # !~
55
+ def not_regexp(left, right)
56
+ if right.is_a? Regexp
57
+ "#{left} #{statement(:not_regexp, right)} #{sanitize right}"
58
+ else
59
+ "#{left} NOT LIKE #{sanitize right}"
60
+ end
61
+ end
62
+
63
+ def <(left, right)
64
+ "#{left} < #{sanitize right}"
65
+ end
66
+
67
+ def >(left, right)
68
+ "#{left} > #{sanitize right}"
69
+ end
70
+
71
+ def >=(left, right)
72
+ "#{left} >= #{sanitize right}"
73
+ end
74
+
75
+ def <=(left, right)
76
+ "#{left} <= #{sanitize right}"
77
+ end
78
+
79
+ def include?(left, right)
80
+ left = left.map { |element| sanitize element }.join(', ')
81
+ "#{right} IN (#{left})"
82
+ end
83
+
84
+ def nil?(column)
85
+ left = "#{owner.table_name}.#{quote_column_name column}"
86
+ negated? ? not_equal(left, nil) : self.==(left, nil)
87
+ end
88
+
89
+ def downcase(column)
90
+ "LOWER(#{owner.table_name}.#{quote_column_name column})"
91
+ end
92
+
93
+ def upcase(column)
94
+ "UPPER(#{owner.table_name}.#{quote_column_name column})"
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,19 @@
1
+ module Ambition
2
+ module Adapters
3
+ module ActiveRecord
4
+ class Slice < Base
5
+ def slice(start, length=nil)
6
+ if start.is_a? Range
7
+ length = start.end
8
+ length -= 1 if start.exclude_end?
9
+ start = start.first - 1
10
+ length -= start
11
+ end
12
+ out = "LIMIT #{length} "
13
+ out << "OFFSET #{start}" if start.to_i.nonzero?
14
+ out
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ module Ambition
2
+ module Adapters
3
+ module ActiveRecord
4
+ class Sort < Base
5
+ def sort_by(method)
6
+ "#{owner.table_name}.#{quote_column_name method}"
7
+ end
8
+
9
+ def reverse_sort_by(method)
10
+ "#{owner.table_name}.#{quote_column_name method} DESC"
11
+ end
12
+
13
+ def chained_sort_by(receiver, method)
14
+ if reflection = owner.reflections[receiver]
15
+ stash[:include] ||= []
16
+ stash[:include] << receiver
17
+ "#{reflection.table_name}.#{quote_column_name method}"
18
+ else
19
+ raise [ receiver, method ].inspect
20
+ end
21
+ end
22
+
23
+ def chained_reverse_sort_by(receiver, method)
24
+ if reflection = owner.reflections[receiver]
25
+ stash[:include] ||= []
26
+ stash[:include] << receiver
27
+ "#{reflection.table_name}.#{quote_column_name method} DESC"
28
+ else
29
+ raise [ receiver, method ].inspect
30
+ end
31
+ end
32
+
33
+ def to_proc(symbol)
34
+ "#{owner.table_name}.#{symbol}"
35
+ end
36
+
37
+ def rand
38
+ 'RAND()'
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,39 @@
1
+ module Ambition
2
+ module Adapters
3
+ module ActiveRecord
4
+ module DatabaseStatements
5
+ def self.const_missing(*args)
6
+ Abstract
7
+ end
8
+
9
+ class Abstract
10
+ def regexp(regexp)
11
+ 'REGEXP'
12
+ end
13
+
14
+ def not_regexp(regexp)
15
+ 'NOT REGEXP'
16
+ end
17
+ end
18
+
19
+ class PostgreSQL < Abstract
20
+ def regexp(regexp)
21
+ if regexp.options == 1
22
+ '~*'
23
+ else
24
+ '~'
25
+ end
26
+ end
27
+
28
+ def not_regexp(regexp)
29
+ if regexp.options == 1
30
+ '!~*'
31
+ else
32
+ '!~'
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end