twilio-test-toolkit 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -47,9 +47,9 @@ TTT doesn't yet support (but you should contribute them!)
47
47
  What's required
48
48
  ================
49
49
 
50
- TTT depends on [Capybara](https://github.com/jnicklas/capybara). It uses Capybara's session object to POST requests to your controllers.
50
+ TTT depends on [Capybara](https://github.com/jnicklas/capybara). It uses Capybara's session object to make requests to your controllers.
51
51
 
52
- TTT expects your controller actions to behave like well-behaved Twilio callbacks. That is, you need to respond to XML-formatted requests, and need to respond with a 200 OK. TTT also requires that your controller actions be wired for POST, not GET (Twilio does support GET, but TTT lacks this support). Twilio will not follow 301 or 302 redirects properly, and neither will TTT (see below for more details).
52
+ TTT expects your controller actions to behave like well-behaved Twilio callbacks. That is, you need to respond to XML-formatted requests, and need to respond with a 200 OK. Twilio will not follow 301 or 302 redirects properly, and neither will TTT (see below for more details).
53
53
 
54
54
  TTT has only been tested with RSpec on Rails. It might work on other test frameworks or other Rack-based frameworks. Feel free to submit pull requests to improve compatibility with these.
55
55
 
@@ -89,15 +89,19 @@ This section describes how to use TTT and its basic functionality.
89
89
  ttt_call
90
90
  -------------
91
91
 
92
- The *ttt_call* method is the main entry point for working with TTT. You call this method to initiate a "Twilio phone call" to your controller actions. TTT simulates Twilio's behavior by POSTing to your action with the expected Twilio parameters (From, To, CallSid, etc).
92
+ The *ttt_call* method is the main entry point for working with TTT. You call this method to initiate a "Twilio phone call" to your controller actions. TTT simulates Twilio's behavior by making requests to your action with the expected Twilio parameters (From, To, CallSid, etc).
93
93
 
94
- *ttt_call* has three required parameters, and two optional ones:
94
+ *ttt_call* has three required parameters and an options hash:
95
95
 
96
- @call = ttt_call(action_path, from_number, to_number, call_sid = nil, is_machine = false)
96
+ @call = ttt_call(action_path, from_number, to_number, options = {})
97
97
 
98
- * **action_path**. Where to POST your request. It should be obvious by now, but whatever action you specify here should be a POST action.
98
+ * **action_path**. Where to make your request. By default this will be a POST, but you can override it with the options hash.
99
99
  * **from_number**. What to fill params[:From] with. If you don't care about this value, you can pass a blank one, as this is only used to pass along to your actions.
100
100
  * **to_number**. What to fill params[:To] with.
101
+
102
+ Options are:
103
+
104
+ * **method** . Specify the http method of the initial request. By default this will be :post.
101
105
  * **call_sid**. Specify an optional fixed value to be passed as params[:CallSid]. This is useful if you are expecting a specific SID. For instance, a common pattern is to initiate a call, store the SID in your database, and look up the call when you get the callback. If you don't pass a SID, TTT will generate one for you that's just a UUID.
102
106
  * **is_machine**. Controls params[:AnsweredBy]. See Twilio's documentation for more information on how Twilio uses this.
103
107
 
@@ -155,7 +159,7 @@ These methods are available on any CallScope.
155
159
  Gathers
156
160
  --------------
157
161
 
158
- Gathers are used to collect digits from the caller (e.g. "press 1 to speak with a representative, press 2 to cancel"). Twilio handles Gathers by speaking the contents of the Gather and waiting for a digit or digits to be pressed. If nothing is pressed, it continues with the script. If something is pressed, it aborts processing the current script and POSTs the digits (via params[:Digits]) to the path specified by the action attribute. TTT handles Gathers in a similar way.
162
+ Gathers are used to collect digits from the caller (e.g. "press 1 to speak with a representative, press 2 to cancel"). Twilio handles Gathers by speaking the contents of the Gather and waiting for a digit or digits to be pressed. If nothing is pressed, it continues with the script. If something is pressed, it aborts processing the current script and makes a request with the digits (via params[:Digits]) to the path specified by the action attribute. If no method is specified in the options, this will be a post TTT handles Gathers in a similar way.
159
163
 
160
164
  You can only interact with a gather by calling *within_gather*:
161
165
 
@@ -178,7 +182,7 @@ Within a gather CallScope, you can use the following methods:
178
182
 
179
183
  You can also use other CallScope methods (e.g. *has_say?* and similar.)
180
184
 
181
- The *press* method has a few caveats worth knowing. It's only callable once per gather - when you call it, TTT will immediately POST to the gather's action. There is no way to simulate pressing buttons slowly, and you don't really need to do this anyways - Twilio doesn't care and just passes them all at once. *press* simply fills out the value of params[:Digits] and POSTs that to your method, just like Twilio does.
185
+ The *press* method has a few caveats worth knowing. It's only callable once per gather - when you call it, TTT will immediately call the gather's action. There is no way to simulate pressing buttons slowly, and you don't really need to do this anyways - Twilio doesn't care and just passes them all at once. *press* simply fills out the value of params[:Digits] and calls your method, just like Twilio does.
182
186
 
183
187
  Although you can technically pass whatever you want to *press*, in practice Twilio only sends digits and #. Still it's probably a good idea to test garbage data in this parameter with your actions, so TTT doesn't get in your way if you want to call press with "UNICORNSANDPONIES" as a parameter.
184
188
 
@@ -187,7 +191,7 @@ TTT doesn't attempt to validate your TwiML, so it's worth knowing that Gather on
187
191
  Redirects
188
192
  --------------
189
193
 
190
- The Redirect element is used to tell Twilio to POST to a different page. It differs from a standard 301 or 302 redirect (created by a *redirect_to*) in that the 301/302 redirects don't support a POST, and if you try a *redirect_to* within a Twilio action, Twilio will fail and your caller will get the dreaded "I'm sorry, an application error has occurred" message. Because Twilio doesn't support 301/302 redirects, TTT doesn't either, and if you use one, TTT will complain.
194
+ The Redirect element is used to tell Twilio to call a different page. It differs from a standard 301 or 302 redirect (created by a *redirect_to*) in that the 301/302 redirects don't support a POST, and if you try a *redirect_to* within a Twilio action, Twilio will fail and your caller will get the dreaded "I'm sorry, an application error has occurred" message. Because Twilio doesn't support 301/302 redirects, TTT doesn't either, and if you use one, TTT will complain.
191
195
 
192
196
  There are several methods you can use within a CallScope related to redirects:
193
197
 
@@ -207,7 +211,6 @@ Contributing
207
211
  TTT is pretty basic, but it should work for most people's needs. You might consider helping to improve it. Some things that could be done:
208
212
 
209
213
  * Support more Twilio functionality
210
- * Support GET actions. Twilio technically supports this, although it doesn't seem to be used very often.
211
214
  * Build more stringent checks into says and plays - e.g. verify that there's enough of a pause between sentences.
212
215
  * Build checks to make sure that numbers, dates, and other special text is spoken properly (e.g. "one two three" instead of "one hundred twenty three").
213
216
  * Build checks to validate the correctness of your TwiML.
@@ -217,6 +220,15 @@ TTT is pretty basic, but it should work for most people's needs. You might consi
217
220
 
218
221
  Contributions are welcome and encouraged. The usual deal applies - fork a branch, add tests, add your changes, submit a pull request. If I haven't done anything with your pull request in a reasonable amount of time, ping me on Twitter or email and I'll get on it.
219
222
 
223
+ Running Tests
224
+ ----------------
225
+
226
+ bundle install
227
+ cd spec/dummy
228
+ bundle exec rake db:create
229
+ cd ../..
230
+ bundle exec rspec
231
+
220
232
  Credits
221
233
  ================
222
234
 
@@ -3,26 +3,30 @@ require "twilio-test-toolkit/call_scope"
3
3
  module TwilioTestToolkit
4
4
  # Models a call
5
5
  class CallInProgress < CallScope
6
- # Init the call
7
- def initialize(initial_path, from_number, to_number, call_sid, is_machine)
6
+ # Initiate a call. Options:
7
+ # * :method - specify the http method of the initial api call
8
+ # * :call_sid - specify an optional fixed value to be passed as params[:CallSid]
9
+ # * :is_machine - controls params[:AnsweredBy]
10
+ def initialize(initial_path, from_number, to_number, options = {})
8
11
  # Save our variables for later
9
12
  @initial_path = initial_path
10
13
  @from_number = from_number
11
14
  @to_number = to_number
12
- @is_machine = is_machine
15
+ @is_machine = options[:is_machine]
16
+ @method = options[:method] || :post
13
17
 
14
18
  # Generate an initial call SID if we don't have one
15
- if (call_sid.nil?)
19
+ if (options[:call_sid].nil?)
16
20
  @sid = UUIDTools::UUID.random_create.to_s
17
21
  else
18
- @sid = call_sid
22
+ @sid = options[:call_sid]
19
23
  end
20
24
 
21
25
  # We are the root call
22
26
  self.root_call = self
23
27
 
24
28
  # Create the request
25
- post_for_twiml!(@initial_path, "", @is_machine)
29
+ request_for_twiml!(@initial_path, :method => @method, :is_machine => @is_machine)
26
30
  end
27
31
 
28
32
  def sid
@@ -44,5 +48,9 @@ module TwilioTestToolkit
44
48
  def is_machine
45
49
  @is_machine
46
50
  end
51
+
52
+ def method
53
+ @method
54
+ end
47
55
  end
48
- end
56
+ end
@@ -12,14 +12,14 @@ module TwilioTestToolkit
12
12
  el = get_redirect_node
13
13
  raise "No redirect" if el.nil?
14
14
 
15
- return CallScope.from_post(self, el.text)
15
+ return CallScope.from_request(self, el.text, :method =>el[:method])
16
16
  end
17
17
 
18
18
  def follow_redirect!
19
19
  el = get_redirect_node
20
20
  raise "No redirect" if el.nil?
21
21
 
22
- post_for_twiml!(normalize_redirect_path(el.text))
22
+ request_for_twiml!(normalize_redirect_path(el.text), :method => el[:method])
23
23
  end
24
24
 
25
25
  # Stuff for Says
@@ -66,10 +66,15 @@ module TwilioTestToolkit
66
66
  end
67
67
 
68
68
  def gather_action
69
- rasie "Not a gather" unless gather?
69
+ raise "Not a gather" unless gather?
70
70
  return @xml["action"]
71
71
  end
72
72
 
73
+ def gather_method
74
+ raise "Not a gather" unless gather?
75
+ return @xml["method"]
76
+ end
77
+
73
78
  def press(digits)
74
79
  raise "Not a gather" unless gather?
75
80
 
@@ -77,7 +82,7 @@ module TwilioTestToolkit
77
82
  path = gather_action
78
83
 
79
84
  # Update the root call
80
- root_call.post_for_twiml!(path, digits)
85
+ root_call.request_for_twiml!(path, :digits => digits, :method => gather_method)
81
86
  end
82
87
 
83
88
  # Some basic accessors
@@ -115,11 +120,13 @@ module TwilioTestToolkit
115
120
  @xml = xml
116
121
  end
117
122
 
118
- # Create a new object from a post
119
- def self.from_post(parent, path, digits = "")
123
+ # Create a new object from a post. Options:
124
+ # * :method - the http method of the request, defaults to :post
125
+ # * :digits - becomes params[:Digits], defaults to ""
126
+ def self.from_request(parent, path, options = {})
120
127
  new_scope = CallScope.new
121
128
  new_scope.send(:root_call=, parent.root_call)
122
- new_scope.send(:post_for_twiml!, path, digits)
129
+ new_scope.send(:request_for_twiml!, path, :digits => options[:digits] || "", :method => options[:method] || :post)
123
130
  return new_scope
124
131
  end
125
132
 
@@ -131,19 +138,21 @@ module TwilioTestToolkit
131
138
  return p
132
139
  end
133
140
 
134
- # Post and update the scope
135
- def post_for_twiml!(path, digits = "", is_machine = false)
141
+ # Post and update the scope. Options:
142
+ # :digits - becomes params[:Digits], optional (becomes "")
143
+ # :is_machine - becomes params[:AnsweredBy], defaults to false / human
144
+ def request_for_twiml!(path, options = {})
136
145
  @current_path = normalize_redirect_path(path)
137
146
 
138
147
  # Post the query
139
148
  rack_test_session_wrapper = Capybara.current_session.driver
140
- @response = rack_test_session_wrapper.post(@current_path,
149
+ @response = rack_test_session_wrapper.send(options[:method] || :post, @current_path,
141
150
  :format => :xml,
142
151
  :CallSid => @root_call.sid,
143
- :Digits => digits,
144
152
  :From => @root_call.from_number,
153
+ :Digits => options[:digits] || "",
145
154
  :To => @root_call.to_number,
146
- :AnsweredBy => (is_machine ? "machine" : "human")
155
+ :AnsweredBy => (options[:is_machine] ? "machine" : "human")
147
156
  )
148
157
 
149
158
  # All Twilio responses must be a success.
@@ -2,11 +2,14 @@ module TwilioTestToolkit
2
2
  require 'twilio-test-toolkit/call_in_progress'
3
3
 
4
4
  # Adds the `ttt_call` method to the top-level namespace.
5
- module DSL
6
- # call = ttt_call(inbound_phone_index_path, "+12065551212")
7
- def ttt_call(initial_path, from_number, to_number, call_sid = nil, is_machine = false)
5
+ module DSL
6
+ # Initiate a call. Options:
7
+ # * :method - specify the http method of the initial api call
8
+ # * :call_sid - specify an optional fixed value to be passed as params[:CallSid]
9
+ # * :is_machine - controls params[:AnsweredBy]
10
+ def ttt_call(initial_path, from_number, to_number, options = {})
8
11
  # Make a new call in progress
9
- return CallInProgress.new(initial_path, from_number, to_number, call_sid, is_machine)
12
+ return CallInProgress.new(initial_path, from_number, to_number, options)
10
13
  end
11
14
  end
12
15
  end
@@ -1,3 +1,3 @@
1
1
  module TwilioTestToolkit
2
- VERSION = "1.0.0"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -2,7 +2,7 @@ class TwilioController < ApplicationController
2
2
  layout "twilio.layout"
3
3
  respond_to :xml
4
4
 
5
- def testaction
5
+ def test_action
6
6
  @digits = params[:Digits]
7
7
  end
8
8
  end
@@ -0,0 +1 @@
1
+ <Redirect method="post"><%= test_start_twilio_index_path %></Redirect>
@@ -0,0 +1,5 @@
1
+ <Say voice="woman">Hi there.</Say>
2
+
3
+ <Gather action="<%= test_action_twilio_index_path %>" method="post">
4
+ <Say>Please enter some digits.</Say>
5
+ </Gather>
@@ -1,11 +1,12 @@
1
1
  Dummy::Application.routes.draw do
2
2
  resources :twilio do
3
- post "teststart", :on => :collection
4
- post "testaction", :on => :collection
3
+ get "test_start", :on => :collection
4
+ post "test_start", :on => :collection
5
+ post "test_action", :on => :collection
5
6
 
6
- post "testhangup", :on => :collection
7
- post "testdial", :on => :collection
8
- post "testredirect", :on => :collection
9
- post "testsay", :on => :collection
7
+ post "test_hangup", :on => :collection
8
+ post "test_dial", :on => :collection
9
+ post "test_redirect", :on => :collection
10
+ post "test_say", :on => :collection
10
11
  end
11
12
  end
@@ -8,7 +8,7 @@ describe TwilioTestToolkit::CallScope do
8
8
 
9
9
  describe "basics" do
10
10
  before(:each) do
11
- @call = ttt_call(teststart_twilio_index_path, @our_number, @their_number)
11
+ @call = ttt_call(test_start_twilio_index_path, @our_number, @their_number)
12
12
  end
13
13
 
14
14
  it "should be a CallScope" do
@@ -21,7 +21,7 @@ describe TwilioTestToolkit::CallScope do
21
21
  end
22
22
 
23
23
  it "should have the right path" do
24
- @call.current_path.should == teststart_twilio_index_path
24
+ @call.current_path.should == test_start_twilio_index_path
25
25
  end
26
26
 
27
27
  it "should have a response xml value" do
@@ -37,7 +37,7 @@ describe TwilioTestToolkit::CallScope do
37
37
  describe "redirect" do
38
38
  describe "success" do
39
39
  before(:each) do
40
- @call = ttt_call(testredirect_twilio_index_path, @our_number, @their_number)
40
+ @call = ttt_call(test_redirect_twilio_index_path, @our_number, @their_number)
41
41
  end
42
42
 
43
43
  it "should have the redirect methods" do
@@ -53,8 +53,8 @@ describe TwilioTestToolkit::CallScope do
53
53
 
54
54
  it "should have the right values for has_redirect_to?" do
55
55
  @call.has_redirect_to?("http://foo").should be_false
56
- @call.has_redirect_to?(teststart_twilio_index_path).should be_true
57
- @call.has_redirect_to?(teststart_twilio_index_path + ".xml").should be_true # Should force normalization
56
+ @call.has_redirect_to?(test_start_twilio_index_path).should be_true
57
+ @call.has_redirect_to?(test_start_twilio_index_path + ".xml").should be_true # Should force normalization
58
58
  end
59
59
 
60
60
  it "should follow the redirect (immutable version)" do
@@ -62,7 +62,7 @@ describe TwilioTestToolkit::CallScope do
62
62
  newcall = @call.follow_redirect
63
63
 
64
64
  # Make sure it followed
65
- newcall.current_path.should == teststart_twilio_index_path
65
+ newcall.current_path.should == test_start_twilio_index_path
66
66
 
67
67
  # And is not the same call
68
68
  newcall.response_xml.should_not == @call.response_xml
@@ -70,7 +70,7 @@ describe TwilioTestToolkit::CallScope do
70
70
  newcall.root_call.should == @call
71
71
 
72
72
  # And we did not modify the original call
73
- @call.current_path.should == testredirect_twilio_index_path
73
+ @call.current_path.should == test_redirect_twilio_index_path
74
74
  end
75
75
 
76
76
  it "should follow the redirect (mutable version)" do
@@ -78,14 +78,14 @@ describe TwilioTestToolkit::CallScope do
78
78
  @call.follow_redirect!
79
79
 
80
80
  # Make sure it followed
81
- @call.current_path.should == teststart_twilio_index_path
81
+ @call.current_path.should == test_start_twilio_index_path
82
82
  end
83
83
  end
84
84
 
85
85
  describe "failure" do
86
86
  before(:each) do
87
87
  # Initiate a call that's not on a redirect - various calls will fail
88
- @call = ttt_call(testsay_twilio_index_path, @our_number, @their_number)
88
+ @call = ttt_call(test_say_twilio_index_path, @our_number, @their_number)
89
89
  end
90
90
 
91
91
  it "should have the right value for has_redirect?" do
@@ -94,8 +94,8 @@ describe TwilioTestToolkit::CallScope do
94
94
 
95
95
  it "should have the right values for has_redirect_to?" do
96
96
  @call.has_redirect_to?("http://foo").should be_false
97
- @call.has_redirect_to?(teststart_twilio_index_path).should be_false
98
- @call.has_redirect_to?(teststart_twilio_index_path + ".xml").should be_false
97
+ @call.has_redirect_to?(test_start_twilio_index_path).should be_false
98
+ @call.has_redirect_to?(test_start_twilio_index_path + ".xml").should be_false
99
99
  end
100
100
 
101
101
  it "should raise an error on follow_redirect" do
@@ -110,7 +110,7 @@ describe TwilioTestToolkit::CallScope do
110
110
 
111
111
  describe "say" do
112
112
  before(:each) do
113
- @call = ttt_call(testsay_twilio_index_path, @our_number, @their_number)
113
+ @call = ttt_call(test_say_twilio_index_path, @our_number, @their_number)
114
114
  end
115
115
 
116
116
  it "should have the expected say methods" do
@@ -126,7 +126,7 @@ describe TwilioTestToolkit::CallScope do
126
126
 
127
127
  describe "dial" do
128
128
  before(:each) do
129
- @call = ttt_call(testdial_twilio_index_path, @our_number, @their_number)
129
+ @call = ttt_call(test_dial_twilio_index_path, @our_number, @their_number)
130
130
  end
131
131
 
132
132
  it "should have the expected dial methods" do
@@ -143,7 +143,7 @@ describe TwilioTestToolkit::CallScope do
143
143
  describe "hangup" do
144
144
  describe "success" do
145
145
  before(:each) do
146
- @call = ttt_call(testhangup_twilio_index_path, @our_number, @their_number)
146
+ @call = ttt_call(test_hangup_twilio_index_path, @our_number, @their_number)
147
147
  end
148
148
 
149
149
  it "should have the expected hangup methods" do
@@ -157,7 +157,7 @@ describe TwilioTestToolkit::CallScope do
157
157
 
158
158
  describe "failure" do
159
159
  before(:each) do
160
- @call = ttt_call(teststart_twilio_index_path, @our_number, @their_number)
160
+ @call = ttt_call(test_start_twilio_index_path, @our_number, @their_number)
161
161
  end
162
162
 
163
163
  it "should have the right value for has_hangup?" do
@@ -169,7 +169,7 @@ describe TwilioTestToolkit::CallScope do
169
169
  describe "gather" do
170
170
  describe "success" do
171
171
  before(:each) do
172
- @call = ttt_call(teststart_twilio_index_path, @our_number, @their_number)
172
+ @call = ttt_call(test_start_twilio_index_path, @our_number, @their_number)
173
173
  end
174
174
 
175
175
  it "should have the expected gather methods" do
@@ -206,7 +206,7 @@ describe TwilioTestToolkit::CallScope do
206
206
  # We should be in a gather
207
207
  gather.gather?.should be_true
208
208
  # And we should have an action
209
- gather.gather_action.should == testaction_twilio_index_path
209
+ gather.gather_action.should == test_action_twilio_index_path
210
210
 
211
211
  # And we should have the right root call
212
212
  gather.root_call.should == @call
@@ -216,7 +216,7 @@ describe TwilioTestToolkit::CallScope do
216
216
  end
217
217
 
218
218
  # This should update the path
219
- @call.current_path.should == testaction_twilio_index_path
219
+ @call.current_path.should == test_action_twilio_index_path
220
220
 
221
221
  # This view says the digits we pressed - make sure
222
222
  @call.should have_say "You entered 98765"
@@ -228,13 +228,13 @@ describe TwilioTestToolkit::CallScope do
228
228
  end
229
229
 
230
230
  # We should still be on the same page
231
- @call.current_path.should == teststart_twilio_index_path
231
+ @call.current_path.should == test_start_twilio_index_path
232
232
  end
233
233
  end
234
234
 
235
235
  describe "failure" do
236
236
  before(:each) do
237
- @call = ttt_call(testsay_twilio_index_path, @our_number, @their_number)
237
+ @call = ttt_call(test_say_twilio_index_path, @our_number, @their_number)
238
238
  end
239
239
 
240
240
  it "should have the right value for has_gather?" do
@@ -9,7 +9,7 @@ describe TwilioTestToolkit::DSL do
9
9
  describe "ttt_call" do
10
10
  describe "basics" do
11
11
  before(:each) do
12
- @call = ttt_call(teststart_twilio_index_path, @our_number, @their_number)
12
+ @call = ttt_call(test_start_twilio_index_path, @our_number, @their_number)
13
13
  end
14
14
 
15
15
  it "should assign the call" do
@@ -20,18 +20,22 @@ describe TwilioTestToolkit::DSL do
20
20
  @call.sid.should_not be_blank
21
21
  end
22
22
 
23
+ it "should default the method to post" do
24
+ @call.method.should == :post
25
+ end
26
+
23
27
  it "should have the right properties" do
24
- @call.initial_path.should == teststart_twilio_index_path
28
+ @call.initial_path.should == test_start_twilio_index_path
25
29
  @call.from_number.should == @our_number
26
30
  @call.to_number.should == @their_number
27
31
  @call.is_machine.should be_false
28
32
  end
29
33
  end
30
34
 
31
- describe "with a sid and machine override" do
35
+ describe "with a sid, method and machine override" do
32
36
  before(:each) do
33
37
  @mysid = "1234567"
34
- @call = ttt_call(teststart_twilio_index_path, @our_number, @their_number, @mysid, true)
38
+ @call = ttt_call(test_start_twilio_index_path, @our_number, @their_number, :call_sid => @mysid, :is_machine => true, :method => :get)
35
39
  end
36
40
 
37
41
  it "should have the right sid" do
@@ -41,6 +45,10 @@ describe TwilioTestToolkit::DSL do
41
45
  it "should be a machine call" do
42
46
  @call.is_machine.should be_true
43
47
  end
48
+
49
+ it "should be a get call" do
50
+ @call.method.should == :get
51
+ end
44
52
  end
45
53
  end
46
54
  end