benhoskings-ambition 0.5.4.3 → 0.5.4.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg
2
+ live
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "benhoskings-ambition"
5
+ gemspec.summary = "Ambition builds yer API calls from plain jane Ruby."
6
+ gemspec.description = "Ambition builds yer API calls from plain jane Ruby."
7
+ gemspec.email = "chris@ozmm.org"
8
+ gemspec.homepage = "http://errtheblog.com/"
9
+ gemspec.authors = ['Chris Wanstrath', 'Ben Hoskings']
10
+ gemspec.add_dependency 'ParseTree', '=2.1.1'
11
+ gemspec.add_dependency 'ruby2ruby', '=1.1.8'
12
+ gemspec.add_dependency 'rubigen', '>=1.1.1'
13
+ end
14
+ rescue LoadError
15
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
16
+ end
data/ambition.gemspec CHANGED
@@ -1,120 +1,121 @@
1
-
2
- # Gem::Specification for Ambition-0.5.4
3
- # Originally generated by Echoe
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
4
5
 
5
6
  Gem::Specification.new do |s|
6
7
  s.name = %q{ambition}
7
- s.version = "0.5.4.3"
8
-
9
- s.specification_version = 2 if s.respond_to? :specification_version=
8
+ s.version = "0.5.4.4"
10
9
 
11
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
11
  s.authors = ["Chris Wanstrath", "Ben Hoskings"]
13
- s.date = %q{2008-04-26}
12
+ s.date = %q{2009-10-22}
14
13
  s.default_executable = %q{ambition_adapter}
15
14
  s.description = %q{Ambition builds yer API calls from plain jane Ruby.}
16
- s.email = %q{chris@ozmm.org, ben@hoskings.net}
15
+ s.email = %q{chris@ozmm.org}
17
16
  s.executables = ["ambition_adapter"]
