fogli 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +14 -0
- data/LICENSE +21 -0
- data/README.md +168 -0
- data/Rakefile +37 -0
- data/VERSION +1 -0
- data/examples/README.md +6 -0
- data/examples/me/README.md +18 -0
- data/examples/me/me.rb +30 -0
- data/lib/fogli.rb +46 -0
- data/lib/fogli/album.rb +8 -0
- data/lib/fogli/categorized_object.rb +9 -0
- data/lib/fogli/comment.rb +5 -0
- data/lib/fogli/event.rb +9 -0
- data/lib/fogli/exception.rb +15 -0
- data/lib/fogli/facebook_graph.rb +125 -0
- data/lib/fogli/facebook_object.rb +225 -0
- data/lib/fogli/facebook_object/connection_proxy.rb +80 -0
- data/lib/fogli/facebook_object/connection_scope.rb +123 -0
- data/lib/fogli/facebook_object/connections.rb +56 -0
- data/lib/fogli/facebook_object/properties.rb +81 -0
- data/lib/fogli/facebook_object/scope_methods.rb +49 -0
- data/lib/fogli/group.rb +8 -0
- data/lib/fogli/link.rb +8 -0
- data/lib/fogli/named_object.rb +8 -0
- data/lib/fogli/note.rb +7 -0
- data/lib/fogli/oauth.rb +167 -0
- data/lib/fogli/page.rb +15 -0
- data/lib/fogli/photo.rb +8 -0
- data/lib/fogli/post.rb +18 -0
- data/lib/fogli/status.rb +7 -0
- data/lib/fogli/user.rb +36 -0
- data/lib/fogli/util/module_attributes.rb +61 -0
- data/lib/fogli/util/options.rb +32 -0
- data/lib/fogli/video.rb +7 -0
- data/test/fogli/facebook_graph_test.rb +124 -0
- data/test/fogli/facebook_object/connection_proxy_test.rb +42 -0
- data/test/fogli/facebook_object/connection_scope_test.rb +91 -0
- data/test/fogli/facebook_object/connections_test.rb +50 -0
- data/test/fogli/facebook_object/properties_test.rb +79 -0
- data/test/fogli/facebook_object/scope_methods_test.rb +69 -0
- data/test/fogli/facebook_object_test.rb +178 -0
- data/test/fogli/oauth_test.rb +56 -0
- data/test/fogli/post_test.rb +18 -0
- data/test/fogli/user_test.rb +25 -0
- data/test/fogli/util/options_test.rb +38 -0
- data/test/fogli_test.rb +16 -0
- data/test/test_helper.rb +14 -0
- metadata +150 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
module Fogli
|
2
|
+
module Util
|
3
|
+
module Options
|
4
|
+
# Verifies that an options hash has all the required keys and
|
5
|
+
# also merges it with a defaults hash if given. This is an
|
6
|
+
# internal helper method.
|
7
|
+
#
|
8
|
+
# @param [Hash] options
|
9
|
+
# @param [Array] required Array of required keys.
|
10
|
+
# @param [Hash] defaults
|
11
|
+
# @return [Hash]
|
12
|
+
def verify_options(data, options=nil)
|
13
|
+
data ||= {}
|
14
|
+
options ||= {}
|
15
|
+
options[:valid_keys] ||= options[:default].keys if options[:default]
|
16
|
+
|
17
|
+
# Merge in the default data and remove any invalid keys if
|
18
|
+
# valid keys are specified.
|
19
|
+
ops = options[:default] || {}
|
20
|
+
ops.merge!(data)
|
21
|
+
ops.reject! { |k,v| !options[:valid_keys].include?(k) } if options[:valid_keys]
|
22
|
+
|
23
|
+
if options[:required_keys]
|
24
|
+
required = ops.reject { |k,v| !options[:required_keys].include?(k) || v.nil? }
|
25
|
+
raise ArgumentError.new("Missing required options: #{options[:required_keys].inspect}") if required.length != options[:required_keys].length
|
26
|
+
end
|
27
|
+
|
28
|
+
ops
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/fogli/video.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class FacebookGraphTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
@klass = Fogli::FacebookGraph
|
6
|
+
end
|
7
|
+
|
8
|
+
context "requesting" do
|
9
|
+
teardown do
|
10
|
+
Fogli.access_token = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
[:get, :post, :delete, :head].each do |method|
|
14
|
+
should "properly request #{method} type" do
|
15
|
+
@klass.expects(:request).with(method, "/foo", {}).once
|
16
|
+
@klass.send(method, "/foo", {})
|
17
|
+
end
|
18
|
+
|
19
|
+
should "properly have a raw request for #{method} type" do
|
20
|
+
RestClient.expects(method).with("/foo", {}).once
|
21
|
+
@klass.send("raw_#{method}".to_sym, "/foo", {})
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
should "use http by default" do
|
26
|
+
RestClient.expects(:get).with("http://#{@klass::GRAPH_DOMAIN}/foo", {}).once
|
27
|
+
@klass.request(:get, "/foo")
|
28
|
+
end
|
29
|
+
|
30
|
+
should "use https if an access token is set" do
|
31
|
+
Fogli.access_token = "foo"
|
32
|
+
RestClient.expects(:get).with("https://#{@klass::GRAPH_DOMAIN}/foo?access_token=foo", {}).once
|
33
|
+
@klass.request(:get, "/foo")
|
34
|
+
end
|
35
|
+
|
36
|
+
should "append parameters for GET/DELETE" do
|
37
|
+
params = { "foo" => "bar baz" }
|
38
|
+
RestClient.expects(:get).with("http://#{@klass::GRAPH_DOMAIN}/foo?foo=bar+baz", {}).once
|
39
|
+
@klass.request(:get, "/foo", params)
|
40
|
+
end
|
41
|
+
|
42
|
+
should "convert params to strings for GET/DELETE" do
|
43
|
+
params = { :limit => 1 }
|
44
|
+
RestClient.expects(:get).with("http://#{@klass::GRAPH_DOMAIN}/foo?limit=1", {}).once
|
45
|
+
@klass.request(:get, "/foo", params)
|
46
|
+
end
|
47
|
+
|
48
|
+
should "pass params into function for POST" do
|
49
|
+
params = { :foo => :baz }
|
50
|
+
RestClient.expects(:post).with("http://#{@klass::GRAPH_DOMAIN}/foo", params).once
|
51
|
+
@klass.request(:post, "/foo", params)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "error checking" do
|
56
|
+
def response(data)
|
57
|
+
response = mock("response")
|
58
|
+
response.stubs(:headers).returns({:content_type => "text/plain"})
|
59
|
+
response.stubs(:body).returns(data)
|
60
|
+
response.stubs(:code).returns(200)
|
61
|
+
response
|
62
|
+
end
|
63
|
+
|
64
|
+
should "return the data if the data is fine" do
|
65
|
+
data = { "foo" => "bar" }
|
66
|
+
|
67
|
+
assert_equal data, @klass.error_check { response(data) }
|
68
|
+
end
|
69
|
+
|
70
|
+
should "raise an exception if the data represents an error" do
|
71
|
+
data = { "error" => { "type" => "foo", "message" => "baz" }}
|
72
|
+
assert_raises(Fogli::Exception) do
|
73
|
+
@klass.error_check { response(data) }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
should "raise an exception for a 500 response code" do
|
78
|
+
resp = response({})
|
79
|
+
resp.stubs(:code).returns(500)
|
80
|
+
assert_raises(Fogli::Exception) do
|
81
|
+
@klass.error_check { resp }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
should "catch exceptions with responses" do
|
86
|
+
data = { "foo" => "bar" }
|
87
|
+
result = @klass.error_check do
|
88
|
+
e = RestClient::Exception.new
|
89
|
+
e.response = response(data)
|
90
|
+
raise e
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "parsing response" do
|
96
|
+
setup do
|
97
|
+
@headers = {}
|
98
|
+
@body = "[1]"
|
99
|
+
|
100
|
+
@response = mock("response")
|
101
|
+
@response.stubs(:headers).returns(@headers)
|
102
|
+
@response.stubs(:body).returns(@body)
|
103
|
+
end
|
104
|
+
|
105
|
+
should "simply return if the content-type is text/plain" do
|
106
|
+
@headers[:content_type] = "text/plain; foo=bar"
|
107
|
+
assert_equal @body, @klass.parse_response(@response)
|
108
|
+
end
|
109
|
+
|
110
|
+
should "parse JSON otherwise" do
|
111
|
+
@headers[:content_type] = "anything"
|
112
|
+
result= @klass.parse_response(@response)
|
113
|
+
assert result.is_a?(Array)
|
114
|
+
assert_equal 1, result[0]
|
115
|
+
end
|
116
|
+
|
117
|
+
should "return the raw body if a JSON parse error occurs" do
|
118
|
+
@headers[:content_type] = "whatever"
|
119
|
+
@body = "true"
|
120
|
+
@response.stubs(:body).returns(@body)
|
121
|
+
assert_equal @body, @klass.parse_response(@response)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
|
2
|
+
|
3
|
+
class FacebookObjectConnectionProxyTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
@klass = Fogli::FacebookObject::ConnectionProxy
|
6
|
+
|
7
|
+
@parent = Fogli::FacebookObject.new
|
8
|
+
@connection_name = "friends"
|
9
|
+
@connection_options = { :class => :FacebookObject }
|
10
|
+
@instance = @klass.new(@parent, @connection_name, @connection_options)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "loading" do
|
14
|
+
setup do
|
15
|
+
# Make sure no actual HTTP requests go through
|
16
|
+
@parent.stubs(:get)
|
17
|
+
@scope = Fogli::FacebookObject::ConnectionScope.new(@instance)
|
18
|
+
end
|
19
|
+
|
20
|
+
should "get the connection with the scope options and parse the data" do
|
21
|
+
@parent.expects(:get).with("/#{@connection_name}", @scope.options).once.returns(nil)
|
22
|
+
assert_equal({"data"=>[]}, @instance.load(@scope))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "parsing data" do
|
27
|
+
should "instantiate for each data item" do
|
28
|
+
data = {"data" => [{"id"=>"1"},{"id"=>"2"}]}
|
29
|
+
@instance.stubs(:connection_class).returns(Fogli::FacebookObject)
|
30
|
+
result = @instance.parse_data(data)
|
31
|
+
assert_equal data["data"].length, result["data"].length
|
32
|
+
assert_equal "1", result["data"][0].id
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "connection class" do
|
37
|
+
should "just return the class if specified" do
|
38
|
+
@connection_options[:class] = :User
|
39
|
+
assert_equal Fogli::User, @instance.connection_class
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
|
2
|
+
|
3
|
+
class FacebookObjectConnectionScopeTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
@klass = Fogli::FacebookObject::ConnectionScope
|
6
|
+
|
7
|
+
@proxy = Fogli::FacebookObject::ConnectionProxy.new(Fogli::FacebookObject.new,
|
8
|
+
:foo,
|
9
|
+
{:class => :Post})
|
10
|
+
@options = {}
|
11
|
+
@instance = @klass.new(@proxy, @options)
|
12
|
+
end
|
13
|
+
|
14
|
+
context "each" do
|
15
|
+
setup do
|
16
|
+
@instance.clear_cache
|
17
|
+
end
|
18
|
+
|
19
|
+
def stub_data(*values)
|
20
|
+
{ "data" => values }
|
21
|
+
end
|
22
|
+
|
23
|
+
should "load the initial data if its not yet loaded" do
|
24
|
+
@instance.expects(:load!).once
|
25
|
+
@instance.each {}
|
26
|
+
end
|
27
|
+
|
28
|
+
should "load as page end is reached" do
|
29
|
+
@instance.expects(:load!).once.returns(false)
|
30
|
+
|
31
|
+
data = [stub_data(1,2,3), stub_data(4,5,6)]
|
32
|
+
@instance.instance_variable_set(:@_data, data)
|
33
|
+
result = @instance.inject(0) do |acc, i|
|
34
|
+
acc + i
|
35
|
+
end
|
36
|
+
|
37
|
+
assert_equal 21, result
|
38
|
+
end
|
39
|
+
|
40
|
+
should "limit the data to the specified amount" do
|
41
|
+
data = [stub_data(1,2,3), stub_data(4,5,6), stub_data(7)]
|
42
|
+
@instance.options[:limit] = 2
|
43
|
+
@instance.instance_variable_set(:@_data, data)
|
44
|
+
result = @instance.inject(0) { |a,i| a + 1 }
|
45
|
+
assert_equal 2, result
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "loading" do
|
50
|
+
setup do
|
51
|
+
@instance.clear_cache
|
52
|
+
end
|
53
|
+
|
54
|
+
should "default the fields to all of the parent's if not specified" do
|
55
|
+
assert @instance.options[:fields].nil? # sanity check
|
56
|
+
@proxy.expects(:load).with() do |scope|
|
57
|
+
assert scope.options[:fields]
|
58
|
+
assert_equal Fogli::Post.properties.keys.join(","), scope.options[:fields]
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
@instance.load!
|
63
|
+
end
|
64
|
+
|
65
|
+
should "load the first page if data hasn't been loaded yet" do
|
66
|
+
data = mock("data")
|
67
|
+
@proxy.expects(:load).with(@instance).returns(data)
|
68
|
+
assert @instance.load!
|
69
|
+
assert_equal data, @instance._data.first
|
70
|
+
end
|
71
|
+
|
72
|
+
should "load the next page if the data has already been loaded and has next page" do
|
73
|
+
data = { "paging" => { "next" => "foo" } }
|
74
|
+
raw = { "data" => [] }
|
75
|
+
@proxy.stubs(:load).returns(data)
|
76
|
+
@instance.load!
|
77
|
+
Fogli::FacebookGraph.expects(:raw_get).with(data["paging"]["next"]).once.returns(raw)
|
78
|
+
@proxy.expects(:parse_data).with(raw).returns(raw)
|
79
|
+
assert @instance.load!
|
80
|
+
assert_equal raw, @instance._data.last
|
81
|
+
end
|
82
|
+
|
83
|
+
should "return false if no next page is available" do
|
84
|
+
data = { "paging" => { } }
|
85
|
+
@proxy.stubs(:load).returns(data)
|
86
|
+
@instance.load!
|
87
|
+
Fogli::FacebookGraph.expects(:raw_get).never
|
88
|
+
assert !@instance.load!
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
|
2
|
+
|
3
|
+
class FacebookObjectConnectionsTest < Test::Unit::TestCase
|
4
|
+
class FOCTestClass
|
5
|
+
include Fogli::FacebookObject::Connections
|
6
|
+
end
|
7
|
+
|
8
|
+
setup do
|
9
|
+
@klass = FOCTestClass
|
10
|
+
end
|
11
|
+
|
12
|
+
context "class methods" do
|
13
|
+
context "defining connections" do
|
14
|
+
teardown do
|
15
|
+
@klass.connections.clear
|
16
|
+
end
|
17
|
+
|
18
|
+
should "be able to define a connection" do
|
19
|
+
@klass.connection(:foo, :class => :bar)
|
20
|
+
assert @klass.connections.keys.include?(:foo)
|
21
|
+
end
|
22
|
+
|
23
|
+
should "be able to define multiple connections" do
|
24
|
+
@klass.connection(:foo, :bar, :class => :foo)
|
25
|
+
assert @klass.connections.keys.include?(:foo)
|
26
|
+
assert @klass.connections.keys.include?(:bar)
|
27
|
+
end
|
28
|
+
|
29
|
+
should "raise an exception if a class is not specified" do
|
30
|
+
assert_raises(ArgumentError) {
|
31
|
+
@klass.connection(:foo)
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
should "be able to define options" do
|
36
|
+
@klass.connection(:foo, :class => :baz)
|
37
|
+
assert @klass.connections.keys.include?(:foo)
|
38
|
+
assert_equal :baz, @klass.connections[:foo][:class]
|
39
|
+
end
|
40
|
+
|
41
|
+
should "propagate connections" do
|
42
|
+
@subklass = Class.new(@klass)
|
43
|
+
@klass.connection(:foo, :class => :bar)
|
44
|
+
assert !@subklass.connections.keys.include?(:foo)
|
45
|
+
@klass.propagate_connections(@subklass)
|
46
|
+
assert @subklass.connections.keys.include?(:foo)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
|
2
|
+
|
3
|
+
class FacebookObjectPropertiesTest < Test::Unit::TestCase
|
4
|
+
class FOPTestClass
|
5
|
+
include Fogli::FacebookObject::Properties
|
6
|
+
end
|
7
|
+
|
8
|
+
setup do
|
9
|
+
@klass = FOPTestClass
|
10
|
+
end
|
11
|
+
|
12
|
+
context "class methods" do
|
13
|
+
context "defining properties" do
|
14
|
+
setup do
|
15
|
+
@property_klass = @klass
|
16
|
+
end
|
17
|
+
|
18
|
+
teardown do
|
19
|
+
@property_klass.properties.clear
|
20
|
+
end
|
21
|
+
|
22
|
+
should "be able to define a property" do
|
23
|
+
@property_klass.property(:foo)
|
24
|
+
assert @property_klass.properties.keys.include?(:foo)
|
25
|
+
end
|
26
|
+
|
27
|
+
should "be able to define multiple properties" do
|
28
|
+
@property_klass.property(:foo, :bar)
|
29
|
+
assert @property_klass.properties.keys.include?(:foo)
|
30
|
+
assert @property_klass.properties.keys.include?(:bar)
|
31
|
+
end
|
32
|
+
|
33
|
+
should "be able to define options" do
|
34
|
+
@property_klass.property(:foo, :bar => :baz)
|
35
|
+
assert @property_klass.properties.keys.include?(:foo)
|
36
|
+
assert_equal :baz, @property_klass.properties[:foo][:bar]
|
37
|
+
end
|
38
|
+
|
39
|
+
should "propagate properties" do
|
40
|
+
@subklass = Class.new(@property_klass)
|
41
|
+
@property_klass.property :foo
|
42
|
+
assert !@subklass.properties.keys.include?(:foo)
|
43
|
+
@property_klass.propagate_properties(@subklass)
|
44
|
+
assert @subklass.properties.keys.include?(:foo)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with an instance" do
|
50
|
+
setup do
|
51
|
+
@klass.property :id
|
52
|
+
@instance = @klass.new
|
53
|
+
end
|
54
|
+
|
55
|
+
teardown do
|
56
|
+
@klass.properties.clear
|
57
|
+
end
|
58
|
+
|
59
|
+
should "set the properties based on the hash data" do
|
60
|
+
@instance.populate_properties({"id" => "foo"})
|
61
|
+
assert_equal "foo", @instance.id
|
62
|
+
end
|
63
|
+
|
64
|
+
should "set the properties based on the hash data [symbol]" do
|
65
|
+
@instance.populate_properties({:id => "foo"})
|
66
|
+
assert_equal "foo", @instance.id
|
67
|
+
end
|
68
|
+
|
69
|
+
should "detect and store NamedObjects" do
|
70
|
+
@instance.populate_properties({"id" => {"name" => "foo"}})
|
71
|
+
assert @instance.property_values[:id].is_a?(Fogli::NamedObject)
|
72
|
+
end
|
73
|
+
|
74
|
+
should "read NamedObject's names when reading a property" do
|
75
|
+
@instance.populate_properties({"id" => {"name" => "foo"}})
|
76
|
+
assert_equal "foo", @instance.id
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
|
2
|
+
|
3
|
+
class ScopeMethodsTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
@module = Fogli::FacebookObject::ScopeMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
context "scope methods" do
|
9
|
+
setup do
|
10
|
+
@klass = Class.new
|
11
|
+
@klass.send(:include, @module)
|
12
|
+
@instance = @klass.new
|
13
|
+
end
|
14
|
+
|
15
|
+
[:limit, :offset, :until, :since].each do |scope|
|
16
|
+
should "return a new connection scope for #{scope}" do
|
17
|
+
value = "#{scope}_foo"
|
18
|
+
result = @instance.send(scope, value)
|
19
|
+
assert_equal value, result.options[scope]
|
20
|
+
assert_equal @instance, result.proxy
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
should "initialize a scope for fields" do
|
25
|
+
tests = [
|
26
|
+
["name,birthday,location"],
|
27
|
+
[:name, :birthday, :location],
|
28
|
+
[["name", :birthday], :location],
|
29
|
+
[["name"], [[[:birthday]], :location]]
|
30
|
+
]
|
31
|
+
|
32
|
+
tests.each do |args|
|
33
|
+
scope = @instance.fields(*args)
|
34
|
+
assert_equal "name,birthday,location", scope.options[:fields]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
context "scope initializer args" do
|
41
|
+
context "not a connection scope" do
|
42
|
+
setup do
|
43
|
+
@klass = Class.new
|
44
|
+
@klass.send(:include, @module)
|
45
|
+
@instance = @klass.new
|
46
|
+
end
|
47
|
+
|
48
|
+
should "return the proxy if not a connection scope" do
|
49
|
+
proxy, options = @instance._scope_initializer_args(:foo, :bar)
|
50
|
+
assert_equal @instance, proxy
|
51
|
+
assert_equal({:foo => :bar}, options)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "in a connection scope" do
|
56
|
+
setup do
|
57
|
+
@proxy = mock("proxy")
|
58
|
+
@options = { :foo => :bar }
|
59
|
+
@instance = Fogli::FacebookObject::ConnectionScope.new(@proxy, @options)
|
60
|
+
end
|
61
|
+
|
62
|
+
should "return the proxy and merged options" do
|
63
|
+
proxy, options = @instance._scope_initializer_args(:bar, :baz)
|
64
|
+
assert_equal @proxy, proxy
|
65
|
+
assert_equal(@options.merge(:bar => :baz), options)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|