cloudkit 0.10.1 → 0.11.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.
- data/CHANGES +11 -0
- data/README +7 -6
- data/Rakefile +13 -6
- data/TODO +7 -5
- data/cloudkit.gemspec +23 -23
- data/doc/curl.html +2 -2
- data/doc/index.html +4 -6
- data/examples/5.ru +2 -3
- data/examples/TOC +1 -3
- data/lib/cloudkit.rb +17 -10
- data/lib/cloudkit/constants.rb +0 -6
- data/lib/cloudkit/exceptions.rb +10 -0
- data/lib/cloudkit/flash_session.rb +1 -3
- data/lib/cloudkit/oauth_filter.rb +8 -16
- data/lib/cloudkit/oauth_store.rb +9 -13
- data/lib/cloudkit/openid_filter.rb +25 -7
- data/lib/cloudkit/openid_store.rb +14 -17
- data/lib/cloudkit/request.rb +6 -1
- data/lib/cloudkit/service.rb +15 -15
- data/lib/cloudkit/store.rb +97 -284
- data/lib/cloudkit/store/memory_table.rb +105 -0
- data/lib/cloudkit/store/resource.rb +256 -0
- data/lib/cloudkit/store/response_helpers.rb +0 -1
- data/lib/cloudkit/uri.rb +88 -0
- data/lib/cloudkit/user_store.rb +7 -14
- data/spec/ext_spec.rb +76 -0
- data/spec/flash_session_spec.rb +20 -0
- data/spec/memory_table_spec.rb +86 -0
- data/spec/oauth_filter_spec.rb +326 -0
- data/spec/oauth_store_spec.rb +10 -0
- data/spec/openid_filter_spec.rb +64 -0
- data/spec/openid_store_spec.rb +101 -0
- data/spec/rack_builder_spec.rb +39 -0
- data/spec/request_spec.rb +185 -0
- data/spec/resource_spec.rb +291 -0
- data/spec/service_spec.rb +974 -0
- data/{test/helper.rb → spec/spec_helper.rb} +14 -2
- data/spec/store_spec.rb +10 -0
- data/spec/uri_spec.rb +93 -0
- data/spec/user_store_spec.rb +10 -0
- data/spec/util_spec.rb +11 -0
- metadata +37 -61
- data/examples/6.ru +0 -10
- data/lib/cloudkit/store/adapter.rb +0 -8
- data/lib/cloudkit/store/extraction_view.rb +0 -57
- data/lib/cloudkit/store/sql_adapter.rb +0 -36
- data/test/ext_test.rb +0 -76
- data/test/flash_session_test.rb +0 -22
- data/test/oauth_filter_test.rb +0 -331
- data/test/oauth_store_test.rb +0 -12
- data/test/openid_filter_test.rb +0 -60
- data/test/openid_store_test.rb +0 -12
- data/test/rack_builder_test.rb +0 -41
- data/test/request_test.rb +0 -197
- data/test/service_test.rb +0 -971
- data/test/store_test.rb +0 -93
- data/test/user_store_test.rb +0 -12
- data/test/util_test.rb +0 -13
@@ -1,7 +1,5 @@
|
|
1
1
|
$:.unshift File.expand_path(File.dirname(__FILE__)) + '/../lib'
|
2
2
|
require 'cloudkit'
|
3
|
-
require 'test/unit'
|
4
|
-
require 'shoulda'
|
5
3
|
require 'rexml/document'
|
6
4
|
|
7
5
|
TEST_REMOTE_USER = '/cloudkit_users/abcdef'.freeze
|
@@ -18,3 +16,17 @@ end
|
|
18
16
|
def app_headers(content)
|
19
17
|
{'Content-Type' => 'text/html', 'Content-Length' => content.length.to_s}
|
20
18
|
end
|
19
|
+
|
20
|
+
module Rack
|
21
|
+
class Config
|
22
|
+
def initialize(app, &block)
|
23
|
+
@app = app
|
24
|
+
@block = block
|
25
|
+
end
|
26
|
+
|
27
|
+
def call(env)
|
28
|
+
@block.call(env)
|
29
|
+
@app.call(env)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/spec/store_spec.rb
ADDED
data/spec/uri_spec.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "A URI" do
|
4
|
+
|
5
|
+
it "should know its string form" do
|
6
|
+
CloudKit::URI.new('/items/123').string.should == '/items/123'
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should know its parent resource collection" do
|
10
|
+
['/items', '/items/123', '/items/123/versions', '/items/123/versions/abc'].each { |uri|
|
11
|
+
CloudKit::URI.new(uri).collection_uri_fragment.should == '/items'
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should split itself into components" do
|
16
|
+
CloudKit::URI.new('/items/123/versions/abc').components.should == ['items', '123', 'versions', 'abc']
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should know its collection type" do
|
20
|
+
['/items', '/items/123', '/items/123/versions', '/items/123/versions/abc'].each { |uri|
|
21
|
+
CloudKit::URI.new(uri).collection_type.should == :items
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should know the URI of its current version" do
|
26
|
+
['/items/123', '/items/123/versions', '/items/123/versions/abc'].each { |uri|
|
27
|
+
CloudKit::URI.new(uri).current_resource_uri.should == '/items/123'
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should know if it is a meta URI" do
|
32
|
+
['/items', '/items/123', '/items/123/versions', '/items/123/versions/abc'].each { |uri|
|
33
|
+
CloudKit::URI.new(uri).should_not be_meta_uri
|
34
|
+
}
|
35
|
+
CloudKit::URI.new('/cloudkit-meta').should be_meta_uri
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should know if it is a resource collection URI" do
|
39
|
+
['/items/123', '/items/123/versions', '/items/123/versions/abc'].each { |uri|
|
40
|
+
CloudKit::URI.new(uri).should_not be_resource_collection_uri
|
41
|
+
}
|
42
|
+
CloudKit::URI.new('/items').should be_resource_collection_uri
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should know if it is a resolved resource collection URI" do
|
46
|
+
['/items', '/items/123', '/items/123/versions', '/items/123/versions/_resolved', '/items/123/versions/abc'].each { |uri|
|
47
|
+
CloudKit::URI.new(uri).should_not be_resolved_resource_collection_uri
|
48
|
+
}
|
49
|
+
CloudKit::URI.new('/items/_resolved').should be_resolved_resource_collection_uri
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should know if it is a resource URI" do
|
53
|
+
['/items', '/items/_resolved', '/items/123/versions', '/items/123/versions/_resolved', '/items/123/versions/abc'].each { |uri|
|
54
|
+
CloudKit::URI.new(uri).should_not be_resource_uri
|
55
|
+
}
|
56
|
+
CloudKit::URI.new('/items/123').should be_resource_uri
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should know if it is a version collection URI" do
|
60
|
+
['/items', '/items/_resolved', '/items/123', '/items/123/versions/_resolved', '/items/123/versions/abc'].each { |uri|
|
61
|
+
CloudKit::URI.new(uri).should_not be_version_collection_uri
|
62
|
+
}
|
63
|
+
CloudKit::URI.new('/items/123/versions').should be_version_collection_uri
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should know if it is a resolved version collection URI" do
|
67
|
+
['/items', '/items/_resolved', '/items/123', '/items/123/versions', '/items/123/versions/abc'].each { |uri|
|
68
|
+
CloudKit::URI.new(uri).should_not be_resolved_version_collection_uri
|
69
|
+
}
|
70
|
+
CloudKit::URI.new('/items/123/versions/_resolved').should be_resolved_version_collection_uri
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should know if it is a resource version URI" do
|
74
|
+
['/items', '/items/_resolved', '/items/123', '/items/123/versions', '/items/123/versions/_resolved'].each { |uri|
|
75
|
+
CloudKit::URI.new(uri).should_not be_resource_version_uri
|
76
|
+
}
|
77
|
+
CloudKit::URI.new('/items/123/versions/abc').should be_resource_version_uri
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should know its cannonical URI string" do
|
81
|
+
CloudKit::URI.new('/items/123').cannonical_uri_string.should == '/items/123'
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should generate its cannonical URI string when needed" do
|
85
|
+
CloudKit::URI.new('/items').cannonical_uri_string.should match(/\/items\/.+/)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should fail when attempting to generate a cannonical URI string for versioned resources" do
|
89
|
+
lambda {
|
90
|
+
CloudKit::URI.new('/items/123/versions/abc').cannonical_uri_string
|
91
|
+
}.should raise_error(CloudKit::InvalidURIFormat)
|
92
|
+
end
|
93
|
+
end
|
data/spec/util_spec.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Crosby
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-03-09 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -22,16 +22,6 @@ dependencies:
|
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: "0.9"
|
24
24
|
version:
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: rack-config
|
27
|
-
type: :runtime
|
28
|
-
version_requirement:
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: "0.9"
|
34
|
-
version:
|
35
25
|
- !ruby/object:Gem::Dependency
|
36
26
|
name: uuid
|
37
27
|
type: :runtime
|
@@ -42,16 +32,6 @@ dependencies:
|
|
42
32
|
- !ruby/object:Gem::Version
|
43
33
|
version: 2.0.1
|
44
34
|
version:
|
45
|
-
- !ruby/object:Gem::Dependency
|
46
|
-
name: sequel
|
47
|
-
type: :runtime
|
48
|
-
version_requirement:
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - ~>
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: "2.9"
|
54
|
-
version:
|
55
35
|
- !ruby/object:Gem::Dependency
|
56
36
|
name: oauth
|
57
37
|
type: :runtime
|
@@ -82,16 +62,6 @@ dependencies:
|
|
82
62
|
- !ruby/object:Gem::Version
|
83
63
|
version: 1.1.3
|
84
64
|
version:
|
85
|
-
- !ruby/object:Gem::Dependency
|
86
|
-
name: sqlite3-ruby
|
87
|
-
type: :runtime
|
88
|
-
version_requirement:
|
89
|
-
version_requirements: !ruby/object:Gem::Requirement
|
90
|
-
requirements:
|
91
|
-
- - "="
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: 1.2.4
|
94
|
-
version:
|
95
65
|
description: An Open Web JSON Appliance.
|
96
66
|
email: jon@joncrosby.me
|
97
67
|
executables: []
|
@@ -120,10 +90,10 @@ files:
|
|
120
90
|
- examples/3.ru
|
121
91
|
- examples/4.ru
|
122
92
|
- examples/5.ru
|
123
|
-
- examples/6.ru
|
124
93
|
- examples/TOC
|
125
94
|
- lib/cloudkit.rb
|
126
95
|
- lib/cloudkit/constants.rb
|
96
|
+
- lib/cloudkit/exceptions.rb
|
127
97
|
- lib/cloudkit/flash_session.rb
|
128
98
|
- lib/cloudkit/oauth_filter.rb
|
129
99
|
- lib/cloudkit/oauth_store.rb
|
@@ -134,32 +104,35 @@ files:
|
|
134
104
|
- lib/cloudkit/request.rb
|
135
105
|
- lib/cloudkit/service.rb
|
136
106
|
- lib/cloudkit/store.rb
|
137
|
-
- lib/cloudkit/store/
|
138
|
-
- lib/cloudkit/store/
|
107
|
+
- lib/cloudkit/store/memory_table.rb
|
108
|
+
- lib/cloudkit/store/resource.rb
|
139
109
|
- lib/cloudkit/store/response.rb
|
140
110
|
- lib/cloudkit/store/response_helpers.rb
|
141
|
-
- lib/cloudkit/store/sql_adapter.rb
|
142
111
|
- lib/cloudkit/templates/authorize_request_token.erb
|
143
112
|
- lib/cloudkit/templates/oauth_descriptor.erb
|
144
113
|
- lib/cloudkit/templates/oauth_meta.erb
|
145
114
|
- lib/cloudkit/templates/openid_login.erb
|
146
115
|
- lib/cloudkit/templates/request_authorization.erb
|
147
116
|
- lib/cloudkit/templates/request_token_denied.erb
|
117
|
+
- lib/cloudkit/uri.rb
|
148
118
|
- lib/cloudkit/user_store.rb
|
149
119
|
- lib/cloudkit/util.rb
|
150
|
-
-
|
151
|
-
-
|
152
|
-
-
|
153
|
-
-
|
154
|
-
-
|
155
|
-
-
|
156
|
-
-
|
157
|
-
-
|
158
|
-
-
|
159
|
-
-
|
160
|
-
-
|
161
|
-
-
|
162
|
-
-
|
120
|
+
- spec/ext_spec.rb
|
121
|
+
- spec/flash_session_spec.rb
|
122
|
+
- spec/memory_table_spec.rb
|
123
|
+
- spec/oauth_filter_spec.rb
|
124
|
+
- spec/oauth_store_spec.rb
|
125
|
+
- spec/openid_filter_spec.rb
|
126
|
+
- spec/openid_store_spec.rb
|
127
|
+
- spec/rack_builder_spec.rb
|
128
|
+
- spec/request_spec.rb
|
129
|
+
- spec/resource_spec.rb
|
130
|
+
- spec/service_spec.rb
|
131
|
+
- spec/spec_helper.rb
|
132
|
+
- spec/store_spec.rb
|
133
|
+
- spec/uri_spec.rb
|
134
|
+
- spec/user_store_spec.rb
|
135
|
+
- spec/util_spec.rb
|
163
136
|
has_rdoc: false
|
164
137
|
homepage: http://getcloudkit.com
|
165
138
|
post_install_message:
|
@@ -187,15 +160,18 @@ signing_key:
|
|
187
160
|
specification_version: 2
|
188
161
|
summary: An Open Web JSON Appliance.
|
189
162
|
test_files:
|
190
|
-
-
|
191
|
-
-
|
192
|
-
-
|
193
|
-
-
|
194
|
-
-
|
195
|
-
-
|
196
|
-
-
|
197
|
-
-
|
198
|
-
-
|
199
|
-
-
|
200
|
-
-
|
201
|
-
-
|
163
|
+
- spec/ext_spec.rb
|
164
|
+
- spec/flash_session_spec.rb
|
165
|
+
- spec/memory_table_spec.rb
|
166
|
+
- spec/oauth_filter_spec.rb
|
167
|
+
- spec/oauth_store_spec.rb
|
168
|
+
- spec/openid_filter_spec.rb
|
169
|
+
- spec/openid_store_spec.rb
|
170
|
+
- spec/rack_builder_spec.rb
|
171
|
+
- spec/request_spec.rb
|
172
|
+
- spec/resource_spec.rb
|
173
|
+
- spec/service_spec.rb
|
174
|
+
- spec/store_spec.rb
|
175
|
+
- spec/uri_spec.rb
|
176
|
+
- spec/user_store_spec.rb
|
177
|
+
- spec/util_spec.rb
|
data/examples/6.ru
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
$:.unshift File.expand_path(File.dirname(__FILE__)) + '/../lib'
|
2
|
-
require 'cloudkit'
|
3
|
-
use Rack::Config do |env|
|
4
|
-
env[CLOUDKIT_STORAGE_URI] = 'mysql://user:pass@localhost/cloudkit_example'
|
5
|
-
end
|
6
|
-
use Rack::Session::Pool
|
7
|
-
use CloudKit::OAuthFilter
|
8
|
-
use CloudKit::OpenIDFilter
|
9
|
-
use CloudKit::Service, :collections => [:notes]
|
10
|
-
run lambda{|env| [200, {'Content-Type' => 'text/html', 'Content-Length' => '5'}, ['HELLO']]}
|
@@ -1,57 +0,0 @@
|
|
1
|
-
module CloudKit
|
2
|
-
|
3
|
-
# An ExtractionView observes a resource collection and extracts specified
|
4
|
-
# elements for querying.
|
5
|
-
class ExtractionView
|
6
|
-
attr_accessor :name, :observe, :extract
|
7
|
-
|
8
|
-
# Initialize an ExtractionView.
|
9
|
-
#
|
10
|
-
# ==Examples
|
11
|
-
#
|
12
|
-
# Observe a "notes" collection and extract the titles and colors.
|
13
|
-
# view = ExtractionView.new(
|
14
|
-
# :name => :note_features,
|
15
|
-
# :observe => :notes,
|
16
|
-
# :extract => [:title, :color])
|
17
|
-
#
|
18
|
-
def initialize(name, options)
|
19
|
-
@name = name
|
20
|
-
@observe = options[:observe]
|
21
|
-
@extract = options[:extract]
|
22
|
-
end
|
23
|
-
|
24
|
-
# Map the provided data into a collection for querying.
|
25
|
-
def map(db, collection, uri, data)
|
26
|
-
if @observe == collection
|
27
|
-
elements = @extract.inject({}) do |e, field|
|
28
|
-
e.merge(field.to_s => data[field.to_s])
|
29
|
-
end
|
30
|
-
elements.merge!('uri' => uri)
|
31
|
-
db.transaction do
|
32
|
-
db[@name].filter(:uri => uri).delete
|
33
|
-
db[@name].insert(elements)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Remove the data with the specified URI from the view
|
39
|
-
def unmap(db, type, uri)
|
40
|
-
if @observe == type
|
41
|
-
db[@name].filter(:uri => uri).delete
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Initialize the storage for this view
|
46
|
-
def initialize_storage(db)
|
47
|
-
extractions = @extract
|
48
|
-
db.create_table @name do
|
49
|
-
extractions.each do |field|
|
50
|
-
text field
|
51
|
-
end
|
52
|
-
primary_key :id
|
53
|
-
varchar :uri
|
54
|
-
end unless db.table_exists?(@name)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module CloudKit
|
2
|
-
|
3
|
-
# Adapts a CloudKit::Store to a SQL backend.
|
4
|
-
class SQLAdapter < Adapter
|
5
|
-
|
6
|
-
# Initialize a new SQL backend. Defaults to in-memory SQLite.
|
7
|
-
def initialize(uri=nil, options={})
|
8
|
-
@db = uri ? Sequel.connect(uri, options) : Sequel.sqlite
|
9
|
-
# TODO accept views as part of a store, then initialize them here
|
10
|
-
initialize_storage
|
11
|
-
end
|
12
|
-
|
13
|
-
# method_missing is a placeholder for future interface extraction into
|
14
|
-
# CloudKit::Adapter.
|
15
|
-
def method_missing(method, *args, &block)
|
16
|
-
@db.send(method, *args, &block)
|
17
|
-
end
|
18
|
-
|
19
|
-
protected
|
20
|
-
|
21
|
-
# Initialize the HTTP-oriented storage if it does not exist.
|
22
|
-
def initialize_storage
|
23
|
-
@db.create_table CLOUDKIT_STORE do
|
24
|
-
primary_key :id
|
25
|
-
varchar :uri, :unique => true
|
26
|
-
varchar :etag
|
27
|
-
varchar :collection_reference
|
28
|
-
varchar :resource_reference
|
29
|
-
varchar :last_modified
|
30
|
-
varchar :remote_user
|
31
|
-
text :content
|
32
|
-
boolean :deleted, :default => false
|
33
|
-
end unless @db.table_exists?(CLOUDKIT_STORE)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/test/ext_test.rb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
class ExtTest < Test::Unit::TestCase
|
3
|
-
|
4
|
-
context "A Hash" do
|
5
|
-
|
6
|
-
should "re-key an entry if it exists" do
|
7
|
-
x = {:a => 1, :b => 2}
|
8
|
-
x.rekey!(:b, :c)
|
9
|
-
assert x == {:a => 1, :c => 2}
|
10
|
-
x.rekey!(:d, :b)
|
11
|
-
assert x == {:a => 1, :c => 2}
|
12
|
-
end
|
13
|
-
|
14
|
-
should "re-key false and nil values" do
|
15
|
-
x = {:a => false, :b => nil}
|
16
|
-
x.rekey!(:b, :c)
|
17
|
-
assert x == {:a => false, :c => nil}
|
18
|
-
x.rekey!(:d, :b)
|
19
|
-
assert x == {:a => false, :c => nil}
|
20
|
-
end
|
21
|
-
|
22
|
-
should "merge conditionally" do
|
23
|
-
x = {:a => 1}
|
24
|
-
y = {:b => 2}
|
25
|
-
x.filter_merge!(:c => y[:c])
|
26
|
-
assert x == {:a => 1}
|
27
|
-
x.filter_merge!(:c => y[:b])
|
28
|
-
assert x == {:a => 1, :c => 2}
|
29
|
-
x = {}.filter_merge!(:a => 1)
|
30
|
-
assert x == {:a => 1}
|
31
|
-
end
|
32
|
-
|
33
|
-
should "merge false values correctly" do
|
34
|
-
x = {:a => 1}
|
35
|
-
y = {:b => 2}
|
36
|
-
x.filter_merge!(:c => false)
|
37
|
-
assert x == {:a => 1, :c => false}
|
38
|
-
x.filter_merge!(:c => y[:b])
|
39
|
-
assert x == {:a => 1, :c => 2}
|
40
|
-
x = {}.filter_merge!(:a => false)
|
41
|
-
assert x == {:a => false}
|
42
|
-
end
|
43
|
-
|
44
|
-
should "exclude pairs using a single key" do
|
45
|
-
x = {:a => 1, :b => 2}
|
46
|
-
y = x.excluding(:b)
|
47
|
-
assert y == {:a => 1}
|
48
|
-
end
|
49
|
-
|
50
|
-
should "exclude pairs using a list of keys" do
|
51
|
-
x = {:a => 1, :b => 2, :c => 3}
|
52
|
-
y = x.excluding(:b, :c)
|
53
|
-
assert y == {:a => 1}
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
context "An Array" do
|
58
|
-
|
59
|
-
should "exclude elements" do
|
60
|
-
x = [0, 1, 2, 3]
|
61
|
-
y = x.excluding(1, 3)
|
62
|
-
assert_equal [0, 2], y
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
context "An Object" do
|
67
|
-
|
68
|
-
should "try" do
|
69
|
-
x = {:a => 'a'}
|
70
|
-
result = x[:a].try(:upcase)
|
71
|
-
assert_equal 'A', result
|
72
|
-
assert_nothing_raised {x[:b].try(:upcase)}
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|