ambition 0.3.1 → 0.5.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.
Files changed (83) hide show
  1. data/Manifest +41 -48
  2. data/README +6 -203
  3. data/ambition.gemspec +111 -0
  4. data/app_generators/ambition_adapter/USAGE +1 -0
  5. data/app_generators/ambition_adapter/ambition_adapter_generator.rb +66 -0
  6. data/app_generators/ambition_adapter/templates/LICENSE +18 -0
  7. data/app_generators/ambition_adapter/templates/README +6 -0
  8. data/app_generators/ambition_adapter/templates/Rakefile +31 -0
  9. data/app_generators/ambition_adapter/templates/lib/base.rb.erb +12 -0
  10. data/app_generators/ambition_adapter/templates/lib/init.rb.erb +22 -0
  11. data/app_generators/ambition_adapter/templates/lib/query.rb.erb +52 -0
  12. data/app_generators/ambition_adapter/templates/lib/select.rb.erb +100 -0
  13. data/app_generators/ambition_adapter/templates/lib/slice.rb.erb +19 -0
  14. data/app_generators/ambition_adapter/templates/lib/sort.rb.erb +43 -0
  15. data/app_generators/ambition_adapter/templates/test/helper.rb.erb +9 -0
  16. data/app_generators/ambition_adapter/templates/test/select_test.rb.erb +157 -0
  17. data/app_generators/ambition_adapter/templates/test/slice_test.rb.erb +36 -0
  18. data/app_generators/ambition_adapter/templates/test/sort_test.rb.erb +53 -0
  19. data/bin/ambition_adapter +13 -0
  20. data/lib/ambition.rb +8 -13
  21. data/lib/ambition/api.rb +42 -35
  22. data/lib/ambition/context.rb +62 -0
  23. data/lib/ambition/{proc_to_ruby.rb → core_ext.rb} +13 -0
  24. data/lib/ambition/enumerable.rb +6 -0
  25. data/lib/ambition/processors/base.rb +126 -0
  26. data/lib/ambition/processors/ruby.rb +24 -0
  27. data/lib/ambition/processors/select.rb +105 -0
  28. data/lib/ambition/processors/slice.rb +15 -0
  29. data/lib/ambition/processors/sort.rb +51 -0
  30. data/test/adapters/exemplar/association_test.rb +34 -0
  31. data/test/adapters/exemplar/count_test.rb +0 -0
  32. data/test/adapters/exemplar/detect_test.rb +9 -0
  33. data/test/adapters/exemplar/enumerable_test.rb +0 -0
  34. data/test/adapters/exemplar/helper.rb +3 -0
  35. data/test/adapters/exemplar/index_operator.rb +6 -0
  36. data/test/adapters/exemplar/reject_test.rb +0 -0
  37. data/test/adapters/exemplar/select_test.rb +151 -0
  38. data/test/adapters/exemplar/slice_test.rb +0 -0
  39. data/test/adapters/exemplar/sort_test.rb +0 -0
  40. data/test/debug +9 -0
  41. data/test/helper.rb +2 -52
  42. metadata +56 -71
  43. data/Rakefile +0 -64
  44. data/init.rb +0 -1
  45. data/lib/ambition/database_statements.rb +0 -31
  46. data/lib/ambition/processor.rb +0 -123
  47. data/lib/ambition/query.rb +0 -91
  48. data/lib/ambition/ruby_processor.rb +0 -22
  49. data/lib/ambition/select_processor.rb +0 -149
  50. data/lib/ambition/simple_processor.rb +0 -10
  51. data/lib/ambition/sort_processor.rb +0 -47
  52. data/lib/ambition/source.rb +0 -53
  53. data/test/benchmark.rb +0 -68
  54. data/test/chaining_test.rb +0 -34
  55. data/test/console +0 -9
  56. data/test/count_test.rb +0 -17
  57. data/test/databases/boot.rb +0 -3
  58. data/test/databases/database.yml +0 -17
  59. data/test/databases/fixtures/admin.rb +0 -3
  60. data/test/databases/fixtures/companies.yml +0 -24
  61. data/test/databases/fixtures/company.rb +0 -23
  62. data/test/databases/fixtures/developer.rb +0 -11
  63. data/test/databases/fixtures/developers_projects.yml +0 -13
  64. data/test/databases/fixtures/project.rb +0 -4
  65. data/test/databases/fixtures/projects.yml +0 -7
  66. data/test/databases/fixtures/replies.yml +0 -20
  67. data/test/databases/fixtures/reply.rb +0 -5
  68. data/test/databases/fixtures/topic.rb +0 -19
  69. data/test/databases/fixtures/topics.yml +0 -32
  70. data/test/databases/fixtures/user.rb +0 -2
  71. data/test/databases/fixtures/users.yml +0 -35
  72. data/test/databases/lib/activerecord_test_connector.rb +0 -65
  73. data/test/databases/lib/load_fixtures.rb +0 -13
  74. data/test/databases/lib/schema.rb +0 -41
  75. data/test/enumerable_test.rb +0 -95
  76. data/test/join_test.rb +0 -61
  77. data/test/limit_test.rb +0 -41
  78. data/test/order_test.rb +0 -52
  79. data/test/profiler.rb +0 -34
  80. data/test/ruby_test.rb +0 -9
  81. data/test/source_test.rb +0 -43
  82. data/test/types_test.rb +0 -59
  83. data/test/where_test.rb +0 -245
@@ -1,3 +0,0 @@
1
- class Admin < User
2
- has_many :companies, :finder_sql => 'SELECT * FROM companies'
3
- end
@@ -1,24 +0,0 @@
1
- thirty_seven_signals:
2
- id: 1
3
- name: 37Signals
4
- rating: 4
5
-
6
- TextDrive:
7
- id: 2
8
- name: TextDrive
9
- rating: 3
10
-
11
- PlanetArgon:
12
- id: 3
13
- name: Planet Argon
14
- rating: 3
15
-
16
- Google:
17
- id: 4
18
- name: Google
19
- rating: 5
20
-
21
- Ionist:
22
- id: 5
23
- name: Ioni.st
24
- rating: 4
@@ -1,23 +0,0 @@
1
- class Company < ActiveRecord::Base
2
- attr_protected :rating
3
- set_sequence_name :companies_nonstd_seq
4
-
5
- validates_presence_of :name
6
- def validate
7
- errors.add('rating', 'rating should not be 2') if rating == 2
8
- end
9
-
10
- def self.with_best
11
- with_scope :find => { :conditions => ['companies.rating > ?', 3] } do
12
- yield
13
- end
14
- end
15
-
16
- def self.find_best(*args)
17
- with_best { find(*args) }
18
- end
19
-
20
- def self.calculate_best(*args)
21
- with_best { calculate(*args) }
22
- end
23
- end
@@ -1,11 +0,0 @@
1
- class Developer < User
2
- has_and_belongs_to_many :projects, :include => :topics, :order => 'projects.name'
3
-
4
- def self.with_poor_ones(&block)
5
- with_scope :find => { :conditions => ['salary <= ?', 80000], :order => 'salary' } do
6
- yield
7
- end
8
- end
9
-
10
- def self.per_page() 10 end
11
- end
@@ -1,13 +0,0 @@
1
- david_action_controller:
2
- developer_id: 1
3
- project_id: 2
4
- joined_on: 2004-10-10
5
-
6
- david_active_record:
7
- developer_id: 1
8
- project_id: 1
9
- joined_on: 2004-10-10
10
-
11
- jamis_active_record:
12
- developer_id: 2
13
- project_id: 1
@@ -1,4 +0,0 @@
1
- class Project < ActiveRecord::Base
2
- has_and_belongs_to_many :developers, :uniq => true
3
- has_many :topics
4
- end
@@ -1,7 +0,0 @@
1
- action_controller:
2
- id: 2
3
- name: Active Controller
4
-
5
- active_record:
6
- id: 1
7
- name: Active Record
@@ -1,20 +0,0 @@
1
- witty_retort:
2
- id: 1
3
- topic_id: 1
4
- content: Birdman is better!
5
- created_at: <%= 6.hours.ago.to_s(:db) %>
6
- updated_at: nil
7
-
8
- another:
9
- id: 2
10
- topic_id: 2
11
- content: Nuh uh!
12
- created_at: <%= 1.hour.ago.to_s(:db) %>
13
- updated_at: nil
14
-
15
- spam:
16
- id: 3
17
- topic_id: 1
18
- content: Nice site!
19
- created_at: <%= 1.hour.ago.to_s(:db) %>
20
- updated_at: nil
@@ -1,5 +0,0 @@
1
- class Reply < ActiveRecord::Base
2
- belongs_to :topic, :include => [:replies]
3
-
4
- validates_presence_of :content
5
- end
@@ -1,19 +0,0 @@
1
- class Topic < ActiveRecord::Base
2
- has_many :replies, :dependent => :destroy, :order => 'replies.created_at DESC'
3
- belongs_to :project
4
-
5
- # pretend find and count were extended and accept an extra option
6
- # if there is a :foo option, prepend its value to collection
7
- def self.find(*args)
8
- more = []
9
- more << args.last.delete(:foo) if args.last.is_a?(Hash) and args.last[:foo]
10
- res = super
11
- more.empty?? res : more + res
12
- end
13
-
14
- # if there is a :foo option, always return 100
15
- def self.count(*args)
16
- return 100 if args.last.is_a?(Hash) and args.last[:foo]
17
- super
18
- end
19
- end
@@ -1,32 +0,0 @@
1
- futurama:
2
- id: 1
3
- title: Isnt futurama awesome?
4
- subtitle: It really is, isnt it.
5
- content: I like futurama
6
- created_at: <%= 1.day.ago.to_s(:db) %>
7
- updated_at: <%= 1.day.ago.to_s(:db) %>
8
-
9
- harvey_birdman:
10
- id: 2
11
- title: Harvey Birdman is the king of all men
12
- subtitle: yup
13
- content: He really is
14
- created_at: <%= 2.hours.ago.to_s(:db) %>
15
- updated_at: <%= 2.hours.ago.to_s(:db) %>
16
-
17
- rails:
18
- id: 3
19
- project_id: 1
20
- title: Rails is nice
21
- subtitle: It makes me happy
22
- content: except when I have to hack internals to fix pagination. even then really.
23
- created_at: <%= 20.minutes.ago.to_s(:db) %>
24
- updated_at: <%= 20.minutes.ago.to_s(:db) %>
25
-
26
- ar:
27
- id: 4
28
- project_id: 1
29
- title: ActiveRecord sometimes freaks me out
30
- content: "I mean, what's the deal with eager loading?"
31
- created_at: <%= 15.minutes.ago.to_s(:db) %>
32
- updated_at: <%= 15.minutes.ago.to_s(:db) %>
@@ -1,2 +0,0 @@
1
- class User < ActiveRecord::Base
2
- end
@@ -1,35 +0,0 @@
1
- david:
2
- id: 1
3
- name: David
4
- salary: 80000
5
- type: Developer
6
-
7
- jamis:
8
- id: 2
9
- name: Jamis
10
- salary: 150000
11
- type: Developer
12
-
13
- <% for digit in 3..10 %>
14
- dev_<%= digit %>:
15
- id: <%= digit %>
16
- name: fixture_<%= digit %>
17
- salary: 100000
18
- type: Developer
19
- <% end %>
20
-
21
- poor_jamis:
22
- id: 11
23
- name: Jamis
24
- salary: 9000
25
- type: Developer
26
-
27
- admin:
28
- id: 12
29
- name: admin
30
- type: Admin
31
-
32
- goofy:
33
- id: 13
34
- name: Goofy
35
- type: Admin
@@ -1,65 +0,0 @@
1
- class ActiveRecordTestConnector
2
- cattr_accessor :able_to_connect
3
- cattr_accessor :connected
4
-
5
- # Set our defaults
6
- self.connected = false
7
- self.able_to_connect = true
8
-
9
- def self.setup
10
- unless connected || !able_to_connect
11
- setup_connection
12
- load_schema
13
- require_fixture_models
14
- self.connected = true
15
- end
16
- rescue Exception => e # errors from ActiveRecord setup
17
- if e.to_s =~ /unknown database/i
18
- puts "\nPlease create an `ambition_development' database to play!"
19
- else
20
- $stderr.puts "\nSkipping ActiveRecord assertion tests: #{e}"
21
- end
22
- self.able_to_connect = false
23
- end
24
-
25
- private
26
-
27
- def self.setup_connection
28
- if Object.const_defined?(:ActiveRecord)
29
- config_file = File.dirname(__FILE__) + '/../database.yml'
30
- ActiveRecord::Base.logger = Logger.new STDOUT
31
-
32
- case adapter = ENV['ADAPTER'] || 'mysql'
33
- when 'sqlite3'
34
- options = { :database => ':memory:', :adapter => 'sqlite3', :timeout => 500 }
35
- ActiveRecord::Base.configurations = { 'sqlite3_ar_integration' => options }
36
- else
37
- options = YAML.load_file(config_file)[adapter]
38
- end
39
-
40
- puts "Using #{adapter}"
41
-
42
- ActiveRecord::Base.establish_connection(options)
43
- ActiveRecord::Base.connection
44
-
45
- unless Object.const_defined?(:QUOTED_TYPE)
46
- Object.send :const_set, :QUOTED_TYPE, ActiveRecord::Base.connection.quote_column_name('type')
47
- end
48
- else
49
- raise "Can't setup connection since ActiveRecord isn't loaded."
50
- end
51
- end
52
-
53
- # Load actionpack sqlite tables
54
- def self.load_schema
55
- ActiveRecord::Base.silence do
56
- load File.dirname(__FILE__) + "/schema.rb"
57
- end
58
- end
59
-
60
- def self.require_fixture_models
61
- models = Dir.glob(File.dirname(__FILE__) + "/../fixtures/*.rb")
62
- models = (models.grep(/user.rb/) + models).uniq
63
- models.each {|f| require f}
64
- end
65
- end
@@ -1,13 +0,0 @@
1
- dirname = File.dirname(__FILE__)
2
- %w(rubygems active_record active_record/version active_record/fixtures).each {|f| require f}
3
- puts " (ActiveRecord v#{ActiveRecord::VERSION::STRING})"
4
- require File.join(dirname, 'activerecord_test_connector')
5
-
6
- # setup the connection
7
- ActiveRecordTestConnector.setup
8
-
9
- # load all fixtures
10
- fixture_path = File.join(dirname, '..', 'fixtures')
11
- Fixtures.create_fixtures(fixture_path, tables = ActiveRecord::Base.connection.tables - %w(schema_info))
12
-
13
- puts "Available models: #{Dir[fixture_path+'/*.rb'].map{|f|File.basename(f,'.rb')}.map(&:classify).to_sentence}"
@@ -1,41 +0,0 @@
1
- ActiveRecord::Schema.define(:version => 0) do
2
- create_table :users, :force => true do |t|
3
- t.column :name, :string
4
- t.column :type, :string
5
- t.column :salary, :integer, :default => 70_000
6
- t.column :created_at, :datetime, :null => false
7
- t.column :updated_at, :datetime, :null => false
8
- end
9
-
10
- create_table :replies, :force => true do |t|
11
- t.column :content, :string
12
- t.column :topic_id, :integer
13
- t.column :created_at, :datetime, :null => false
14
- t.column :updated_at, :datetime, :null => false
15
- end
16
-
17
- create_table :topics, :force => true do |t|
18
- t.column :project_id, :integer
19
- t.column :title, :string
20
- t.column :subtitle, :string
21
- t.column :content, :text
22
- t.column :created_at, :datetime, :null => false
23
- t.column :updated_at, :datetime, :null => false
24
- end
25
-
26
- create_table :projects, :force => true do |t|
27
- t.column :name, :string
28
- end
29
-
30
- create_table :developers_projects, :force => true do |t|
31
- t.column :developer_id, :integer
32
- t.column :project_id, :integer
33
- t.column :joined_on, :datetime
34
- t.column :access_level, :integer, :default => 1
35
- end
36
-
37
- create_table :companies, :force => true do |t|
38
- t.column :name, :string
39
- t.column :rating, :integer
40
- end
41
- end
@@ -1,95 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- context "Each" do
4
- specify "simple ==" do
5
- hash = { :conditions => "users.age = 21" }
6
- User.expects(:find).with(:all, hash).returns([])
7
- User.select { |m| m.age == 21 }.each do |user|
8
- puts user.name
9
- end
10
- end
11
-
12
- specify "limit and conditions" do
13
- hash = { :limit => 5, :conditions => "users.age = 21" }
14
- User.expects(:find).with(:all, hash).returns([])
15
- User.select { |m| m.age == 21 }.first(5).each do |user|
16
- puts user.name
17
- end
18
- end
19
-
20
- specify "limit and conditions and order" do
21
- hash = { :limit => 5, :conditions => "users.age = 21", :order => 'users.name' }
22
- User.expects(:find).with(:all, hash).returns([])
23
- User.select { |m| m.age == 21 }.sort_by { |m| m.name }.first(5).each do |user|
24
- puts user.name
25
- end
26
- end
27
-
28
- specify "limit and order" do
29
- hash = { :limit => 5, :order => 'users.name' }
30
- User.expects(:find).with(:all, hash).returns([])
31
- User.sort_by { |m| m.name }.first(5).each do |user|
32
- puts user.name
33
- end
34
- end
35
- end
36
-
37
- context "Enumerable Methods" do
38
- specify "map" do
39
- hash = { :conditions => "users.age = 21" }
40
- User.expects(:find).with(:all, hash).returns([])
41
- User.select { |m| m.age == 21 }.map { |u| u.name }
42
- end
43
-
44
- specify "each_with_index" do
45
- hash = { :conditions => "users.age = 21" }
46
- User.expects(:find).with(:all, hash).returns([])
47
- User.select { |m| m.age == 21 }.each_with_index do |user, i|
48
- puts "#{i}: #{user.name}"
49
- end
50
- end
51
-
52
- specify "any?" do
53
- User.expects(:count).with(:conditions => "users.age > 21").returns(1)
54
- User.any? { |u| u.age > 21 }.should == true
55
- end
56
-
57
- specify "all?" do
58
- User.expects(:count).at_least_once.returns(10, 20)
59
- User.all? { |u| u.age > 21 }.should == false
60
-
61
- User.expects(:count).at_least_once.returns(10, 10)
62
- User.all? { |u| u.age > 21 }.should == true
63
- end
64
-
65
- specify "empty?" do
66
- User.expects(:count).with(:conditions => "users.age > 21").returns(1)
67
- User.select { |u| u.age > 21 }.empty?.should.equal false
68
-
69
- User.expects(:count).with(:conditions => "users.age > 21").returns(0)
70
- User.select { |u| u.age > 21 }.empty?.should.equal true
71
- end
72
-
73
- specify "entries" do
74
- User.expects(:find).with(:all, {})
75
- User.entries
76
-
77
- hash = { :conditions => "users.age = 21" }
78
- User.expects(:find).with(:all, hash).returns([])
79
- User.select { |m| m.age == 21 }.entries
80
- end
81
-
82
- specify "to_a" do
83
- User.expects(:find).with(:all, {})
84
- User.to_a
85
- end
86
-
87
- xspecify "each_slice" do
88
- end
89
-
90
- xspecify "max" do
91
- end
92
-
93
- xspecify "min" do
94
- end
95
- end
data/test/join_test.rb DELETED
@@ -1,61 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- context "Joins" do
4
- specify "simple == on an association" do
5
- sql = User.select { |m| m.account.email == 'chris@ozmm.org' }
6
- sql.to_hash.should == {
7
- :conditions => "accounts.email = 'chris@ozmm.org'",
8
- :include => [:account]
9
- }
10
- end
11
-
12
- specify "simple mixed == on an association" do
13
- sql = User.select { |m| m.name == 'chris' && m.account.email == 'chris@ozmm.org' }
14
- sql.to_hash.should == {
15
- :conditions => "(users.name = 'chris' AND accounts.email = 'chris@ozmm.org')",
16
- :include => [:account]
17
- }
18
- end
19
-
20
- specify "multiple associations" do
21
- sql = User.select { |m| m.ideas.title == 'New Freezer' || m.invites.email == 'pj@hyett.com' }
22
- sql.to_hash.should == {
23
- :conditions => "(ideas.title = 'New Freezer' OR invites.email = 'pj@hyett.com')",
24
- :include => [:ideas, :invites]
25
- }
26
- end
27
-
28
- specify "belongs_to" do
29
- sql = User.select { |m| m.account.id > 20 }
30
- sql.to_hash.should == {
31
- :conditions => "accounts.id > 20",
32
- :include => [:account]
33
- }
34
- end
35
-
36
- specify "complex joins have no to_s" do
37
- sql = User.select { |m| m.account.id > 20 }
38
- should.raise { sql.to_s }
39
- end
40
-
41
- specify "non-existant associations" do
42
- sql = User.select { |m| m.liquor.brand == 'Jack' }
43
- should.raise { sql.to_hash }
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