18
- s.extra_rdoc_files = ["bin/ambition_adapter", "lib/ambition/api.rb", "lib/ambition/context.rb", "lib/ambition/core_ext.rb", "lib/ambition/enumerable.rb", "lib/ambition/processors/base.rb", "lib/ambition/processors/ruby.rb", "lib/ambition/processors/select.rb", "lib/ambition/processors/slice.rb", "lib/ambition/processors/sort.rb", "lib/ambition/sexp_translator.rb", "lib/ambition.rb", "LICENSE", "README"]
19
- s.files = ["app_generators/ambition_adapter/ambition_adapter_generator.rb", "app_generators/ambition_adapter/templates/lib/adapter/base.rb.erb", "app_generators/ambition_adapter/templates/lib/adapter/query.rb.erb", "app_generators/ambition_adapter/templates/lib/adapter/select.rb.erb", "app_generators/ambition_adapter/templates/lib/adapter/slice.rb.erb", "app_generators/ambition_adapter/templates/lib/adapter/sort.rb.erb", "app_generators/ambition_adapter/templates/lib/init.rb.erb", "app_generators/ambition_adapter/templates/LICENSE", "app_generators/ambition_adapter/templates/Rakefile", "app_generators/ambition_adapter/templates/README", "app_generators/ambition_adapter/templates/test/helper.rb.erb", "app_generators/ambition_adapter/templates/test/select_test.rb.erb", "app_generators/ambition_adapter/templates/test/slice_test.rb.erb", "app_generators/ambition_adapter/templates/test/sort_test.rb.erb", "app_generators/ambition_adapter/USAGE", "bin/ambition_adapter", "lib/ambition/api.rb", "lib/ambition/context.rb", "lib/ambition/core_ext.rb", "lib/ambition/enumerable.rb", "lib/ambition/processors/base.rb", "lib/ambition/processors/ruby.rb", "lib/ambition/processors/select.rb", "lib/ambition/processors/slice.rb", "lib/ambition/processors/sort.rb", "lib/ambition/sexp_translator.rb", "lib/ambition.rb", "LICENSE", "Manifest", "README", "test/adapters/exemplar/association_test.rb", "test/adapters/exemplar/count_test.rb", "test/adapters/exemplar/detect_test.rb", "test/adapters/exemplar/enumerable_test.rb", "test/adapters/exemplar/helper.rb", "test/adapters/exemplar/index_operator.rb", "test/adapters/exemplar/reject_test.rb", "test/adapters/exemplar/select_test.rb", "test/adapters/exemplar/slice_test.rb", "test/adapters/exemplar/sort_test.rb", "test/debug", "test/helper.rb", "ambition.gemspec"]
20
- s.has_rdoc = true
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README"
20
+ ]
21
+ s.files = [
22
+ ".gitignore",
23
+ "LICENSE",
24
+ "Manifest",
25
+ "README",
26
+ "Rakefile",
27
+ "ambition.gemspec",
28
+ "app_generators/ambition_adapter/USAGE",
29
+ "app_generators/ambition_adapter/ambition_adapter_generator.rb",
30
+ "app_generators/ambition_adapter/templates/LICENSE",
31
+ "app_generators/ambition_adapter/templates/README",
32
+ "app_generators/ambition_adapter/templates/Rakefile",
33
+ "app_generators/ambition_adapter/templates/lib/adapter/base.rb.erb",
34
+ "app_generators/ambition_adapter/templates/lib/adapter/query.rb.erb",
35
+ "app_generators/ambition_adapter/templates/lib/adapter/select.rb.erb",
36
+ "app_generators/ambition_adapter/templates/lib/adapter/slice.rb.erb",
37
+ "app_generators/ambition_adapter/templates/lib/adapter/sort.rb.erb",
38
+ "app_generators/ambition_adapter/templates/lib/init.rb.erb",
39
+ "app_generators/ambition_adapter/templates/test/helper.rb.erb",
40
+ "app_generators/ambition_adapter/templates/test/select_test.rb.erb",
41
+ "app_generators/ambition_adapter/templates/test/slice_test.rb.erb",
42
+ "app_generators/ambition_adapter/templates/test/sort_test.rb.erb",
43
+ "bin/ambition_adapter",
44
+ "deps.rip",
45
+ "lib/ambition.rb",
46
+ "lib/ambition/api.rb",
47
+ "lib/ambition/context.rb",
48
+ "lib/ambition/core_ext.rb",
49
+ "lib/ambition/enumerable.rb",
50
+ "lib/ambition/processors/base.rb",
51
+ "lib/ambition/processors/ruby.rb",
52
+ "lib/ambition/processors/select.rb",
53
+ "lib/ambition/processors/slice.rb",
54
+ "lib/ambition/processors/sort.rb",
55
+ "lib/ambition/sexp_translator.rb",
56
+ "site/Rakefile",
57
+ "site/src/_adapters.textile",
58
+ "site/src/adapters.textile",
59
+ "site/src/adapters/activerecord.textile",
60
+ "site/src/api.textile",
61
+ "site/src/index.textile",
62
+ "site/src/layout.textile",
63
+ "site/src/static/bg.png",
64
+ "site/src/static/code_highlighter.js",
65
+ "site/src/static/css.js",
66
+ "site/src/static/html.js",
67
+ "site/src/static/hubris.css",
68
+ "site/src/static/javascript.js",
69
+ "site/src/static/ruby.js",
70
+ "test/adapters/exemplar/association_test.rb",
71
+ "test/adapters/exemplar/count_test.rb",
72
+ "test/adapters/exemplar/detect_test.rb",
73
+ "test/adapters/exemplar/enumerable_test.rb",
74
+ "test/adapters/exemplar/helper.rb",
75
+ "test/adapters/exemplar/index_operator.rb",
76
+ "test/adapters/exemplar/reject_test.rb",
77
+ "test/adapters/exemplar/select_test.rb",
78
+ "test/adapters/exemplar/slice_test.rb",
79
+ "test/adapters/exemplar/sort_test.rb",
80
+ "test/debug",
81
+ "test/helper.rb"
82
+ ]
21
83
  s.homepage = %q{http://errtheblog.com/}
22
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Ambition", "--main", "README"]
84
+ s.rdoc_options = ["--charset=UTF-8"]
23
85
  s.require_paths = ["lib"]
24
- s.required_ruby_version = Gem::Requirement.new(">= 1.8.6")
25
- s.rubyforge_project = %q{err}
26
- s.rubygems_version = %q{1.3.1}
86
+ s.rubygems_version = %q{1.3.5}
27
87
  s.summary = %q{Ambition builds yer API calls from plain jane Ruby.}
88
+ s.test_files = [
89
+ "test/adapters/exemplar/association_test.rb",
90
+ "test/adapters/exemplar/count_test.rb",
91
+ "test/adapters/exemplar/detect_test.rb",
92
+ "test/adapters/exemplar/enumerable_test.rb",
93
+ "test/adapters/exemplar/helper.rb",
94
+ "test/adapters/exemplar/index_operator.rb",
95
+ "test/adapters/exemplar/reject_test.rb",
96
+ "test/adapters/exemplar/select_test.rb",
97
+ "test/adapters/exemplar/slice_test.rb",
98
+ "test/adapters/exemplar/sort_test.rb",
99
+ "test/helper.rb"
100
+ ]
28
101
 
29
- s.add_dependency(%q<ParseTree>, ["= 2.1.1"])
30
- s.add_dependency(%q<ruby2ruby>, ["= 1.1.8"])
31
- s.add_dependency(%q<rubigen>, [">= 1.1.1"])
32
- end
102
+ if s.respond_to? :specification_version then
103
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
104
+ s.specification_version = 3
33
105
 
106
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
107
+ s.add_runtime_dependency(%q<ParseTree>, ["= 2.1.1"])
108
+ s.add_runtime_dependency(%q<ruby2ruby>, ["= 1.1.8"])
109
+ s.add_runtime_dependency(%q<rubigen>, [">= 1.1.1"])
110
+ else
111
+ s.add_dependency(%q<ParseTree>, ["= 2.1.1"])
112
+ s.add_dependency(%q<ruby2ruby>, ["= 1.1.8"])
113
+ s.add_dependency(%q<rubigen>, [">= 1.1.1"])
114
+ end
115
+ else
116
+ s.add_dependency(%q<ParseTree>, ["= 2.1.1"])
117
+ s.add_dependency(%q<ruby2ruby>, ["= 1.1.8"])
118
+ s.add_dependency(%q<rubigen>, [">= 1.1.1"])
119
+ end
120
+ end
34
121
 
35
- # # Original Rakefile source (requires the Echoe gem):
36
- #
37
- # require 'rake'
38
- # require 'rake/testtask'
39
- # require 'rake/rdoctask'
40
- #
41
- # Version = '0.5.4'
42
- #
43
- # module Rake::TaskManager
44
- # def delete_task(task_class, *args, &block)
45
- # task_name, deps = resolve_args(args)
46
- # @tasks.delete(task_class.scope_name(@scope, task_name).to_s)
47
- # end
48
- # end
49
- # class Rake::Task
50
- # def self.delete_task(args, &block) Rake.application.delete_task(self, args, &block) end
51
- # end
52
- # def delete_task(args, &block) Rake::Task.delete_task(args, &block) end
53
- #
54
- # begin
55
- # require 'rubygems'
56
- # gem 'echoe', '>=2.7'
57
- # ENV['RUBY_FLAGS'] = ""
58
- # require 'echoe'
59
- #
60
- # Echoe.new('ambition', Version) do |p|
61
- # p.project = 'err'
62
- # p.summary = "Ambition builds yer API calls from plain jane Ruby."
63
- # p.description = "Ambition builds yer API calls from plain jane Ruby."
64
- # p.url = "http://errtheblog.com/"
65
- # p.author = 'Chris Wanstrath'
66
- # p.email = "chris@ozmm.org"
67
- # p.ruby_version = '>= 1.8.6'
68
- # p.ignore_pattern = /^(\.git|site|adapters).+/
69
- # p.test_pattern = 'test/*_test.rb'
70
- # p.dependencies << 'ParseTree =2.1.1'
71
- # p.dependencies << 'ruby2ruby =1.1.8'
72
- # p.dependencies << 'rubigen =1.1.1'
73
- # end
74
- #
75
- # rescue LoadError
76
- # puts "Not doing any of the Echoe gemmy stuff, because you don't have the specified gem versions"
77
- # end
78
- #
79
- # delete_task :test
80
- # delete_task :install_gem
81
- #
82
- # Rake::TestTask.new('test') do |t|
83
- # t.pattern = 'test/*_test.rb'
84
- # end
85
- #
86
- # Rake::TestTask.new('test:adapters') do |t|
87
- # t.pattern = 'adapters/*/test/*_test.rb'
88
- # end
89
- #
90
- # Dir['adapters/*'].each do |adapter|
91
- # adapter = adapter.split('/').last
92
- # Rake::TestTask.new("test:adapters:#{adapter.sub('ambitious_','')}") do |t|
93
- # t.pattern = "adapters/#{adapter}/test/*_test.rb"
94
- # end
95
- # end
96
- #
97
- # desc 'Default: run unit tests.'
98
- # task :default => :test
99
- #
100
- # desc 'Generate RDoc documentation'
101
- # Rake::RDocTask.new(:rdoc) do |rdoc|
102
- # files = ['README', 'LICENSE', 'lib/**/*.rb']
103
- # rdoc.rdoc_files.add(files)
104
- # rdoc.main = "README"
105
- # rdoc.title = "ambition"
106
- # # rdoc.template = File.exists?(t="/Users/chris/ruby/projects/err/rock/template.rb") ? t : "/var/www/rock/template.rb"
107
- # rdoc.rdoc_dir = 'doc'
108
- # rdoc.options << '--inline-source'
109
- # end
110
- #
111
- # desc 'Generate coverage reports'
112
- # task :rcov do
113
- # `rcov -e gems test/*_test.rb`
114
- # puts 'Generated coverage reports.'
115
- # end
116
- #
117
- # desc 'Install as a gem'
118
- # task :install_gem do
119
- # puts `rake manifest package && gem install pkg/ambition-#{Version}.gem`
120
- # end
data/deps.rip ADDED
@@ -0,0 +1,3 @@
1
+ git://github.com/drnic/rubigen.git REL-1.3.0
2
+ git://github.com/seattlerb/ruby2ruby.git e3cf57559 # 1.1.8
3
+ git://github.com/seattlerb/parsetree.git 480ede9d9 # 2.1.1
@@ -109,7 +109,7 @@ module Ambition #:nodoc:
109
109
  # * clauses
110
110
  # * stash
111
111
  # * negated?
112
- unless instance.respond_to? :context
112
+ unless instance.respond_to? :context=
113
113
  klass.class_eval do
114
114
  attr_accessor :context, :negated
115
115
  def owner; @context.owner end
data/site/Rakefile ADDED
@@ -0,0 +1,61 @@
1
+ require 'rubygems'
2
+ require 'redcloth'
3
+ require 'rake'
4
+ require 'rake/contrib/sshpublisher'
5
+
6
+ StaticFiles = %w( png gif jpeg jpg css js )
7
+ LiveDirectories = %w( adapters textile static )
8
+
9
+ task :default => [ :clean, :build ]
10
+
11
+ desc "Clean generated files"
12
+ task :clean do
13
+ FileUtils.rm_rf 'live'
14
+ end
15
+
16
+ def compile(file)
17
+ layout = File.read('src/layout.textile')
18
+ layout.sub('%CONTENT%', compile_without_layout(file)).gsub('%PAGE%', File.basename(file).split('.').first)
19
+ end
20
+
21
+ def compile_without_layout(file)
22
+ textile = File.read(file).
23
+ gsub(/%INCLUDE (.+)%/) { |match| File.read("src/#{$1}") }.
24
+ gsub('<ruby>', '<pre class="ruby">').gsub('</ruby>', '</pre>')
25
+ RedCloth.new(textile).to_html
26
+ end
27
+
28
+ desc "Build live HTML files"
29
+ task :build do
30
+ LiveDirectories.each { |dir| FileUtils.mkdir_p "live/#{dir}" }
31
+ Dir['src/**/*.textile'].each do |file|
32
+ next if File.basename(file) == 'layout.textile'
33
+
34
+ file_name = file.sub('src/', '').sub('.textile', '.html')
35
+ live_file = "live/#{file_name}"
36
+
37
+ unless uptodate?(live_file, file) && uptodate?(live_file, "src/layout.textile")
38
+ File.open(live_file, 'w') { |f| f.puts(compile(file)); f.flush }
39
+ puts "created #{live_file}"
40
+ cp file, 'live/textile/' + file.split('/').last.sub('.textile', '.txt')
41
+ end
42
+ end
43
+
44
+ static_files = "{#{StaticFiles.join(',')}}"
45
+ Dir["src/**/*.#{static_files}"].each do |file|
46
+ file = file.sub('src/','')
47
+ src, live = "src/#{file}", "live/#{file}"
48
+ unless uptodate? live, src
49
+ cp src, live
50
+ puts "copied #{file}"
51
+ end
52
+ end
53
+ end
54
+
55
+ desc "Publish the documentation"
56
+ task :publish => [ :build ] do
57
+ Rake::SshDirPublisher.new(
58
+ "defunkt@rubyforge.org",
59
+ "/var/www/gforge-projects/ambition/",
60
+ "live" ).upload
61
+ end
@@ -0,0 +1,23 @@
1
+ Adapters are gems named @ambitious-something@, where _something_ corresponds to the data
2
+ store they are adapting. They can be required in code via @ambition/adapters/something@.
3
+
4
+ To install and test the ActiveRecord adapter:
5
+
6
+ <pre>
7
+ $ gem install ambitious-activerecord
8
+ $ irb
9
+ >> require 'rubygems'
10
+ >> require 'ambition/adapters/active_record'
11
+ </pre>
12
+
13
+ Adapters typically inject themselves into their target automatically, so that should be
14
+ all you need.
15
+
16
+ There are a few adapters in development or released currently:
17
+
18
+ * "ActiveRecord":adapters/activerecord.html
19
+ * ActiveLDAP
20
+ * Facebook
21
+ * XPath
22
+ * CouchDB
23
+ * DataMapper
@@ -0,0 +1,163 @@
1
+ h2. The Adapters
2
+
3
+ %INCLUDE _adapters.textile%
4
+
5
+ If you're interested in writing your own adapter, read on.
6
+
7
+ h2. The Anatomy of an Adapter
8
+
9
+ Ambition adapters consist of two parts: *Translators* and the *Query*. Translators
10
+ are used to translate plane jane Ruby into strings while the Query is used to build
11
+ and execute a query from those strings.
12
+
13
+ The three translators are @Select@, @Slice@, and @Sort@. Their names correspond to the
14
+ API method they represent. Each translator consists of methods which convert passed
15
+ arguments into a string.
16
+
17
+ Here's how the ActiveRecord adapter maps translator classes to SQL clauses:
18
+
19
+ * @Select@ =&gt; @WHERE@
20
+ * @Slice@ =&gt; @LIMIT@ and @OFFSET@
21
+ * @Sort@ =&gt; @ORDER BY@
22
+
23
+ Your translators and the Query have three special methods available at all times:
24
+
25
+ * @owner@
26
+ * @clauses@
27
+ * @stash@
28
+
29
+ @owner@ is the class from which the request was generated.
30
+
31
+ <ruby>
32
+ User.select { |u| u.name == 'Pork' }
33
+ # => owner == User
34
+ </ruby>
35
+
36
+ @clauses@ is the hash of translated string arrays, keyed by processors.
37
+
38
+ <ruby>
39
+ User.select { |u| u.name == 'Pork' }
40
+ # => clauses == { :select => [ "users.name = 'Pork'" ] }
41
+ </ruby>
42
+
43
+ @stash@ is your personal private stash. A hash you can use for
44
+ keeping stuff around. Translators are free to set things which
45
+ can later be picked up by the Query class.
46
+
47
+ For instance, the @ActiveRecord@ adapter's @Select@ translator adds to the
48
+ @stash[:include]@ array whenever it thinks it needs to do a join. The
49
+ Query class picks this up and adds it to the hash it feeds
50
+ @find(:all)@.
51
+
52
+ <ruby>
53
+ User.select { |u| u.profile.name == 'Pork' }
54
+ # => stash == { :include => [ :profile ] }
55
+ </ruby>
56
+
57
+ @stash@ is basically a way for your translators to talk to each other and,
58
+ more importantly, to the Query.
59
+
60
+ The Query is what kicks off the actual data store query, after all the translators have done
61
+ their business. Its @clauses@ and @stash@ hashes are as full as they will ever be.
62
+
63
+ The kicking is done by one of two methods:
64
+
65
+ * @kick@
66
+ * @count@
67
+
68
+ While two other methods are generally expected to turn the @clauses@ hash into something
69
+ semantically valid:
70
+
71
+ * @to_s@
72
+ * @to_hash@
73
+
74
+ So, for instance, @Query#kick@ may look like this:
75
+
76
+ <ruby>
77
+ def kick
78
+ owner.find(:all, to_hash)
79
+ end
80
+ </ruby>
81
+
82
+ A straightforward translator/query API reference can be found on the "api":api.html page.
83
+
84
+ The easiest way to understand translators is to check out the source of the existing adapters
85
+ or by using the adapter generator.
86
+
87
+ h2. The Adapter Generator
88
+
89
+ Ambition ships with an @ambition_adapter@ script which can generate an adapter skeleton. Built
90
+ using Dr Nic's "Rubigen":http://rubigen.rubyforge.org/, it spits out all the files, tests, and
91
+ Rakefiles your adapter needs.
92
+
93
+ Run it:
94
+
95
+ <pre>
96
+ $ ambition_adapter flickr
97
+ create
98
+ create lib/ambition/adapters/flickr
99
+ create test
100
+ create lib/ambition/adapters/flickr/base.rb
101
+ create lib/ambition/adapters/flickr/query.rb
102
+ create lib/ambition/adapters/flickr/select.rb
103
+ create lib/ambition/adapters/flickr/slice.rb
104
+ create lib/ambition/adapters/flickr/sort.rb
105
+ create lib/ambition/adapters/flickr.rb
106
+ create test/helper.rb
107
+ create test/select_test.rb
108
+ create test/slice_test.rb
109
+ create test/sort_test.rb
110
+ create README
111
+ create Rakefile
112
+ </pre>
113
+
114
+ Presto, you've got a ready and willing adapter skeleton in place now. Check out the comments
115
+ and you're on your way.
116
+
117
+ h2. The Flow: Ambition + Adapters
118
+
119
+ Let us examine the flow of a typical call, using the @ActiveRecord@ adapter for reference.
120
+
121
+ The call:
122
+
123
+ <ruby>
124
+ User.select { |u| u.name == 'Chris' && u.age == 22 }.to_s
125
+ </ruby>
126
+
127
+ The first few steps:
128
+
129
+ * @Ambition::API#select@ is called.
130
+ * An @Ambition::Context@ is created.
131
+ * An @Ambition::Processors::Select@ is created and added to the context.
132
+ * The context calls @to_s@ on the new @Select@ processor
133
+ * The block passed to @select@ is processed.
134
+
135
+ This processing is the real meat. Ambition will instantiate your @Select@ translator and
136
+ pass values to it, saving the return value of these method calls.
137
+
138
+ * @Ambition::Adapters::ActiveRecord::Select@ is instantiated.
139
+ * The translator's @call@ method is passed @:name@, returning @"users.name"@
140
+ * The translator's @==@ method is passed @"users.name"@ and @"Chris"@, returning @"users.name = 'Chris'"@
141
+ * @call@ is passed @:age@, returning @"users.age"@
142
+ * @==@ is passed @"users.age"@ and @22@, returning @"users.age = 22"@
143
+ * The translator's @both@ method is passed @"users.name = 'Chris'"@ and @"users.age = 22"@,
144
+ returning @"(users.name = 'Chris' AND users.age = 22)"@
145
+
146
+ At this point we leave adapter-land. The final string is stored in the @clauses@ hash
147
+ (available to your @Query@) by the context. The @clauses@ hash is keyed by the translator
148
+ name -- in this case, @:select@.
149
+
150
+ * The context is returned by @Ambition::API#select@.
151
+ * @to_s@ is called on the context
152
+ * The context forwards this @to_s@ call to an instance of the adapter's @Query@ class
153
+ * The ActiveRecord adapter's @to_s@ calls @to_hash@
154
+ * @to_hash@ uses the @clauses@ hash to build an AR hash
155
+ * @to_s@ then uses the hash's members to build a SQL string
156
+
157
+ The final string is then returned:
158
+
159
+ <ruby>
160
+ "SELECT * FROM users WHERE (users.name = 'Chris' AND users.age = 22)"
161
+ </ruby>
162
+
163
+ And that's all there is to it. Except, of course, for the "api":api.html page.