ambition 0.2.2 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest CHANGED
@@ -4,6 +4,7 @@
4
4
  ./lib/ambition/proc_to_ruby.rb
5
5
  ./lib/ambition/processor.rb
6
6
  ./lib/ambition/query.rb
7
+ ./lib/ambition/ruby_processor.rb
7
8
  ./lib/ambition/select_processor.rb
8
9
  ./lib/ambition/simple_processor.rb
9
10
  ./lib/ambition/sort_processor.rb
@@ -42,5 +43,6 @@
42
43
  ./test/order_test.rb
43
44
  ./test/profiler.rb
44
45
  ./test/source_test.rb
46
+ ./test/ruby_test.rb
45
47
  ./test/types_test.rb
46
48
  ./test/where_test.rb
data/README CHANGED
@@ -59,21 +59,13 @@ See, +to_hash+:
59
59
  >> User.select { |m| m.name == 'jon' }.to_hash
60
60
  => {:conditions=>"users.name = 'jon'"}
61
61
 
62
- == Limitations
63
-
64
- You can use variables, but any more complex Ruby (right now) won't work
65
- inside your blocks. Just do it outside the block and assign it to a variable.
66
-
67
- Instead of:
68
- User.select { |m| m.date == 2.days.ago }
69
-
70
- Just do:
71
- date = 2.days.ago
72
- User.select { |m| m.date == date }
62
+ == Equality -- select { |u| u.field == 'bob' }
73
63
 
74
- Instance variables and globals work, too. Same with method calls.
64
+ User.select { |m| m.name == 'jon' }
65
+ "SELECT * FROM users WHERE users.name = 'jon'"
75
66
 
76
- == Equality -- select { |u| u.field == 'bob' }
67
+ User.select { |m| m.created_at > 2.days.ago }
68
+ "SELECT * FROM users WHERE users.created_at > '2007-09-26 20:37:47'"
77
69
 
78
70
  User.select { |m| m.name == 'jon' }
79
71
  "SELECT * FROM users WHERE users.name = 'jon'"
@@ -208,4 +200,8 @@ Found a bug? Sweet. Add it at the Lighthouse:
208
200
 
209
201
  Feature requests are welcome.
210
202
 
203
+ And hey, join our mailing list!
204
+
205
+ http://groups.google.com/group/ambition-rb
206
+
211
207
  * Chris Wanstrath [ chris@ozmm.org ]
data/Rakefile CHANGED
@@ -2,19 +2,18 @@ require 'rake'
2
2
  require 'rake/testtask'
3
3
  require 'rake/rdoctask'
4
4
 
5
- Version = '0.2.2'
5
+ Version = '0.3.1'
6
6
 
7
7
  module Rake::TaskManager
8
- def redefine_task(task_class, args, &block)
8
+ def delete_task(task_class, args, &block)
9
9
  task_name, deps = resolve_args(args)
10
10
  @tasks.delete(task_class.scope_name(@scope, task_name).to_s)
11
- define_task(task_class, args, &block)
12
11
  end
13
12
  end
14
13
  class Rake::Task
15
- def self.redefine_task(args, &block) Rake.application.redefine_task(self, args, &block) end
14
+ def self.delete_task(args, &block) Rake.application.delete_task(self, args, &block) end
16
15
  end
17
- def redefine_task(args, &block) Rake::Task.redefine_task(args, &block) end
16
+ def delete_task(args, &block) Rake::Task.delete_task(args, &block) end
18
17
 
19
18
  begin
20
19
  require 'rubygems'
@@ -30,6 +29,7 @@ begin
30
29
  p.author = 'Chris Wanstrath'
31
30
  p.email = "chris@ozmm.org"
32
31
  p.extra_deps << ['ParseTree', '=2.0.1']
32
+ p.extra_deps << ['ruby2ruby', '=1.1.7']
33
33
  p.extra_deps << ['activerecord', '>=1.15.0']
34
34
  p.test_globs = 'test/*_test.rb'
35
35
  end
@@ -37,7 +37,7 @@ begin
37
37
  rescue LoadError
38
38
  end
39
39
 
40
- redefine_task(:test) { }
40
+ delete_task :test
41
41
 
42
42
  Rake::TestTask.new('test') do |t|
43
43
  t.pattern = 'test/*_test.rb'
@@ -5,6 +5,7 @@ end
5
5
  require 'ambition/api'
6
6
  require 'ambition/source'
7
7
  require 'ambition/processor'
8
+ require 'ambition/ruby_processor'
8
9
  require 'ambition/select_processor'
9
10
  require 'ambition/sort_processor'
10
11
  require 'ambition/simple_processor'
@@ -1,6 +1,7 @@
1
1
  ##
2
2
  # Taken from ruby2ruby, Copyright (c) 2006 Ryan Davis under the MIT License
