ambition 0.2.0 → 0.2.1
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.
- data/Manifest +7 -7
- data/Rakefile +1 -1
- data/lib/ambition.rb +5 -17
- data/lib/ambition/api.rb +73 -0
- data/lib/ambition/proc_to_ruby.rb +0 -1
- data/lib/ambition/processor.rb +15 -7
- data/lib/ambition/{where.rb → select_processor.rb} +7 -18
- data/lib/ambition/simple_processor.rb +10 -0
- data/lib/ambition/{order.rb → sort_processor.rb} +1 -7
- data/test/benchmark.rb +62 -0
- data/test/mocks_test.rb +29 -0
- data/test/profiler.rb +34 -0
- metadata +10 -11
- data/lib/ambition/count.rb +0 -8
- data/lib/ambition/enumerable.rb +0 -26
- data/lib/ambition/limit.rb +0 -57
- data/test/constructive_test.rb +0 -16
- data/test/destructive_test.rb +0 -21
data/Manifest
CHANGED
@@ -1,21 +1,20 @@
|
|
1
1
|
./init.rb
|
2
|
-
./lib/ambition/
|
2
|
+
./lib/ambition/api.rb
|
3
3
|
./lib/ambition/database_statements.rb
|
4
|
-
./lib/ambition/enumerable.rb
|
5
|
-
./lib/ambition/limit.rb
|
6
|
-
./lib/ambition/order.rb
|
7
4
|
./lib/ambition/proc_to_ruby.rb
|
8
5
|
./lib/ambition/processor.rb
|
9
6
|
./lib/ambition/query.rb
|
10
|
-
./lib/ambition/
|
7
|
+
./lib/ambition/select_processor.rb
|
8
|
+
./lib/ambition/simple_processor.rb
|
9
|
+
./lib/ambition/sort_processor.rb
|
11
10
|
./lib/ambition.rb
|
12
11
|
./LICENSE
|
13
12
|
./Manifest
|
14
13
|
./Rakefile
|
15
14
|
./README
|
15
|
+
./test/benchmark.rb
|
16
16
|
./test/chaining_test.rb
|
17
17
|
./test/console
|
18
|
-
./test/constructive_test.rb
|
19
18
|
./test/count_test.rb
|
20
19
|
./test/databases/boot.rb
|
21
20
|
./test/databases/database.yml
|
@@ -35,11 +34,12 @@
|
|
35
34
|
./test/databases/lib/activerecord_test_connector.rb
|
36
35
|
./test/databases/lib/load_fixtures.rb
|
37
36
|
./test/databases/lib/schema.rb
|
38
|
-
./test/destructive_test.rb
|
39
37
|
./test/enumerable_test.rb
|
40
38
|
./test/helper.rb
|
41
39
|
./test/join_test.rb
|
42
40
|
./test/limit_test.rb
|
41
|
+
./test/mocks_test.rb
|
43
42
|
./test/order_test.rb
|
43
|
+
./test/profiler.rb
|
44
44
|
./test/types_test.rb
|
45
45
|
./test/where_test.rb
|
data/Rakefile
CHANGED
data/lib/ambition.rb
CHANGED
@@ -2,24 +2,12 @@ unless defined? ActiveRecord
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'active_record'
|
4
4
|
end
|
5
|
-
require 'ambition/
|
5
|
+
require 'ambition/api'
|
6
6
|
require 'ambition/processor'
|
7
|
+
require 'ambition/select_processor'
|
8
|
+
require 'ambition/sort_processor'
|
9
|
+
require 'ambition/simple_processor'
|
7
10
|
require 'ambition/query'
|
8
|
-
require 'ambition/where'
|
9
|
-
require 'ambition/order'
|
10
|
-
require 'ambition/limit'
|
11
|
-
require 'ambition/count'
|
12
|
-
require 'ambition/enumerable'
|
13
11
|
require 'ambition/database_statements'
|
14
12
|
|
15
|
-
|
16
|
-
include Where, Order, Limit, Enumerable, Count
|
17
|
-
|
18
|
-
attr_accessor :query_context
|
19
|
-
|
20
|
-
def query_context
|
21
|
-
@query_context || Query.new(self)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
ActiveRecord::Base.extend Ambition
|
13
|
+
ActiveRecord::Base.extend Ambition::API
|
data/lib/ambition/api.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
module Ambition
|
2
|
+
module API
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_accessor :query_context
|
6
|
+
def query_context
|
7
|
+
@query_context || Query.new(self)
|
8
|
+
end
|
9
|
+
|
10
|
+
def entries
|
11
|
+
find(:all, query_context.to_hash)
|
12
|
+
end
|
13
|
+
alias_method :to_a, :entries
|
14
|
+
|
15
|
+
def select(*args, &block)
|
16
|
+
query_context.add SelectProcessor.new(self, block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def first(limit = 1)
|
20
|
+
query_context.add SimpleProcessor.new(:limit => limit)
|
21
|
+
|
22
|
+
if limit == 1
|
23
|
+
find(:first, query_context.to_hash)
|
24
|
+
else
|
25
|
+
query_context
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def slice(offset, limit = nil)
|
30
|
+
if offset.is_a? Range
|
31
|
+
limit = offset.end
|
32
|
+
limit -= 1 if offset.exclude_end?
|
33
|
+
offset = offset.first
|
34
|
+
limit -= offset
|
35
|
+
elsif limit.nil?
|
36
|
+
return find(offset)
|
37
|
+
end
|
38
|
+
|
39
|
+
query_context.add SimpleProcessor.new(:offset => offset)
|
40
|
+
query_context.add SimpleProcessor.new(:limit => limit)
|
41
|
+
end
|
42
|
+
alias_method :[], :slice
|
43
|
+
|
44
|
+
def sort_by(&block)
|
45
|
+
query_context.add SortProcessor.new(self, block)
|
46
|
+
end
|
47
|
+
|
48
|
+
def detect(&block)
|
49
|
+
select(&block).first
|
50
|
+
end
|
51
|
+
|
52
|
+
def size
|
53
|
+
count(query_context.to_hash)
|
54
|
+
end
|
55
|
+
alias_method :length, :size
|
56
|
+
|
57
|
+
def each(&block)
|
58
|
+
entries.each(&block)
|
59
|
+
end
|
60
|
+
|
61
|
+
def any?(&block)
|
62
|
+
select(&block).size > 0
|
63
|
+
end
|
64
|
+
|
65
|
+
def all?(&block)
|
66
|
+
size == select(&block).size
|
67
|
+
end
|
68
|
+
|
69
|
+
def empty?
|
70
|
+
size.zero?
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/ambition/processor.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_record/connection_adapters/abstract/quoting'
|
2
|
+
require 'ambition/proc_to_ruby'
|
2
3
|
|
3
4
|
module Ambition
|
4
5
|
class Processor
|
@@ -29,7 +30,6 @@ module Ambition
|
|
29
30
|
|
30
31
|
def process_array(exp)
|
31
32
|
arrayed = exp.map { |m| process(m) }
|
32
|
-
exp.clear
|
33
33
|
return arrayed.join(', ')
|
34
34
|
end
|
35
35
|
|
@@ -52,18 +52,26 @@ module Ambition
|
|
52
52
|
when Regexp
|
53
53
|
"'#{value.source}'"
|
54
54
|
else
|
55
|
-
|
55
|
+
if active_connection?
|
56
|
+
ActiveRecord::Base.connection.quote(value)
|
57
|
+
else
|
58
|
+
quote(value)
|
59
|
+
end
|
56
60
|
end
|
57
|
-
rescue ActiveRecord::ConnectionNotEstablished
|
58
|
-
quote(value)
|
59
61
|
rescue
|
60
62
|
"'#{value}'"
|
61
63
|
end
|
62
64
|
|
63
65
|
def quote_column_name(value)
|
64
|
-
|
65
|
-
|
66
|
-
|
66
|
+
if active_connection?
|
67
|
+
ActiveRecord::Base.connection.quote_column_name(value)
|
68
|
+
else
|
69
|
+
value.to_s
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def active_connection?
|
74
|
+
ActiveRecord::Base.active_connection_name
|
67
75
|
end
|
68
76
|
|
69
77
|
def statement(*args)
|
@@ -1,15 +1,5 @@
|
|
1
1
|
module Ambition
|
2
|
-
|
3
|
-
def select(*args, &block)
|
4
|
-
query_context.add WhereProcessor.new(self, block)
|
5
|
-
end
|
6
|
-
|
7
|
-
def detect(&block)
|
8
|
-
select(&block).first
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class WhereProcessor < Processor
|
2
|
+
class SelectProcessor < Processor
|
13
3
|
def initialize(owner, block)
|
14
4
|
super()
|
15
5
|
@receiver = nil
|
@@ -31,7 +21,6 @@ module Ambition
|
|
31
21
|
|
32
22
|
def process_not(exp)
|
33
23
|
type, receiver, method, other = *exp.first
|
34
|
-
exp.clear
|
35
24
|
|
36
25
|
case type
|
37
26
|
when :call
|
@@ -39,14 +28,15 @@ module Ambition
|
|
39
28
|
when :match3
|
40
29
|
regexp = receiver.last
|
41
30
|
"#{process(method)} #{statement(:negated_regexp, regexp)} #{sanitize(regexp)}"
|
31
|
+
else
|
32
|
+
process_error(exp)
|
42
33
|
end
|
43
34
|
end
|
44
35
|
|
45
36
|
def process_call(exp)
|
46
37
|
receiver, method, other = *exp
|
47
|
-
exp.clear
|
48
38
|
|
49
|
-
|
39
|
+
translation(receiver, method, other)
|
50
40
|
end
|
51
41
|
|
52
42
|
def process_lit(exp)
|
@@ -77,9 +67,9 @@ module Ambition
|
|
77
67
|
def process_dvar(exp)
|
78
68
|
target = exp.shift
|
79
69
|
if target == @receiver
|
80
|
-
|
70
|
+
@table_name
|
81
71
|
else
|
82
|
-
|
72
|
+
value(target.to_s[0..-1])
|
83
73
|
end
|
84
74
|
end
|
85
75
|
|
@@ -100,7 +90,6 @@ module Ambition
|
|
100
90
|
end
|
101
91
|
|
102
92
|
def process_attrasgn(exp)
|
103
|
-
exp.clear
|
104
93
|
raise "Assignment not supported. Maybe you meant ==?"
|
105
94
|
end
|
106
95
|
|
@@ -111,7 +100,7 @@ module Ambition
|
|
111
100
|
while clause = exp.shift
|
112
101
|
clauses << clause
|
113
102
|
end
|
114
|
-
|
103
|
+
"(" + clauses.map { |c| process(c) }.join(" #{with} ") + ")"
|
115
104
|
end
|
116
105
|
|
117
106
|
def value(variable)
|
data/test/benchmark.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
$NO_TEST = true
|
3
|
+
%w( ambition rubygems active_record benchmark ).each { |f| require f }
|
4
|
+
|
5
|
+
class User < ActiveRecord::Base
|
6
|
+
def self.reflections
|
7
|
+
return @reflections if @reflections
|
8
|
+
@reflections = {}
|
9
|
+
@reflections[:ideas] = Reflection.new(:has_many, 'user_id', :ideas, 'ideas')
|
10
|
+
@reflections[:invites] = Reflection.new(:has_many, 'referrer_id', :invites, 'invites')
|
11
|
+
@reflections[:profile] = Reflection.new(:has_one, 'user_id', :profile, 'profiles')
|
12
|
+
@reflections[:account] = Reflection.new(:belongs_to, 'account_id', :account, 'accounts')
|
13
|
+
@reflections
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.table_name
|
17
|
+
'users'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Reflection < Struct.new(:macro, :primary_key_name, :name, :table_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
Times = 1000
|
25
|
+
|
26
|
+
Benchmark.bm(30) do |x|
|
27
|
+
x.report 'simple select' do
|
28
|
+
Times.times do
|
29
|
+
User.select { |u| u.id == 20 }.to_hash
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
x.report 'dual select' do
|
34
|
+
Times.times do
|
35
|
+
User.select { |u| u.id == 20 && u.age > 20 }.to_hash
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
x.report 'join select' do
|
40
|
+
Times.times do
|
41
|
+
User.select { |u| u.id == 20 && u.ideas.name =~ /stuff/ }.to_hash
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
x.report 'dual select w/ sort' do
|
46
|
+
Times.times do
|
47
|
+
User.select { |u| u.id == 20 && u.age > 20 }.sort_by { |u| u.id }.to_hash
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
x.report 'dual select w/ sort & first' do
|
52
|
+
Times.times do
|
53
|
+
User.select { |u| u.id == 20 && u.age > 20 }.sort_by { |u| u.id }.first(20).to_hash
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
x.report "it's complicated" do
|
58
|
+
Times.times do
|
59
|
+
User.select { |u| (u.id == 20 && u.age > 20) || u.profile.name == 'Jon' }.sort_by { |u| [u.id, -u.name] }.first(20).to_hash
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/test/mocks_test.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#require File.dirname(__FILE__) + '/helper'
|
2
|
+
#
|
3
|
+
#context "Setting the ambition_source" do
|
4
|
+
# setup do
|
5
|
+
# @users = [
|
6
|
+
# OpenStruct.new(:name => 'Chris', :age => 22),
|
7
|
+
# OpenStruct.new(:name => 'PJ', :age => 24),
|
8
|
+
# OpenStruct.new(:name => 'Kevin', :age => 23),
|
9
|
+
# OpenStruct.new(:name => '_why', :age => 65)
|
10
|
+
# ]
|
11
|
+
# User.ambition_source = @users
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# teardown do
|
15
|
+
# User.ambition_source = nil
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# xspecify "should run all selects / detects against that collection" do
|
19
|
+
# User.detect { |u| u.name == 'Chris' }.should == @users.first
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# specify "should run all sorts against that collection" do
|
23
|
+
# User.sort_by { |u| -u.age }.entries.should == @users.sort_by { |u| -u.age }
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# xspecify "should chain successfully" do
|
27
|
+
# User.select { |u| u.age > 22 }.sort_by { |u| -u.age }.entries.should == [ @users[3], @users[1], @users[2] ]
|
28
|
+
# end
|
29
|
+
#end
|
data/test/profiler.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
require 'ambition'
|
3
|
+
require 'ruby-prof'
|
4
|
+
|
5
|
+
class User < ActiveRecord::Base
|
6
|
+
def self.reflections
|
7
|
+
return @reflections if @reflections
|
8
|
+
@reflections = {}
|
9
|
+
@reflections[:ideas] = Reflection.new(:has_many, 'user_id', :ideas, 'ideas')
|
10
|
+
@reflections[:invites] = Reflection.new(:has_many, 'referrer_id', :invites, 'invites')
|
11
|
+
@reflections[:profile] = Reflection.new(:has_one, 'user_id', :profile, 'profiles')
|
12
|
+
@reflections[:account] = Reflection.new(:belongs_to, 'account_id', :account, 'accounts')
|
13
|
+
@reflections
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.table_name
|
17
|
+
'users'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Reflection < Struct.new(:macro, :primary_key_name, :name, :table_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
result = RubyProf.profile do
|
25
|
+
1000.times do
|
26
|
+
User.select { |u| (u.id == 20 && u.age > 20) || u.profile.name == 'Jon' }.sort_by { |u| [u.id, -u.name] }.first(20).to_hash
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
printer = RubyProf::FlatPrinter.new(result)
|
31
|
+
#printer = RubyProf::GraphPrinter.new(result)
|
32
|
+
printer.print(STDOUT, 0)
|
33
|
+
|
34
|
+
puts User.select { |u| (u.id == 20 && u.age > 20) || u.profile.name == 'Jon' }.sort_by { |u| [u.id, -u.name] }.first(20).to_hash.inspect
|
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.
|
7
|
-
date: 2007-09-
|
6
|
+
version: 0.2.1
|
7
|
+
date: 2007-09-10 00:00:00 -07:00
|
8
8
|
summary: Ambition builds SQL from plain jane Ruby.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -30,23 +30,22 @@ authors:
|
|
30
30
|
- Chris Wanstrath
|
31
31
|
files:
|
32
32
|
- ./init.rb
|
33
|
-
- ./lib/ambition/
|
33
|
+
- ./lib/ambition/api.rb
|
34
34
|
- ./lib/ambition/database_statements.rb
|
35
|
-
- ./lib/ambition/enumerable.rb
|
36
|
-
- ./lib/ambition/limit.rb
|
37
|
-
- ./lib/ambition/order.rb
|
38
35
|
- ./lib/ambition/proc_to_ruby.rb
|
39
36
|
- ./lib/ambition/processor.rb
|
40
37
|
- ./lib/ambition/query.rb
|
41
|
-
- ./lib/ambition/
|
38
|
+
- ./lib/ambition/select_processor.rb
|
39
|
+
- ./lib/ambition/simple_processor.rb
|
40
|
+
- ./lib/ambition/sort_processor.rb
|
42
41
|
- ./lib/ambition.rb
|
43
42
|
- ./LICENSE
|
44
43
|
- ./Manifest
|
45
44
|
- ./Rakefile
|
46
45
|
- ./README
|
46
|
+
- ./test/benchmark.rb
|
47
47
|
- ./test/chaining_test.rb
|
48
48
|
- ./test/console
|
49
|
-
- ./test/constructive_test.rb
|
50
49
|
- ./test/count_test.rb
|
51
50
|
- ./test/databases/boot.rb
|
52
51
|
- ./test/databases/database.yml
|
@@ -66,22 +65,22 @@ files:
|
|
66
65
|
- ./test/databases/lib/activerecord_test_connector.rb
|
67
66
|
- ./test/databases/lib/load_fixtures.rb
|
68
67
|
- ./test/databases/lib/schema.rb
|
69
|
-
- ./test/destructive_test.rb
|
70
68
|
- ./test/enumerable_test.rb
|
71
69
|
- ./test/helper.rb
|
72
70
|
- ./test/join_test.rb
|
73
71
|
- ./test/limit_test.rb
|
72
|
+
- ./test/mocks_test.rb
|
74
73
|
- ./test/order_test.rb
|
74
|
+
- ./test/profiler.rb
|
75
75
|
- ./test/types_test.rb
|
76
76
|
- ./test/where_test.rb
|
77
77
|
test_files:
|
78
78
|
- test/chaining_test.rb
|
79
|
-
- test/constructive_test.rb
|
80
79
|
- test/count_test.rb
|
81
|
-
- test/destructive_test.rb
|
82
80
|
- test/enumerable_test.rb
|
83
81
|
- test/join_test.rb
|
84
82
|
- test/limit_test.rb
|
83
|
+
- test/mocks_test.rb
|
85
84
|
- test/order_test.rb
|
86
85
|
- test/types_test.rb
|
87
86
|
- test/where_test.rb
|
data/lib/ambition/count.rb
DELETED
data/lib/ambition/enumerable.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
module Ambition
|
2
|
-
module Enumerable
|
3
|
-
include ::Enumerable
|
4
|
-
|
5
|
-
def each(&block)
|
6
|
-
entries.each(&block)
|
7
|
-
end
|
8
|
-
|
9
|
-
def any?(&block)
|
10
|
-
select(&block).size > 0
|
11
|
-
end
|
12
|
-
|
13
|
-
def all?(&block)
|
14
|
-
size == select(&block).size
|
15
|
-
end
|
16
|
-
|
17
|
-
def empty?
|
18
|
-
size.zero?
|
19
|
-
end
|
20
|
-
|
21
|
-
def entries
|
22
|
-
find(:all, query_context.to_hash)
|
23
|
-
end
|
24
|
-
alias_method :to_a, :entries
|
25
|
-
end
|
26
|
-
end
|
data/lib/ambition/limit.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
module Ambition
|
2
|
-
module Limit
|
3
|
-
def first(limit = 1)
|
4
|
-
query_context.add LimitProcessor.new(limit)
|
5
|
-
|
6
|
-
if limit == 1
|
7
|
-
find(:first, query_context.to_hash)
|
8
|
-
else
|
9
|
-
query_context
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def slice(offset, limit = nil)
|
14
|
-
|
15
|
-
if offset.is_a? Range
|
16
|
-
limit = offset.end
|
17
|
-
limit -= 1 if offset.exclude_end?
|
18
|
-
offset = offset.first
|
19
|
-
limit -= offset
|
20
|
-
elsif limit.nil?
|
21
|
-
return find(offset)
|
22
|
-
end
|
23
|
-
|
24
|
-
query_context.add OffsetProcessor.new(offset)
|
25
|
-
query_context.add LimitProcessor.new(limit)
|
26
|
-
end
|
27
|
-
alias_method :[], :slice
|
28
|
-
end
|
29
|
-
|
30
|
-
class LimitProcessor
|
31
|
-
def initialize(limit)
|
32
|
-
@limit = limit
|
33
|
-
end
|
34
|
-
|
35
|
-
def key
|
36
|
-
:limit
|
37
|
-
end
|
38
|
-
|
39
|
-
def to_s
|
40
|
-
@limit
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class OffsetProcessor
|
45
|
-
def initialize(offset)
|
46
|
-
@offset = offset
|
47
|
-
end
|
48
|
-
|
49
|
-
def key
|
50
|
-
:offset
|
51
|
-
end
|
52
|
-
|
53
|
-
def to_s
|
54
|
-
@offset
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/test/constructive_test.rb
DELETED
data/test/destructive_test.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/helper'
|
2
|
-
|
3
|
-
context "Destructive" do
|
4
|
-
xspecify "clear" do
|
5
|
-
end
|
6
|
-
|
7
|
-
xspecify "delete" do
|
8
|
-
end
|
9
|
-
|
10
|
-
xspecify "delete_if" do
|
11
|
-
end
|
12
|
-
|
13
|
-
xspecify "<<" do
|
14
|
-
end
|
15
|
-
|
16
|
-
xspecify "concat" do
|
17
|
-
end
|
18
|
-
|
19
|
-
xspecify "delete_at" do
|
20
|
-
end
|
21
|
-
end
|