ambition 0.3.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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