3
3
  require 'parse_tree'
4
+ require 'ruby2ruby'
4
5
 
5
6
  class ProcHolder
6
7
  end
@@ -14,23 +14,31 @@ module Ambition
14
14
 
15
15
  ##
16
16
  # Processing methods
17
- def process_error(exp)
18
- raise "Missing process method for sexp: #{exp.inspect}"
19
- end
20
-
21
17
  def process_proc(exp)
22
18
  receiver, body = process(exp.shift), exp.shift
23
- return process(body)
19
+ process(body)
24
20
  end
25
21
 
26
22
  def process_dasgn_curr(exp)
27
- @receiver = exp.shift
28
- return @receiver.to_s
23
+ @receiver = exp.first
24
+ @receiver.to_s
29
25
  end
26
+ alias_method :process_dasgn, :process_dasgn_curr
30
27
 
31
28
  def process_array(exp)
32
- arrayed = exp.map { |m| process(m) }
33
- return arrayed.join(', ')
29
+ # Branch on whether this is straight Ruby or a real array
30
+ if ruby = rubify(exp)
31
+ value ruby
32
+ else
33
+ arrayed = exp.map { |m| process(m) }
34
+ arrayed.join(', ')
35
+ end
36
+ end
37
+
38
+ def rubify(exp)
39
+ if exp.first.first == :call && exp.first[1].last != @receiver && Array(exp.first[1][1]).last != @receiver
40
+ RubyProcessor.process(exp.first)
41
+ end
34
42
  end
35
43
 
36
44
  ##
@@ -39,6 +47,10 @@ module Ambition
39
47
  process(@block.to_sexp).squeeze(' ')
40
48
  end
41
49
 
50
+ def value(variable)
51
+ sanitize eval(variable, @block)
52
+ end
53
+
42
54
  def sanitize(value)
43
55
  if value.is_a? Array
44
56
  return value.map { |v| sanitize(v) }.join(', ')
@@ -98,7 +110,14 @@ module Ambition
98
110
 
99
111
  def process(node)
100
112
  node ||= []
101
- respond_to?(method = "process_#{node.shift}") ? send(method, node) : ''
113
+
114
+ if respond_to?(method = "process_#{node.first}")
115
+ send(method, node[1..-1])
116
+ elsif node.blank?
117
+ ''
118
+ else
119
+ raise "Missing process method for sexp: #{node.inspect}"
120
+ end
102
121
  end
103
122
  end
104
123
  end
@@ -58,12 +58,13 @@ module Ambition
58
58
  def to_s
59
59
  hash = keyed_clauses
60
60
 
61
+ raise "Sorry, I can't construct SQL with complex joins (yet)" unless hash[:includes].blank?
62
+
61
63
  sql = []
62
- sql << "JOIN #{hash[:includes].join(', ')}" unless hash[:includes].blank?
63
64
  sql << "WHERE #{hash[:conditions].join(' AND ')}" unless hash[:conditions].blank?
64
65
  sql << "ORDER BY #{hash[:order].join(', ')}" unless hash[:order].blank?
65
66
  sql << "LIMIT #{hash[:limit]}" unless hash[:limit].blank?
66
- sql << "OFFSET #{hash[:limit]}" unless hash[:offset].blank?
67
+ sql << "OFFSET #{hash[:offset]}" unless hash[:offset].blank?
67
68
 
68
69
  @@select % [ @table_name, sql.join(' ') ]
69
70
  end
@@ -0,0 +1,22 @@
1
+ module Ambition
2
+ class RubyProcessor < RubyToRuby
3
+ def self.process(node)
4
+ @processor ||= new
5
+ @processor.process node
6
+ end
7
+
8
+ ##
9
+ # This is not DRY, and I don't care.
10
+ def process(node)
11
+ node ||= []
12
+
13
+ if respond_to?(method = "process_#{node.first}")
14
+ send(method, node[1..-1])
15
+ elsif node.blank?
16
+ ''
17
+ else
18
+ raise "Missing process method for sexp: #{node.inspect}"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -103,10 +103,6 @@ module Ambition
103
103
  "(" + clauses.map { |c| process(c) }.join(" #{with} ") + ")"
104
104
  end
105
105
 
106
- def value(variable)
107
- sanitize eval(variable, @block)
108
- end
109
-
110
106
  def negate(method, target = nil)
111
107
  if Array(target).last == [:nil]
112
108
  return 'IS NOT'
@@ -30,6 +30,12 @@ Benchmark.bm(30) do |x|
30
30
  end
31
31
  end
32
32
 
33
+ x.report 'simple select w/ eval' do
34
+ Times.times do
35
+ User.select { |u| u.created_at == Time.now }.to_hash
36
+ end
37
+ end
38
+
33
39
  x.report 'dual select' do
34
40
  Times.times do
35
41
  User.select { |u| u.id == 20 && u.age > 20 }.to_hash
@@ -25,6 +25,19 @@ context "Joins" do
25
25
  }
26
26
  end
27
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
+
28
41
  specify "non-existant associations" do
29
42
  sql = User.select { |m| m.liquor.brand == 'Jack' }
30
43
  should.raise { sql.to_hash }
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "Inline Ruby" do
4
+ xspecify "should know what to return" do
5
+ name = 'David'
6
+ sql = User.select { |u| name.nil? || u.name == name }.to_s
7
+ sql.should == "SELECT * FROM users WHERE (users.name = 'David')"
8
+ end
9
+ end
@@ -52,9 +52,8 @@ context "Different types" do
52
52
  sql.should == "SELECT * FROM users WHERE users.name IS NOT NULL"
53
53
  end
54
54
 
55
- xspecify "Time" do
56
- # TODO: nothing but variables inside blocks for now
55
+ specify "Time" do
57
56
  sql = User.select { |m| m.name == Time.now }.to_sql
58
- sql.should == "SELECT * FROM users WHERE users.name = NULL"
57
+ sql.should == "SELECT * FROM users WHERE users.name = '#{Time.now.to_s(:db)}'"
59
58
  end
60
59
  end
@@ -74,7 +74,7 @@ context "Where (using select)" do
74
74
  sql.should == "SELECT * FROM users WHERE users.name = '#{@me}'"
75
75
  end
76
76
 
77
- xspecify "simple == with instance variable method call" do
77
+ specify "simple == with instance variable method call" do
78
78
  require 'ostruct'
79
79
  @person = OpenStruct.new(:name => 'chris')
80
80
 
@@ -136,11 +136,15 @@ context "Where (using select)" do
136
136
  specify "undefined equality symbol" do
137
137
  should.raise { User.select { |m| m.name =* /chris/ }.to_sql }
138
138
  end
139
+
140
+ specify "block variable / assigning variable conflict" do
141
+ m = User.select { |m| m.name == 'chris' }.to_sql
142
+ m.should == "SELECT * FROM users WHERE users.name = 'chris'"
143
+ end
139
144
 
140
- xspecify "simple == with inline ruby" do
141
- # TODO: implement this
145
+ specify "simple == with inline ruby" do
142
146
  sql = User.select { |m| m.created_at == 2.days.ago.to_s(:db) }.to_sql
143
- sql.should == "SELECT * FROM users WHERE users.created_at = #{2.days.ago.to_s(:db)}"
147
+ sql.should == "SELECT * FROM users WHERE users.created_at = '#{2.days.ago.to_s(:db)}'"
144
148
  end
145
149
 
146
150
  specify "inspect" do
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: ambition
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.2.2
7
- date: 2007-09-11 00:00:00 -07:00
6
+ version: 0.3.1
7
+ date: 2007-11-06 00:00:00 -08:00
8
8
  summary: Ambition builds SQL from plain jane Ruby.
9
9
  require_paths:
10
10
  - lib
@@ -35,6 +35,7 @@ files:
35
35
  - ./lib/ambition/proc_to_ruby.rb
36
36
  - ./lib/ambition/processor.rb
37
37
  - ./lib/ambition/query.rb
38
+ - ./lib/ambition/ruby_processor.rb
38
39
  - ./lib/ambition/select_processor.rb
39
40
  - ./lib/ambition/simple_processor.rb
40
41
  - ./lib/ambition/sort_processor.rb
@@ -73,6 +74,7 @@ files:
73
74
  - ./test/order_test.rb
74
75
  - ./test/profiler.rb
75
76
  - ./test/source_test.rb
77
+ - ./test/ruby_test.rb
76
78
  - ./test/types_test.rb
77
79
  - ./test/where_test.rb
78
80
  test_files:
@@ -82,6 +84,7 @@ test_files:
82
84
  - test/join_test.rb
83
85
  - test/limit_test.rb
84
86
  - test/order_test.rb
87
+ - test/ruby_test.rb
85
88
  - test/source_test.rb
86
89
  - test/types_test.rb
87
90
  - test/where_test.rb
@@ -105,6 +108,15 @@ dependencies:
105
108
  - !ruby/object:Gem::Version
106
109
  version: 2.0.1
107
110
  version:
111
+ - !ruby/object:Gem::Dependency
112
+ name: ruby2ruby
113
+ version_requirement:
114
+ version_requirements: !ruby/object:Gem::Version::Requirement
115
+ requirements:
116
+ - - "="
117
+ - !ruby/object:Gem::Version
118
+ version: 1.1.7
119
+ version:
108
120
  - !ruby/object:Gem::Dependency
109
121
  name: activerecord
110
122
  version_requirement: