ambitious-activerecord 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
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.rb
8
+ test/benchmark.rb
9
+ test/chaining_test.rb
10
+ test/count_test.rb
11
+ test/enumerable_test.rb
12
+ test/helper.rb
13
+ test/join_test.rb
14
+ test/profiler.rb
15
+ test/ruby_test.rb
16
+ test/select_test.rb
17
+ test/slice_test.rb
18
+ test/sort_test.rb
19
+ test/source_test.rb
20
+ test/types_test.rb
21
+ Manifest
@@ -0,0 +1,55 @@
1
+
2
+ # Gem::Specification for Ambitious-activerecord-0.1.0
3
+ # Originally generated by Echoe
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{ambitious-activerecord}
7
+ s.version = "0.1.0"
8
+ s.date = %q{2008-01-29}
9
+ s.summary = %q{An ambitious adapter for ActiveRecord}
10
+ s.email = %q{chris@ozmm.org}
11
+ s.homepage = %q{http://ambition.rubyforge.org/}
12
+ s.rubyforge_project = %q{ambition}
13
+ s.description = %q{An ambitious adapter for ActiveRecord}
14
+ s.has_rdoc = true
15
+ s.authors = ["Chris Wanstrath"]
16
+ 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"]
17
+ 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"]
18
+ s.add_dependency(%q<activerecord>, [">= 1.15.0"])
19
+ s.add_dependency(%q<ambition>, [">= 0.5.0"])
20
+ end
21
+
22
+
23
+ # # Original Rakefile source (requires the Echoe gem):
24
+ #
25
+ # require 'rake'
26
+ #
27
+ # Version = '0.1.0'
28
+ #
29
+ # begin
30
+ # require 'rubygems'
31
+ # gem 'echoe', '>=2.7'
32
+ # ENV['RUBY_FLAGS'] = ""
33
+ # require 'echoe'
34
+ #
35
+ # Echoe.new('ambitious-activerecord') do |p|
36
+ # p.dependencies << 'activerecord >=1.15.0'
37
+ # p.summary = "An ambitious adapter for ActiveRecord"
38
+ # p.author = 'Chris Wanstrath'
39
+ # p.email = "chris@ozmm.org"
40
+ #
41
+ # p.project = 'ambition'
42
+ # p.url = "http://ambition.rubyforge.org/"
43
+ # p.test_pattern = 'test/*_test.rb'
44
+ # p.version = Version
45
+ # p.dependencies << 'ambition >=0.5.0'
46
+ # end
47
+ #
48
+ # rescue LoadError
49
+ # puts "Not doing any of the Echoe gemmy stuff, because you don't have the specified gem versions"
50
+ # end
51
+ #
52
+ # desc 'Install as a gem'
53
+ # task :install_gem do
54
+ # puts `rake manifest package && gem install pkg/ambitious-activerecord-#{Version}.gem`
55
+ # end
@@ -0,0 +1,11 @@
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
+
10
+ ActiveRecord::Base.extend Ambition::API
11
+ ActiveRecord::Base.ambition_adapter = Ambition::Adapters::ActiveRecord
@@ -0,0 +1,57 @@
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 active_connection?
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 active_connection?
34
+ ::ActiveRecord::Base.connection.quote_column_name(value)
35
+ else
36
+ value.to_s
37
+ end
38
+ end
39
+
40
+ def active_connection?
41
+ ::ActiveRecord::Base.active_connection_name
42
+ end
43
+
44
+ def dbadapter_name
45
+ ::ActiveRecord::Base.connection.adapter_name
46
+ rescue ::ActiveRecord::ConnectionNotEstablished
47
+ 'Abstract'
48
+ end
49
+
50
+ def statement(*args)
51
+ @statement_instance ||= DatabaseStatements.const_get(dbadapter_name).new
52
+ @statement_instance.send(*args)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,56 @@
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
+
15
+ def to_hash
16
+ hash = {}
17
+
18
+ unless (where = clauses[:select]).blank?
19
+ hash[:conditions] = Array(where)
20
+ hash[:conditions] *= ' AND '
21
+ end
22
+
23
+ if order = clauses[:sort]
24
+ hash[:order] = order.join(', ')
25
+ end
26
+
27
+ if clauses[:slice].last =~ /LIMIT (\d+)/
28
+ hash[:limit] = $1.to_i
29
+ end
30
+
31
+ if clauses[:slice].last =~ /OFFSET (\d+)/
32
+ hash[:offset] = $1.to_i
33
+ end
34
+
35
+ hash[:include] = stash[:include] if stash[:include]
36
+
37
+ hash
38
+ end
39
+
40
+ def to_s
41
+ hash = to_hash
42
+
43
+ raise "Sorry, I can't construct SQL with complex joins (yet)" unless hash[:include].blank?
44
+
45
+ sql = []
46
+ sql << "WHERE #{hash[:conditions]}" unless hash[:conditions].blank?
47
+ sql << "ORDER BY #{hash[:order]}" unless hash[:order].blank?
48
+ sql << clauses[:slice].last unless hash[:slice].blank?
49
+
50
+ @@select % [ owner.table_name, sql.join(' ') ]
51
+ end
52
+ alias_method :to_sql, :to_s
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,94 @@
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 downcase(column)
85
+ "LOWER(#{owner.table_name}.#{quote_column_name column})"
86
+ end
87
+
88
+ def upcase(column)
89
+ "UPPER(#{owner.table_name}.#{quote_column_name column})"
90
+ end
91
+ end
92
+ end
93
+ end
94
+ 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
@@ -0,0 +1,67 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../../../lib'
2
+ %w( rubygems ambition ambition/adapters/active_record benchmark ).each { |f| require f }
3
+
4
+ class User < ActiveRecord::Base
5
+ def self.reflections
6
+ return @reflections if @reflections
7
+ @reflections = {}
8
+ @reflections[:ideas] = Reflection.new(:has_many, 'user_id', :ideas, 'ideas')
9
+ @reflections[:invites] = Reflection.new(:has_many, 'referrer_id', :invites, 'invites')
10
+ @reflections[:profile] = Reflection.new(:has_one, 'user_id', :profile, 'profiles')
11
+ @reflections[:account] = Reflection.new(:belongs_to, 'account_id', :account, 'accounts')
12
+ @reflections
13
+ end
14
+
15
+ def self.table_name
16
+ 'users'
17
+ end
18
+ end
19
+
20
+ class Reflection < Struct.new(:macro, :primary_key_name, :name, :table_name)
21
+ end
22
+
23
+ Times = 10000
24
+
25
+ Benchmark.bm(30) do |x|
26
+ x.report 'simple select' do
27
+ Times.times do
28
+ User.select { |u| u.id == 20 }.to_hash
29
+ end
30
+ end
31
+
32
+ x.report 'simple select w/ eval' do
33
+ Times.times do
34
+ User.select { |u| u.created_at == Time.now }.to_hash
35
+ end
36
+ end
37
+
38
+ x.report 'dual select' do
39
+ Times.times do
40
+ User.select { |u| u.id == 20 && u.age > 20 }.to_hash
41
+ end
42
+ end
43
+
44
+ x.report 'join select' do
45
+ Times.times do
46
+ User.select { |u| u.id == 20 && u.ideas.name =~ /stuff/ }.to_hash
47
+ end
48
+ end
49
+
50
+ x.report 'dual select w/ sort' do
51
+ Times.times do
52
+ User.select { |u| u.id == 20 && u.age > 20 }.sort_by { |u| u.id }.to_hash
53
+ end
54
+ end
55
+
56
+ x.report 'dual select w/ sort & first' do
57
+ Times.times do
58
+ User.select { |u| u.id == 20 && u.age > 20 }.sort_by { |u| u.id }.first(20).to_hash
59
+ end
60
+ end
61
+
62
+ x.report "it's complicated" do
63
+ Times.times do
64
+ User.select { |u| (u.id == 20 && u.age > 20) || u.profile.name == 'Jon' }.sort_by { |u| [u.id, -u.name] }.first(20).to_hash
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "ActiveRecord Adapter" do
4
+ context "Chaining" do
5
+ specify "should join selects with AND" do
6
+ sql = User.select { |m| m.name == 'jon' }
7
+ sql = sql.select { |m| m.age == 22 }
8
+ sql.to_s.should == "SELECT * FROM users WHERE users.name = 'jon' AND users.age = 22"
9
+ end
10
+
11
+ specify "should join sort_bys with a comma" do
12
+ sql = User.select { |m| m.name == 'jon' }
13
+ sql = sql.sort_by { |m| m.name }
14
+ sql = sql.sort_by { |m| m.age }
15
+ sql.to_s.should == "SELECT * FROM users WHERE users.name = 'jon' ORDER BY users.name, users.age"
16
+ end
17
+
18
+ specify "should join selects and sorts intelligently" do
19
+ sql = User.select { |m| m.name == 'jon' }
20
+ sql = sql.select { |m| m.age == 22 }
21
+ sql = sql.sort_by { |m| -m.name }
22
+ sql = sql.sort_by { |m| m.age }
23
+ sql.to_s.should == "SELECT * FROM users WHERE users.name = 'jon' AND users.age = 22 ORDER BY users.name DESC, users.age"
24
+ end
25
+
26
+ specify "should join lots of selects and sorts intelligently" do
27
+ sql = User.select { |m| m.name == 'jon' }
28
+ sql = sql.select { |m| m.age == 22 }
29
+ sql = sql.sort_by { |m| m.name }
30
+ sql = sql.select { |m| m.power == true }
31
+ sql = sql.sort_by { |m| m.email }
32
+ sql = sql.select { |m| m.admin == true && m.email == 'chris@ozmm.org' }
33
+ sql.to_s.should == "SELECT * FROM users WHERE users.name = 'jon' AND users.age = 22 AND users.power = 1 AND (users.admin = 1 AND users.email = 'chris@ozmm.org') ORDER BY users.name, users.email"
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "ActiveRecord Adapter" do
4
+ context "Count" do
5
+ setup do
6
+ hash = { :conditions => "users.name = 'jon'" }
7
+ User.expects(:count).with(hash)
8
+ @sql = User.select { |m| m.name == 'jon' }
9
+ end
10
+
11
+ specify "size" do
12
+ @sql.size
13
+ end
14
+
15
+ specify "length" do
16
+ @sql.length
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,88 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "ActiveRecord Adapter" do
4
+ context "Each" do
5
+ specify "simple ==" do
6
+ hash = { :conditions => "users.age = 21" }
7
+ User.expects(:find).with(:all, hash).returns([])
8
+ User.select { |m| m.age == 21 }.each do |user|
9
+ puts user.name
10
+ end
11
+ end
12
+
13
+ specify "limit and conditions" do
14
+ hash = { :limit => 5, :conditions => "users.age = 21" }
15
+ User.expects(:find).with(:all, hash).returns([])
16
+ User.select { |m| m.age == 21 }.first(5).each do |user|
17
+ puts user.name
18
+ end
19
+ end
20
+
21
+ specify "limit and conditions and order" do
22
+ hash = { :limit => 5, :conditions => "users.age = 21", :order => 'users.name' }
23
+ User.expects(:find).with(:all, hash).returns([])
24
+ User.select { |m| m.age == 21 }.sort_by { |m| m.name }.first(5).each do |user|
25
+ puts user.name
26
+ end
27
+ end
28
+
29
+ specify "limit and order" do
30
+ hash = { :limit => 5, :order => 'users.name' }
31
+ User.expects(:find).with(:all, hash).returns([])
32
+ User.sort_by { |m| m.name }.first(5).each do |user|
33
+ puts user.name
34
+ end
35
+ end
36
+ end
37
+
38
+ context "Enumerable Methods" do
39
+ specify "map" do
40
+ hash = { :conditions => "users.age = 21" }
41
+ User.expects(:find).with(:all, hash).returns([])
42
+ User.select { |m| m.age == 21 }.map { |u| u.name }
43
+ end
44
+
45
+ specify "each_with_index" do
46
+ hash = { :conditions => "users.age = 21" }
47
+ User.expects(:find).with(:all, hash).returns([])
48
+ User.select { |m| m.age == 21 }.each_with_index do |user, i|
49
+ puts "#{i}: #{user.name}"
50
+ end
51
+ end
52
+
53
+ specify "any?" do
54
+ User.expects(:count).with(:conditions => "users.age > 21").returns(1)
55
+ User.any? { |u| u.age > 21 }.should == true
56
+ end
57
+
58
+ specify "all?" do
59
+ User.expects(:count).at_least_once.returns(10, 20)
60
+ User.all? { |u| u.age > 21 }.should == false
61
+
62
+ User.expects(:count).at_least_once.returns(10, 10)
63
+ User.all? { |u| u.age > 21 }.should == true
64
+ end
65
+
66
+ specify "empty?" do
67
+ User.expects(:count).with(:conditions => "users.age > 21").returns(1)
68
+ User.select { |u| u.age > 21 }.empty?.should.equal false
69
+
70
+ User.expects(:count).with(:conditions => "users.age > 21").returns(0)
71
+ User.select { |u| u.age > 21 }.empty?.should.equal true
72
+ end
73
+
74
+ specify "entries" do
75
+ User.expects(:find).with(:all, {})
76
+ User.entries
77
+
78
+ hash = { :conditions => "users.age = 21" }
79
+ User.expects(:find).with(:all, hash).returns([])
80
+ User.select { |m| m.age == 21 }.entries
81
+ end
82
+
83
+ specify "to_a" do
84
+ User.expects(:find).with(:all, {})
85
+ User.to_a
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,43 @@
1
+ %w( rubygems test/spec mocha redgreen English ).each { |f| require f }
2
+
3
+ $LOAD_PATH.unshift *[ File.dirname(__FILE__) + '/../lib', File.dirname(__FILE__) + '/../../../lib' ]
4
+ require 'ambition/adapters/active_record'
5
+
6
+ class User < ActiveRecord::Base
7
+ def self.reflections
8
+ return @reflections if @reflections
9
+ @reflections = {}
10
+ @reflections[:ideas] = Reflection.new(:has_many, 'user_id', :ideas, 'ideas')
11
+ @reflections[:invites] = Reflection.new(:has_many, 'referrer_id', :invites, 'invites')
12
+ @reflections[:profile] = Reflection.new(:has_one, 'user_id', :profile, 'profiles')
13
+ @reflections[:account] = Reflection.new(:belongs_to, 'account_id', :account, 'accounts')
14
+ @reflections
15
+ end
16
+
17
+ def self.table_name
18
+ 'users'
19
+ end
20
+ end
21
+
22
+ class Reflection < Struct.new(:macro, :primary_key_name, :name, :table_name)
23
+ end
24
+
25
+ module ActiveRecord
26
+ module ConnectionAdapters
27
+ class MysqlAdapter
28
+ def connect(*args)
29
+ true
30
+ end
31
+ end
32
+
33
+ class PostgreSQLAdapter
34
+ def connect(*args)
35
+ true
36
+ end
37
+ class PGError; end
38
+ end
39
+
40
+ class FakeAdapter < AbstractAdapter
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,62 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "ActiveRecord Adapter" do
4
+ context "Joins" do
5
+ specify "simple == on an association" do
6
+ sql = User.select { |m| m.account.email == 'chris@ozmm.org' }
7
+ sql.to_hash.should == {
8
+ :conditions => "accounts.email = 'chris@ozmm.org'",
9
+ :include => [:account]
10
+ }
11
+ end
12
+
13
+ specify "simple mixed == on an association" do
14
+ sql = User.select { |m| m.name == 'chris' && m.account.email == 'chris@ozmm.org' }
15
+ sql.to_hash.should == {
16
+ :conditions => "(users.name = 'chris' AND accounts.email = 'chris@ozmm.org')",
17
+ :include => [:account]
18
+ }
19
+ end
20
+
21
+ specify "multiple associations" do
22
+ sql = User.select { |m| m.ideas.title == 'New Freezer' || m.invites.email == 'pj@hyett.com' }
23
+ sql.to_hash.should == {
24
+ :conditions => "(ideas.title = 'New Freezer' OR invites.email = 'pj@hyett.com')",
25
+ :include => [:ideas, :invites]
26
+ }
27
+ end
28
+
29
+ specify "belongs_to" do
30
+ sql = User.select { |m| m.account.id > 20 }
31
+ sql.to_hash.should == {
32
+ :conditions => "accounts.id > 20",
33
+ :include => [:account]
34
+ }
35
+ end
36
+
37
+ specify "complex joins have no to_s" do
38
+ sql = User.select { |m| m.account.id > 20 }
39
+ should.raise { sql.to_s }
40
+ end
41
+
42
+ specify "non-existant associations" do
43
+ should.raise { User.select { |m| m.liquor.brand == 'Jack' } }
44
+ end
45
+
46
+ specify "in order" do
47
+ sql = User.sort_by { |m| m.ideas.title }
48
+ sql.to_hash.should == {
49
+ :order => "ideas.title",
50
+ :include => [:ideas]
51
+ }
52
+ end
53
+
54
+ specify "in a more complex order" do
55
+ sql = User.sort_by { |m| [ m.ideas.title, -m.invites.email ] }
56
+ sql.to_hash.should == {
57
+ :order => "ideas.title, invites.email DESC",
58
+ :include => [:ideas, :invites]
59
+ }
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,36 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../../../lib'
2
+ require 'rubygems'
3
+ require 'ambition'
4
+ require 'ambition/adapters/active_record'
5
+ require 'ruby-prof'
6
+
7
+ class User < ActiveRecord::Base
8
+ def self.reflections
9
+ return @reflections if @reflections
10
+ @reflections = {}
11
+ @reflections[:ideas] = Reflection.new(:has_many, 'user_id', :ideas, 'ideas')
12
+ @reflections[:invites] = Reflection.new(:has_many, 'referrer_id', :invites, 'invites')
13
+ @reflections[:profile] = Reflection.new(:has_one, 'user_id', :profile, 'profiles')
14
+ @reflections[:account] = Reflection.new(:belongs_to, 'account_id', :account, 'accounts')
15
+ @reflections
16
+ end
17
+
18
+ def self.table_name
19
+ 'users'
20
+ end
21
+ end
22
+
23
+ class Reflection < Struct.new(:macro, :primary_key_name, :name, :table_name)
24
+ end
25
+
26
+ result = RubyProf.profile do
27
+ 1000.times do
28
+ User.select { |u| (u.id == 20 && u.age > 20) || u.profile.name == 'Jon' }.sort_by { |u| [u.id, -u.name] }.first(20).to_hash
29
+ end
30
+ end
31
+
32
+ printer = RubyProf::FlatPrinter.new(result)
33
+ #printer = RubyProf::GraphPrinter.new(result)
34
+ printer.print(STDOUT, 0)
35
+
36
+ puts User.select { |u| (u.id == 20 && u.age > 20) || u.profile.name == 'Jon' }.sort_by { |u| [u.id, -u.name] }.first(20).to_hash.inspect
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "ActiveRecord Adapter" do
4
+ context "Inline Ruby" do
5
+ xspecify "should know what to return" do
6
+ name = 'David'
7
+ sql = User.select { |u| name.nil? || u.name == name }.to_s
8
+ sql.should == "SELECT * FROM users WHERE (users.name = 'David')"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,259 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "ActiveRecord Adapter" do
4
+ context "Select" do
5
+ specify "simple ==" do
6
+ sql = User.select { |m| m.name == 'jon' }.to_s
7
+ sql.should == "SELECT * FROM users WHERE users.name = 'jon'"
8
+ end
9
+
10
+ specify "simple !=" do
11
+ sql = User.select { |m| m.name != 'jon' }.to_s
12
+ sql.should == "SELECT * FROM users WHERE users.name <> 'jon'"
13
+ end
14
+
15
+ specify "simple == && ==" do
16
+ sql = User.select { |m| m.name == 'jon' && m.age == 21 }.to_s
17
+ sql.should == "SELECT * FROM users WHERE (users.name = 'jon' AND users.age = 21)"
18
+ end
19
+
20
+ specify "simple == || ==" do
21
+ sql = User.select { |m| m.name == 'jon' || m.age == 21 }.to_s
22
+ sql.should == "SELECT * FROM users WHERE (users.name = 'jon' OR users.age = 21)"
23
+ end
24
+
25
+ specify "mixed && and ||" do
26
+ sql = User.select { |m| m.name == 'jon' || m.age == 21 && m.password == 'pass' }.to_s
27
+ sql.should == "SELECT * FROM users WHERE (users.name = 'jon' OR (users.age = 21 AND users.password = 'pass'))"
28
+ end
29
+
30
+ specify "grouped && and ||" do
31
+ sql = User.select { |m| (m.name == 'jon' || m.name == 'rick') && m.age == 21 }.to_s
32
+ sql.should == "SELECT * FROM users WHERE ((users.name = 'jon' OR users.name = 'rick') AND users.age = 21)"
33
+ end
34
+
35
+ specify "simple >/<" do
36
+ sql = User.select { |m| m.age > 21 }.to_s
37
+ sql.should == "SELECT * FROM users WHERE users.age > 21"
38
+
39
+ sql = User.select { |m| m.age >= 21 }.to_s
40
+ sql.should == "SELECT * FROM users WHERE users.age >= 21"
41
+
42
+ sql = User.select { |m| m.age < 21 }.to_s
43
+ sql.should == "SELECT * FROM users WHERE users.age < 21"
44
+ end
45
+
46
+ specify "array.include? item" do
47
+ sql = User.select { |m| [1, 2, 3, 4].include? m.id }.to_s
48
+ sql.should == "SELECT * FROM users WHERE users.id IN (1, 2, 3, 4)"
49
+ end
50
+
51
+ specify "variable'd array.include? item" do
52
+ array = [1, 2, 3, 4]
53
+ sql = User.select { |m| array.include? m.id }.to_s
54
+ sql.should == "SELECT * FROM users WHERE users.id IN (1, 2, 3, 4)"
55
+ end
56
+
57
+ specify "simple == with variables" do
58
+ me = 'chris'
59
+ sql = User.select { |m| m.name == me }.to_s
60
+ sql.should == "SELECT * FROM users WHERE users.name = '#{me}'"
61
+ end
62
+
63
+ specify "simple == with method arguments" do
64
+ def test_it(name)
65
+ sql = User.select { |m| m.name == name }.to_s
66
+ sql.should == "SELECT * FROM users WHERE users.name = '#{name}'"
67
+ end
68
+
69
+ test_it('chris')
70
+ end
71
+
72
+ specify "simple == with instance variables" do
73
+ @me = 'chris'
74
+ sql = User.select { |m| m.name == @me }.to_s
75
+ sql.should == "SELECT * FROM users WHERE users.name = '#{@me}'"
76
+ end
77
+
78
+ specify "simple == with instance variable method call" do
79
+ require 'ostruct'
80
+ @person = OpenStruct.new(:name => 'chris')
81
+
82
+ sql = User.select { |m| m.name == @person.name }.to_s
83
+ sql.should == "SELECT * FROM users WHERE users.name = '#{@person.name}'"
84
+ end
85
+
86
+ specify "simple == with global variables" do
87
+ $my_name = 'boston'
88
+ sql = User.select { |m| m.name == $my_name }.to_s
89
+ sql.should == "SELECT * FROM users WHERE users.name = '#{$my_name}'"
90
+ end
91
+
92
+ specify "simple == with method call" do
93
+ def band
94
+ 'megadeth'
95
+ end
96
+
97
+ sql = User.select { |m| m.name == band }.to_s
98
+ sql.should == "SELECT * FROM users WHERE users.name = '#{band}'"
99
+ end
100
+
101
+ specify "simple =~ with string" do
102
+ sql = User.select { |m| m.name =~ 'chris' }.to_s
103
+ sql.should == "SELECT * FROM users WHERE users.name LIKE 'chris'"
104
+
105
+ sql = User.select { |m| m.name =~ 'chri%' }.to_s
106
+ sql.should == "SELECT * FROM users WHERE users.name LIKE 'chri%'"
107
+ end
108
+
109
+ specify "simple !~ with string" do
110
+ sql = User.select { |m| m.name !~ 'chris' }.to_s
111
+ sql.should == "SELECT * FROM users WHERE users.name NOT LIKE 'chris'"
112
+
113
+ sql = User.select { |m| !(m.name =~ 'chris') }.to_s
114
+ sql.should == "SELECT * FROM users WHERE users.name NOT LIKE 'chris'"
115
+ end
116
+
117
+ specify "simple =~ with regexp" do
118
+ sql = User.select { |m| m.name =~ /chris/ }.to_s
119
+ sql.should == "SELECT * FROM users WHERE users.name REGEXP 'chris'"
120
+ end
121
+
122
+ specify "simple =~ with regexp flags" do
123
+ sql = User.select { |m| m.name =~ /chris/i }.to_s
124
+ sql.should == "SELECT * FROM users WHERE users.name REGEXP 'chris'"
125
+ end
126
+
127
+ specify "simple LOWER()" do
128
+ sql = User.select { |m| m.name.downcase =~ 'chris%' }.to_s
129
+ sql.should == "SELECT * FROM users WHERE LOWER(users.name) LIKE 'chris%'"
130
+ end
131
+
132
+ specify "simple UPPER()" do
133
+ sql = User.select { |m| m.name.upcase =~ 'chris%' }.to_s
134
+ sql.should == "SELECT * FROM users WHERE UPPER(users.name) LIKE 'chris%'"
135
+ end
136
+
137
+ specify "undefined equality symbol" do
138
+ should.raise { User.select { |m| m.name =* /chris/ }.to_s }
139
+ end
140
+
141
+ specify "block variable / assigning variable conflict" do
142
+ m = User.select { |m| m.name == 'chris' }.to_s
143
+ m.should == "SELECT * FROM users WHERE users.name = 'chris'"
144
+ end
145
+
146
+ specify "simple == with inline ruby" do
147
+ sql = User.select { |m| m.created_at == 2.days.ago.to_s(:db) }.to_s
148
+ sql.should == "SELECT * FROM users WHERE users.created_at = '#{2.days.ago.to_s(:db)}'"
149
+ end
150
+
151
+ specify "deep chains" do
152
+ should.raise do
153
+ User.select { |m| m.created_at.something.else.perhaps }.to_s
154
+ end
155
+ end
156
+
157
+ specify "inspect" do
158
+ User.select { |u| u.name }.inspect.should.match %r(call #to_s or #to_hash)
159
+ end
160
+ end
161
+
162
+ context "Detect" do
163
+ specify "simple ==" do
164
+ User.expects(:select).returns(mock(:first => true))
165
+ User.detect { |m| m.name == 'chris' }
166
+ end
167
+
168
+ specify "nothing found" do
169
+ User.expects(:select).returns(mock(:first => nil))
170
+ User.detect { |m| m.name == 'chris' }.should.be.nil
171
+ end
172
+ end
173
+
174
+ xcontext "[]" do
175
+ specify "finds a single row" do
176
+ User.expects(:find).with(1)
177
+ User[1]
178
+ end
179
+ end
180
+
181
+ context "PostgreSQL specific" do
182
+ setup do
183
+ ActiveRecord::Base.connection = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new 'fake_connection', 'fake_logger'
184
+ end
185
+
186
+ teardown do
187
+ ActiveRecord::Base.remove_connection
188
+ end
189
+
190
+ specify "quoting of column name" do
191
+ me = 'chris'
192
+ sql = User.select { |m| m.name == me }.to_s
193
+ sql.should == %(SELECT * FROM users WHERE users."name" = '#{me}')
194
+ end
195
+
196
+ specify "simple =~ with regexp" do
197
+ sql = User.select { |m| m.name =~ /chris/ }.to_s
198
+ sql.should == %(SELECT * FROM users WHERE users."name" ~ 'chris')
199
+ end
200
+
201
+ specify "insensitive =~" do
202
+ sql = User.select { |m| m.name =~ /chris/i }.to_s
203
+ sql.should == %(SELECT * FROM users WHERE users."name" ~* 'chris')
204
+ end
205
+
206
+ specify "negated =~" do
207
+ sql = User.select { |m| m.name !~ /chris/ }.to_s
208
+ sql.should == %(SELECT * FROM users WHERE users."name" !~ 'chris')
209
+ end
210
+
211
+ specify "negated insensitive =~" do
212
+ sql = User.select { |m| m.name !~ /chris/i }.to_s
213
+ sql.should == %(SELECT * FROM users WHERE users."name" !~* 'chris')
214
+ end
215
+ end
216
+
217
+ context "MySQL specific" do
218
+ setup do
219
+ ActiveRecord::Base.connection = ActiveRecord::ConnectionAdapters::MysqlAdapter.new('connection', 'logger', 'options', 'config')
220
+ end
221
+
222
+ teardown do
223
+ ActiveRecord::Base.connection = ActiveRecord::ConnectionAdapters::FakeAdapter.new('connection', 'logger')
224
+ end
225
+
226
+ specify "quoting of column name" do
227
+ me = 'chris'
228
+ sql = User.select { |m| m.name == me }.to_s
229
+ sql.should == "SELECT * FROM users WHERE users.`name` = '#{me}'"
230
+ end
231
+
232
+ specify "simple =~ with regexp" do
233
+ sql = User.select { |m| m.name =~ /chris/ }.to_s
234
+ sql.should == "SELECT * FROM users WHERE users.`name` REGEXP 'chris'"
235
+ end
236
+
237
+ specify "negated =~" do
238
+ sql = User.select { |m| m.name !~ 'chris' }.to_s
239
+ sql.should == "SELECT * FROM users WHERE users.`name` NOT LIKE 'chris'"
240
+ end
241
+
242
+ specify "negated =~ with regexp" do
243
+ sql = User.select { |m| m.name !~ /chris/ }.to_s
244
+ sql.should == "SELECT * FROM users WHERE users.`name` NOT REGEXP 'chris'"
245
+ end
246
+ end
247
+
248
+ context "Adapter without overrides" do
249
+ setup do
250
+ ActiveRecord::Base.connection = ActiveRecord::ConnectionAdapters::FakeAdapter.new('connection', 'logger')
251
+ end
252
+
253
+ specify "quoting of column name" do
254
+ me = 'chris'
255
+ sql = User.select { |m| m.name == me }.to_s
256
+ sql.should == "SELECT * FROM users WHERE users.name = '#{me}'"
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "ActiveRecord Adapter" do
4
+ context "Slice" do
5
+ setup do
6
+ @sql = User.select { |m| m.name == 'jon' }
7
+ end
8
+
9
+ specify "first" do
10
+ conditions = { :conditions => "users.name = 'jon'", :limit => 1 }
11
+ User.expects(:find).with(:all, conditions)
12
+ @sql.first
13
+ end
14
+
15
+ specify "first with argument" do
16
+ conditions = { :conditions => "users.name = 'jon'", :limit => 5 }
17
+ User.expects(:find).with(:all, conditions)
18
+ @sql.first(5).entries
19
+ end
20
+
21
+ specify "[] with two elements" do
22
+ conditions = { :conditions => "users.name = 'jon'", :limit => 20, :offset => 10 }
23
+ User.expects(:find).with(:all, conditions)
24
+ @sql[10, 20].entries
25
+
26
+ conditions = { :conditions => "users.name = 'jon'", :limit => 20, :offset => 20 }
27
+ User.expects(:find).with(:all, conditions)
28
+ @sql[20, 20].entries
29
+ end
30
+
31
+ specify "slice is an alias of []" do
32
+ conditions = { :conditions => "users.name = 'jon'", :limit => 20, :offset => 10 }
33
+ User.expects(:find).with(:all, conditions)
34
+ @sql.slice(10, 20).entries
35
+ end
36
+
37
+ specify "[] with range" do
38
+ conditions = { :conditions => "users.name = 'jon'", :limit => 10, :offset => 10 }
39
+ User.expects(:find).with(:all, conditions)
40
+ @sql[11..20].entries
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,54 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "ActiveRecord Adapter" do
4
+ context "Sort" do
5
+ setup do
6
+ @sql = User.select { |m| m.name == 'jon' }
7
+ end
8
+
9
+ specify "simple order" do
10
+ string = @sql.sort_by { |m| m.name }.to_s
11
+ string.should == "SELECT * FROM users WHERE users.name = 'jon' ORDER BY users.name"
12
+ end
13
+
14
+ specify "simple combined order" do
15
+ string = @sql.sort_by { |m| [ m.name, m.age ] }.to_s
16
+ string.should == "SELECT * FROM users WHERE users.name = 'jon' ORDER BY users.name, users.age"
17
+ end
18
+
19
+ specify "simple combined order with single reverse" do
20
+ string = @sql.sort_by { |m| [ m.name, -m.age ] }.to_s
21
+ string.should == "SELECT * FROM users WHERE users.name = 'jon' ORDER BY users.name, users.age DESC"
22
+ end
23
+
24
+ specify "simple combined order with two reverses" do
25
+ string = @sql.sort_by { |m| [ -m.name, -m.age ] }.to_s
26
+ string.should == "SELECT * FROM users WHERE users.name = 'jon' ORDER BY users.name DESC, users.age DESC"
27
+ end
28
+
29
+ specify "reverse order with -" do
30
+ string = @sql.sort_by { |m| -m.age }.to_s
31
+ string.should == "SELECT * FROM users WHERE users.name = 'jon' ORDER BY users.age DESC"
32
+ end
33
+
34
+ xspecify "reverse order with #reverse" do
35
+ # TODO: not implemented
36
+ string = @sql.sort_by { |m| m.age }.reverse.to_s
37
+ string.should == "SELECT * FROM users WHERE users.name = 'jon' ORDER BY users.age DESC"
38
+ end
39
+
40
+ specify "random order" do
41
+ string = @sql.sort_by { rand }.to_s
42
+ string.should == "SELECT * FROM users WHERE users.name = 'jon' ORDER BY RAND()"
43
+ end
44
+
45
+ specify "non-existent method to sort by" do
46
+ should.raise(NoMethodError) { @sql.sort_by { foo }.to_s }
47
+ end
48
+
49
+ specify "Symbol#to_proc" do
50
+ string = User.sort_by(&:name).to_s
51
+ string.should == "SELECT * FROM users ORDER BY users.name"
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+ require 'ostruct'
3
+
4
+ context "Setting the ambition_source" do
5
+ setup do
6
+ # @users = [
7
+ # OpenStruct.new(:name => 'Chris', :age => 22),
8
+ # OpenStruct.new(:name => 'PJ', :age => 24),
9
+ # OpenStruct.new(:name => 'Kevin', :age => 23),
10
+ # OpenStruct.new(:name => '_why', :age => 65)
11
+ # ]
12
+ # User.ambition_source = @users
13
+ end
14
+
15
+ teardown do
16
+ # User.ambition_source = nil
17
+ end
18
+
19
+ xspecify "should run all selects / detects against that collection" do
20
+ User.detect { |u| u.name == 'Chris' }.should == @users.first
21
+ end
22
+
23
+ xspecify "should run all sorts against that collection" do
24
+ User.sort_by { |u| -u.age }.entries.should == @users.sort_by { |u| -u.age }
25
+ end
26
+
27
+ xspecify "should chain successfully" do
28
+ User.select { |u| u.age > 22 }.sort_by { |u| -u.age }.entries.should == [ @users[3], @users[1], @users[2] ]
29
+ end
30
+
31
+ xspecify "should be able to revert to normal" do
32
+ block = proc { User.select { |m| m.name == 'PJ' }.first }
33
+
34
+ User.expects(:find).never
35
+ block.call.should == @users[1]
36
+
37
+ conditions = { :conditions => "users.name = 'PJ'", :limit => 1 }
38
+ User.expects(:find).with(:first, conditions)
39
+
40
+ User.ambition_source = nil
41
+ block.call
42
+ end
43
+ end
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ ##
4
+ # Once dynamically, once hardcoded
5
+ context "Different types" do
6
+ types_hash = {
7
+ 'string' => "'string'",
8
+ :symbol => "'--- :symbol\n'",
9
+ 1 => '1',
10
+ 1.2 => '1.2',
11
+ true => '1',
12
+ false => '0',
13
+ Time.now => "'#{Time.now.to_s(:db)}'",
14
+ DateTime.now => "'#{DateTime.now.to_s(:db)}'",
15
+ Date.today => "'#{Date.today.to_s(:db)}'"
16
+ }
17
+
18
+ types_hash.each do |type, translation|
19
+ specify "simple using #{type}" do
20
+ sql = User.select { |m| m.name == type }.to_s
21
+ sql.should == "SELECT * FROM users WHERE users.name = #{translation}"
22
+ end
23
+ end
24
+
25
+ specify "float" do
26
+ sql = User.select { |m| m.name == 1.2 }.to_s
27
+ sql.should == "SELECT * FROM users WHERE users.name = 1.2"
28
+ end
29
+
30
+ specify "integer" do
31
+ sql = User.select { |m| m.name == 1 }.to_s
32
+ sql.should == "SELECT * FROM users WHERE users.name = 1"
33
+ end
34
+
35
+ specify "true" do
36
+ sql = User.select { |m| m.name == true }.to_s
37
+ sql.should == "SELECT * FROM users WHERE users.name = 1"
38
+ end
39
+
40
+ specify "false" do
41
+ sql = User.select { |m| m.name == false }.to_s
42
+ sql.should == "SELECT * FROM users WHERE users.name = 0"
43
+ end
44
+
45
+ specify "nil" do
46
+ sql = User.select { |m| m.name == nil }.to_s
47
+ sql.should == "SELECT * FROM users WHERE users.name IS NULL"
48
+ end
49
+
50
+ specify "not nil" do
51
+ sql = User.select { |m| m.name != nil }.to_s
52
+ sql.should == "SELECT * FROM users WHERE users.name IS NOT NULL"
53
+ end
54
+
55
+ specify "Time" do
56
+ sql = User.select { |m| m.name == Time.now }.to_s
57
+ sql.should == "SELECT * FROM users WHERE users.name = '#{Time.now.to_s(:db)}'"
58
+ end
59
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: ambitious-activerecord
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2008-01-29 00:00:00 -08:00
8
+ summary: An ambitious adapter for ActiveRecord
9
+ require_paths:
10
+ - lib
11
+ email: chris@ozmm.org
12
+ homepage: http://ambition.rubyforge.org/
13
+ rubyforge_project: ambition
14
+ description: An ambitious adapter for ActiveRecord
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Chris Wanstrath
31
+ files:
32
+ - lib/ambition/adapters/active_record/base.rb
33
+ - lib/ambition/adapters/active_record/query.rb
34
+ - lib/ambition/adapters/active_record/select.rb
35
+ - lib/ambition/adapters/active_record/slice.rb
36
+ - lib/ambition/adapters/active_record/sort.rb
37
+ - lib/ambition/adapters/active_record/statements.rb
38
+ - lib/ambition/adapters/active_record.rb
39
+ - test/benchmark.rb
40
+ - test/chaining_test.rb
41
+ - test/count_test.rb
42
+ - test/enumerable_test.rb
43
+ - test/helper.rb
44
+ - test/join_test.rb
45
+ - test/profiler.rb
46
+ - test/ruby_test.rb
47
+ - test/select_test.rb
48
+ - test/slice_test.rb
49
+ - test/sort_test.rb
50
+ - test/source_test.rb
51
+ - test/types_test.rb
52
+ - Manifest
53
+ - ambitious-activerecord.gemspec
54
+ test_files:
55
+ - test/chaining_test.rb
56
+ - test/count_test.rb
57
+ - test/enumerable_test.rb
58
+ - test/join_test.rb
59
+ - test/ruby_test.rb
60
+ - test/select_test.rb
61
+ - test/slice_test.rb
62
+ - test/sort_test.rb
63
+ - test/source_test.rb
64
+ - test/types_test.rb
65
+ rdoc_options: []
66
+
67
+ extra_rdoc_files: []
68
+
69
+ executables: []
70
+
71
+ extensions: []
72
+
73
+ requirements: []
74
+
75
+ dependencies:
76
+ - !ruby/object:Gem::Dependency
77
+ name: activerecord
78
+ version_requirement:
79
+ version_requirements: !ruby/object:Gem::Version::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 1.15.0
84
+ version:
85
+ - !ruby/object:Gem::Dependency
86
+ name: ambition
87
+ version_requirement:
88
+ version_requirements: !ruby/object:Gem::Version::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 0.5.0
93
+ version: