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
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2007 Your Name
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,6 @@
1
+ <%= string = "An Ambitious #{adapter_module} Adapter" %>
2
+ <%= '=' * string.size %>
3
+
4
+ More information on Ambition:
5
+ -> http://ambition.rubyforge.org
6
+ -> http://groups.google.com/group/ambition-rb/
@@ -0,0 +1,31 @@
1
+ require 'rake'
2
+
3
+ Version = '0.1.0'
4
+
5
+ begin
6
+ require 'rubygems'
7
+ gem 'echoe', '>=2.7'
8
+ ENV['RUBY_FLAGS'] = ""
9
+ require 'echoe'
10
+
11
+ Echoe.new('ambitious-<%= adapter_name %>') do |p|
12
+ p.dependencies << '<%= adapter_name %> >=1.0'
13
+ p.summary = "An ambitious adapter for <%= adapter_module %>"
14
+ p.author = 'Your Name'
15
+ p.email = "your@email.com"
16
+
17
+ p.project = 'ambition'
18
+ p.url = "http://ambition.rubyforge.org/"
19
+ p.test_pattern = 'test/*_test.rb'
20
+ p.version = Version
21
+ p.dependencies << 'ambition >=0.5.0'
22
+ end
23
+
24
+ rescue LoadError
25
+ puts "Not doing any of the Echoe gemmy stuff, because you don't have the specified gem versions"
26
+ end
27
+
28
+ desc 'Install as a gem'
29
+ task :install_gem do
30
+ puts `rake manifest package && gem install pkg/ambitious-<%= adapter_name %>-#{Version}.gem`
31
+ end
@@ -0,0 +1,12 @@
1
+ module Ambition
2
+ module Adapters
3
+ module <%= adapter_module %>
4
+ class Base
5
+ ##
6
+ # Extract common functionality into this class.
7
+ # All your classes, by default, inherit from this
8
+ # one -- Query and the Translators.
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ require 'ambition'
2
+ require '<%= adapter_name %>'
3
+ require 'ambition/adapters/<%= adapter_name %>/base'
4
+ require 'ambition/adapters/<%= adapter_name %>/query'
5
+ require 'ambition/adapters/<%= adapter_name %>/select'
6
+ require 'ambition/adapters/<%= adapter_name %>/sort'
7
+ require 'ambition/adapters/<%= adapter_name %>/slice'
8
+
9
+ ##
10
+ # This is where you inject Ambition into your target.
11
+ #
12
+ # Use `extend' if you are injecting a class, `include' if you are
13
+ # injecting instances of that class.
14
+ #
15
+ # You must also set the `ambition_adapter' class variable on your target
16
+ # class, regardless of whether you are injecting instances or the class itself.
17
+ #
18
+ # You probably want something like this:
19
+ #
20
+ # <%= adapter_module %>::Base.extend Ambition::API
21
+ # <%= adapter_module %>::Base.ambition_adapter = Ambition::Adapters::<%= adapter_module %>
22
+ #
@@ -0,0 +1,52 @@
1
+ =begin
2
+
3
+ These methods are king:
4
+
5
+ - owner
6
+ - clauses
7
+ - stash
8
+
9
+ +owner+ is the class from which the request was generated.
10
+
11
+ User.select { |u| u.name == 'Pork' }
12
+ # => owner == User
13
+
14
+ +clauses+ is the hash of translated arrays, keyed by processors
15
+
16
+ User.select { |u| u.name == 'Pork' }
17
+ # => clauses == { :select => [ "users.name = 'Pork'" ] }
18
+
19
+ +stash+ is your personal private stash. A hash you can use for
20
+ keeping stuff around.
21
+
22
+ User.select { |u| u.profile.name == 'Pork' }
23
+ # => stash == { :include => [ :profile ] }
24
+
25
+ The above is totally arbitrary. It's basically a way for your
26
+ translators to talk to each other and, more importantly, to the Query
27
+ object.
28
+
29
+ =end
30
+ module Ambition
31
+ module Adapters
32
+ module <%= adapter_module %>
33
+ class Query < Base
34
+ def kick
35
+ raise "Example: owner.find(:all, to_hash)"
36
+ end
37
+
38
+ def size
39
+ raise "Example: owner.count(to_hash)"
40
+ end
41
+
42
+ def to_hash
43
+ raise "Not implemented"
44
+ end
45
+
46
+ def to_s
47
+ raise "Not implemented"
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,100 @@
1
+ ##
2
+ # The format of the documentation herein is:
3
+ #
4
+ # >> method with block
5
+ # => methods on this class called by Ambition (with arguments)
6
+ #
7
+ module Ambition
8
+ module Adapters
9
+ module <%= adapter_module %>
10
+ class Select < Base
11
+ # >> select { |u| u.name == 'chris' }
12
+ # => #call(:name)
13
+ def call(method)
14
+ raise "Not implemented."
15
+ end
16
+
17
+ # >> select { |u| u.name.downcase == 'chris' }
18
+ # => #call(:name, :downcase)
19
+ def chained_call(*methods)
20
+ # An idiom here is to call the chained method and pass it
21
+ # the first method.
22
+ #
23
+ # if respond_to? methods[1]
24
+ # send(methods[1], methods[0])
25
+ # end
26
+ #
27
+ # In the above example, this translates to calling:
28
+ #
29
+ # #downcase(:name)
30
+ #
31
+ raise "Not implemented."
32
+ end
33
+
34
+ # &&
35
+ # >> select { |u| u.name == 'chris' && u.age == 22 }
36
+ # => #both( processed left side, processed right side )
37
+ def both(left, right)
38
+ raise "Not implemented."
39
+ end
40
+
41
+ # ||
42
+ # >> select { |u| u.name == 'chris' || u.age == 22 }
43
+ # => #either( processed left side, processed right side )
44
+ def either(left, right)
45
+ raise "Not implemented."
46
+ end
47
+
48
+ # >> select { |u| u.name == 'chris' }
49
+ # => #==( call(:name), 'chris' )
50
+ def ==(left, right)
51
+ raise "Not implemented."
52
+ end
53
+
54
+ # !=
55
+ # >> select { |u| u.name != 'chris' }
56
+ # => #not_equal( call(:name), 'chris' )
57
+ def not_equal(left, right)
58
+ raise "Not implemented."
59
+ end
60
+
61
+ # >> select { |u| u.name =~ 'chris' }
62
+ # => #=~( call(:name), 'chris' )
63
+ def =~(left, right)
64
+ raise "Not implemented."
65
+ end
66
+
67
+ # !~
68
+ # >> select { |u| u.name !~ 'chris' }
69
+ # => #not_regexp( call(:name), 'chris' )
70
+ def not_regexp(left, right)
71
+ raise "Not implemented."
72
+ end
73
+
74
+ ##
75
+ # Etc.
76
+ def <(left, right)
77
+ raise "Not implemented."
78
+ end
79
+
80
+ def >(left, right)
81
+ raise "Not implemented."
82
+ end
83
+
84
+ def >=(left, right)
85
+ raise "Not implemented."
86
+ end
87
+
88
+ def <=(left, right)
89
+ raise "Not implemented."
90
+ end
91
+
92
+ # >> select { |u| [1, 2, 3].include? u.id }
93
+ # => #include?( [1, 2, 3], call(:id) )
94
+ def include?(left, right)
95
+ raise "Not implemented."
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,19 @@
1
+ module Ambition
2
+ module Adapters
3
+ module <%= adapter_module %>
4
+ class Slice < Base
5
+ # >> User.first(5)
6
+ # => #slice(0, 5)
7
+ #
8
+ # >> User.first
9
+ # => #slice(0, 1)
10
+ #
11
+ # >> User[10, 20]
12
+ # => #slice(10, 20)
13
+ def slice(start, length)
14
+ raise "Not implemented."
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ module Ambition
2
+ module Adapters
3
+ module <%= adapter_module %>
4
+ class Sort < Base
5
+ # >> sort_by { |u| u.age }
6
+ # => #sort_by(:age)
7
+ def sort_by(method)
8
+ raise "Not implemented."
9
+ end
10
+
11
+ # >> sort_by { |u| -u.age }
12
+ # => #reverse_sort_by(:age)
13
+ def reverse_sort_by(method)
14
+ raise "Not implemented."
15
+ end
16
+
17
+ # >> sort_by { |u| u.profile.name }
18
+ # => #chained_sort_by(:profile, :name)
19
+ def chained_sort_by(receiver, method)
20
+ raise "Not implemented."
21
+ end
22
+
23
+ # >> sort_by { |u| -u.profile.name }
24
+ # => #chained_reverse_sort_by(:profile, :name)
25
+ def chained_reverse_sort_by(receiver, method)
26
+ raise "Not implemented."
27
+ end
28
+
29
+ # >> sort_by(&:name)
30
+ # => #to_proc(:name)
31
+ def to_proc(symbol)
32
+ raise "Not implemented."
33
+ end
34
+
35
+ # >> sort_by { rand }
36
+ # => #rand
37
+ def rand
38
+ raise "Not implemented."
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,9 @@
1
+ %w( rubygems test/spec mocha English ).each { |f| require f }
2
+
3
+ begin
4
+ require 'redgreen'
5
+ rescue LoadError
6
+ end
7
+
8
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
9
+ require 'ambition/adapters/<%= adapter_name %>'
@@ -0,0 +1,157 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "<%= adapter_module %> Adapter :: Select" do
4
+ setup do
5
+ @klass = User
6
+ end
7
+
8
+ xspecify "==" do
9
+ translator = @klass.select { |m| m.name == 'jon' }
10
+ translator.to_s.should == %Q(foo)
11
+ end
12
+
13
+ xspecify "!=" do
14
+ translator = @klass.select { |m| m.name != 'jon' }
15
+ translator.to_s.should == %Q(foo)
16
+ end
17
+
18
+ xspecify "== && ==" do
19
+ translator = @klass.select { |m| m.name == 'jon' && m.age == 21 }
20
+ translator.to_s.should == %Q(foo)
21
+ end
22
+
23
+ xspecify "== || ==" do
24
+ translator = @klass.select { |m| m.name == 'jon' || m.age == 21 }
25
+ translator.to_s.should == %Q(foo)
26
+ end
27
+
28
+ xspecify "mixed && and ||" do
29
+ translator = @klass.select { |m| m.name == 'jon' || m.age == 21 && m.password == 'pass' }
30
+ translator.to_s.should == %Q(foo)
31
+ end
32
+
33
+ xspecify "grouped && and ||" do
34
+ translator = @klass.select { |m| (m.name == 'jon' || m.name == 'rick') && m.age == 21 }
35
+ translator.to_s.should == %Q(foo)
36
+ end
37
+
38
+ xspecify ">/<" do
39
+ translator = @klass.select { |m| m.age > 21 }
40
+ translator.to_s.should == %Q(foo)
41
+
42
+ translator = @klass.select { |m| m.age >= 21 }
43
+ translator.to_s.should == %Q(foo)
44
+
45
+ translator = @klass.select { |m| m.age < 21 }
46
+ translator.to_s.should == %Q(foo)
47
+ end
48
+
49
+ xspecify "array.include? item" do
50
+ translator = @klass.select { |m| [1, 2, 3, 4].include? m.id }
51
+ translator.to_s.should == %Q(foo)
52
+ end
53
+
54
+ xspecify "variabled array.include? item" do
55
+ array = [1, 2, 3, 4]
56
+ translator = @klass.select { |m| array.include? m.id }
57
+ translator.to_s.should == %Q(foo)
58
+ end
59
+
60
+ xspecify "== with variables" do
61
+ me = 'chris'
62
+ translator = @klass.select { |m| m.name == me }
63
+ translator.to_s.should == %Q(foo)
64
+ end
65
+
66
+ xspecify "== with method arguments" do
67
+ def test_it(name)
68
+ translator = @klass.select { |m| m.name == name }
69
+ translator.to_s.should == %Q(foo)
70
+ end
71
+
72
+ test_it('chris')
73
+ end
74
+
75
+ xspecify "== with instance variables" do
76
+ @me = 'chris'
77
+ translator = @klass.select { |m| m.name == @me }
78
+ translator.to_s.should == %Q(foo)
79
+ end
80
+
81
+ xspecify "== with instance variable method call" do
82
+ require 'ostruct'
83
+ @person = OpenStruct.new(:name => 'chris')
84
+
85
+ translator = @klass.select { |m| m.name == @person.name }
86
+ translator.to_s.should == %Q(foo)
87
+ end
88
+
89
+ xspecify "== with global variables" do
90
+ $my_name = 'boston'
91
+ translator = @klass.select { |m| m.name == $my_name }
92
+ translator.to_s.should == %Q(foo)
93
+ end
94
+
95
+ xspecify "== with method call" do
96
+ def band
97
+ 'skinny puppy'
98
+ end
99
+
100
+ translator = @klass.select { |m| m.name == band }
101
+ translator.to_s.should == %Q(foo)
102
+ end
103
+
104
+ xspecify "=~ with string" do
105
+ translator = @klass.select { |m| m.name =~ 'chris' }
106
+ translator.to_s.should == %Q(foo)
107
+
108
+ translator = @klass.select { |m| m.name =~ 'chri%' }
109
+ translator.to_s.should == %Q(foo)
110
+ end
111
+
112
+ xspecify "!~ with string" do
113
+ translator = @klass.select { |m| m.name !~ 'chris' }
114
+ translator.to_s.should == %Q(foo)
115
+
116
+ translator = @klass.select { |m| !(m.name =~ 'chris') }
117
+ translator.to_s.should == %Q(foo)
118
+ end
119
+
120
+ xspecify "=~ with regexp" do
121
+ translator = @klass.select { |m| m.name =~ /chris/ }
122
+ translator.to_s.should == %Q(foo)
123
+ end
124
+
125
+ xspecify "=~ with regexp flags" do
126
+ translator = @klass.select { |m| m.name =~ /chris/i }
127
+ translator.to_s.should == %Q(foo)
128
+ end
129
+
130
+ xspecify "downcase" do
131
+ translator = @klass.select { |m| m.name.downcase =~ 'chris%' }
132
+ translator.to_s.should == %Q(foo)
133
+ end
134
+
135
+ xspecify "upcase" do
136
+ translator = @klass.select { |m| m.name.upcase =~ 'chris%' }
137
+ translator.to_s.should == %Q(foo)
138
+ end
139
+
140
+ xspecify "undefined equality symbol" do
141
+ should.raise { @klass.select { |m| m.name =* /chris/ } }
142
+ end
143
+
144
+ xspecify "block variable / assigning variable conflict" do
145
+ m = @klass.select { |m| m.name == 'chris' }
146
+ m.should == %Q(foo)
147
+ end
148
+
149
+ xspecify "== with inline ruby" do
150
+ translator = @klass.select { |m| m.created_at == Time.now.to_s }
151
+ translator.to_s.should == %Q(foo)
152
+ end
153
+
154
+ xspecify "inspect" do
155
+ @klass.select { |u| u.name }.inspect.should.match %r(call #to_s or #to_hash)
156
+ end
157
+ end