benhoskings-ambitious-activerecord 0.1.3

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 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