parity-sendgrid-api 0.0.4

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.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +3 -0
  5. data/.yardopts +6 -0
  6. data/Gemfile +17 -0
  7. data/Gemfile.lock +67 -0
  8. data/LICENSE +22 -0
  9. data/README.md +261 -0
  10. data/Rakefile +12 -0
  11. data/lib/sendgrid/api.rb +7 -0
  12. data/lib/sendgrid/api/client.rb +43 -0
  13. data/lib/sendgrid/api/entities/category.rb +13 -0
  14. data/lib/sendgrid/api/entities/email.rb +13 -0
  15. data/lib/sendgrid/api/entities/entity.rb +83 -0
  16. data/lib/sendgrid/api/entities/list.rb +30 -0
  17. data/lib/sendgrid/api/entities/marketing_email.rb +20 -0
  18. data/lib/sendgrid/api/entities/profile.rb +14 -0
  19. data/lib/sendgrid/api/entities/response.rb +21 -0
  20. data/lib/sendgrid/api/entities/response_insert.rb +23 -0
  21. data/lib/sendgrid/api/entities/response_remove.rb +23 -0
  22. data/lib/sendgrid/api/entities/schedule.rb +13 -0
  23. data/lib/sendgrid/api/entities/sender_address.rb +13 -0
  24. data/lib/sendgrid/api/entities/stats.rb +14 -0
  25. data/lib/sendgrid/api/newsletter/categories.rb +74 -0
  26. data/lib/sendgrid/api/newsletter/emails.rb +69 -0
  27. data/lib/sendgrid/api/newsletter/lists.rb +64 -0
  28. data/lib/sendgrid/api/newsletter/marketing_emails.rb +72 -0
  29. data/lib/sendgrid/api/newsletter/recipients.rb +55 -0
  30. data/lib/sendgrid/api/newsletter/schedule.rb +70 -0
  31. data/lib/sendgrid/api/newsletter/sender_addresses.rb +80 -0
  32. data/lib/sendgrid/api/newsletter/utils.rb +34 -0
  33. data/lib/sendgrid/api/rest/errors/error.rb +66 -0
  34. data/lib/sendgrid/api/rest/resource.rb +58 -0
  35. data/lib/sendgrid/api/rest/response/parse_error.rb +19 -0
  36. data/lib/sendgrid/api/rest/response/parse_json.rb +24 -0
  37. data/lib/sendgrid/api/service.rb +23 -0
  38. data/lib/sendgrid/api/version.rb +5 -0
  39. data/lib/sendgrid/api/web/mail.rb +44 -0
  40. data/lib/sendgrid/api/web/profile.rb +38 -0
  41. data/lib/sendgrid/api/web/stats.rb +36 -0
  42. data/sendgrid-api.gemspec +23 -0
  43. data/spec/fixtures/categories.json +11 -0
  44. data/spec/fixtures/emails/email.json +6 -0
  45. data/spec/fixtures/emails/emails.json +10 -0
  46. data/spec/fixtures/errors/already_exists.json +3 -0
  47. data/spec/fixtures/errors/bad_request.json +6 -0
  48. data/spec/fixtures/errors/database_error.json +3 -0
  49. data/spec/fixtures/errors/does_not_exist.json +3 -0
  50. data/spec/fixtures/errors/forbidden.json +3 -0
  51. data/spec/fixtures/errors/invalid_fields.json +3 -0
  52. data/spec/fixtures/errors/not_scheduled.json +3 -0
  53. data/spec/fixtures/errors/unauthorized.json +6 -0
  54. data/spec/fixtures/lists/list.json +5 -0
  55. data/spec/fixtures/lists/lists.json +11 -0
  56. data/spec/fixtures/marketing_emails/marketing_email.json +19 -0
  57. data/spec/fixtures/marketing_emails/marketing_emails.json +10 -0
  58. data/spec/fixtures/profile.json +18 -0
  59. data/spec/fixtures/recipients.json +8 -0
  60. data/spec/fixtures/schedule.json +3 -0
  61. data/spec/fixtures/sender_addresses/sender_address.json +11 -0
  62. data/spec/fixtures/sender_addresses/sender_addresses.json +11 -0
  63. data/spec/fixtures/stats.json +50 -0
  64. data/spec/fixtures/success.json +3 -0
  65. data/spec/sendgrid/api/client_spec.rb +38 -0
  66. data/spec/sendgrid/api/entities/category_spec.rb +14 -0
  67. data/spec/sendgrid/api/entities/email_spec.rb +15 -0
  68. data/spec/sendgrid/api/entities/entity_spec.rb +279 -0
  69. data/spec/sendgrid/api/entities/list_spec.rb +34 -0
  70. data/spec/sendgrid/api/entities/marketing_email_spec.rb +31 -0
  71. data/spec/sendgrid/api/entities/profile_spec.rb +26 -0
  72. data/spec/sendgrid/api/entities/response_insert_spec.rb +28 -0
  73. data/spec/sendgrid/api/entities/response_remove_spec.rb +28 -0
  74. data/spec/sendgrid/api/entities/response_spec.rb +28 -0
  75. data/spec/sendgrid/api/entities/schedule_spec.rb +14 -0
  76. data/spec/sendgrid/api/entities/sender_address_spec.rb +21 -0
  77. data/spec/sendgrid/api/entities/stats_spec.rb +25 -0
  78. data/spec/sendgrid/api/newsletter/categories_spec.rb +247 -0
  79. data/spec/sendgrid/api/newsletter/emails_spec.rb +265 -0
  80. data/spec/sendgrid/api/newsletter/lists_spec.rb +307 -0
  81. data/spec/sendgrid/api/newsletter/marketing_emails_spec.rb +306 -0
  82. data/spec/sendgrid/api/newsletter/recipients_spec.rb +252 -0
  83. data/spec/sendgrid/api/newsletter/schedule_spec.rb +263 -0
  84. data/spec/sendgrid/api/newsletter/sender_addresses_spec.rb +300 -0
  85. data/spec/sendgrid/api/rest/errors/error_spec.rb +121 -0
  86. data/spec/sendgrid/api/rest/resource_spec.rb +145 -0
  87. data/spec/sendgrid/api/rest/response/parse_error_spec.rb +39 -0
  88. data/spec/sendgrid/api/rest/response/parse_json_spec.rb +45 -0
  89. data/spec/sendgrid/api/service_spec.rb +44 -0
  90. data/spec/sendgrid/api/version_spec.rb +11 -0
  91. data/spec/sendgrid/api/web/mail_spec.rb +111 -0
  92. data/spec/sendgrid/api/web/profile_spec.rb +110 -0
  93. data/spec/sendgrid/api/web/stats_spec.rb +94 -0
  94. data/spec/spec_helper.rb +23 -0
  95. data/spec/support/helpers.rb +23 -0
  96. data/spec/support/mock.rb +30 -0
  97. data/spec/support/online.rb +114 -0
  98. data/spec/support/shared_examples.rb +104 -0
  99. metadata +225 -0
@@ -0,0 +1,64 @@
1
+ require 'sendgrid/api/service'
2
+ require 'sendgrid/api/entities/list'
3
+ require 'sendgrid/api/entities/response'
4
+ require 'sendgrid/api/newsletter/utils'
5
+
6
+ module Sendgrid
7
+ module API
8
+ module Newsletter
9
+ module Lists
10
+
11
+ def lists
12
+ Services.new(resource)
13
+ end
14
+
15
+ class Services < Sendgrid::API::Service
16
+ include Newsletter::Utils
17
+
18
+ # Create a new Recipient List.
19
+ #
20
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/lists.html#-add
21
+ # @param list [String, Entities::List] A new list name or Entities::List object.
22
+ # @return [Entities::Response] An Entities::Response object.
23
+ def add(list)
24
+ params = { :list => extract_listname(list) }
25
+ perform_request(Entities::Response, 'newsletter/lists/add.json', params)
26
+ end
27
+
28
+ # Rename a Recipient List.
29
+ #
30
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/lists.html#-edit
31
+ # @param list [String, Entities::List] An existing list name or Entities::List object.
32
+ # @param newlist [String, Entities::List] A new list name or Entities::List object.
33
+ # @return [Entities::Response] An Entities::Response object.
34
+ def edit(list, newlist)
35
+ params = { :list => extract_listname(list), :newlist => extract_listname(newlist) }
36
+ perform_request(Entities::Response, 'newsletter/lists/edit.json', params)
37
+ end
38
+
39
+ # List all Recipient Lists on your account, or check if a particular List exists.
40
+ #
41
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/lists.html#-get
42
+ # @param list [String, Entities::List] An existing list name or Entities::List object. Optional.
43
+ # @return [Array<Entities::List>] An array of Entities::List objects.
44
+ def get(list = nil)
45
+ params = { :list => extract_listname(list) } if list
46
+ perform_request(Entities::List, 'newsletter/lists/get.json', params || {})
47
+ end
48
+
49
+ # Remove a Recipient List from your account.
50
+ #
51
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/lists.html#-delete
52
+ # @param list [String, Entities::List] An existing list name or Entities::List object.
53
+ # @return [Entities::Response] An Entities::Response object.
54
+ def delete(list)
55
+ params = { :list => extract_listname(list) }
56
+ perform_request(Entities::Response, 'newsletter/lists/delete.json', params)
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,72 @@
1
+ require 'sendgrid/api/service'
2
+ require 'sendgrid/api/entities/marketing_email'
3
+ require 'sendgrid/api/entities/response'
4
+ require 'sendgrid/api/newsletter/utils'
5
+
6
+ module Sendgrid
7
+ module API
8
+ module Newsletter
9
+ module MarketingEmails
10
+
11
+ def marketing_emails
12
+ Services.new(resource)
13
+ end
14
+
15
+ class Services < Sendgrid::API::Service
16
+ include Newsletter::Utils
17
+
18
+ # Create a new Marketing Email.
19
+ #
20
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/newsletters.html#-add
21
+ # @param marketing_email [Entities::MarketingEmail] An Entities::MarketingEmail object.
22
+ # @return [Entities::Response] An Entities::Response object.
23
+ def add(marketing_email)
24
+ perform_request(Entities::Response, 'newsletter/add.json', marketing_email.as_json)
25
+ end
26
+
27
+ # Edit an existing Marketing Email.
28
+ #
29
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/newsletters.html#-edit
30
+ # @param marketing_email [Entities::MarketingEmail] An Entities::MarketingEmail object.
31
+ # @param newname [String] The new name for the Marketing Email being edited. Optional.
32
+ # @return [Entities::Response] An Entities::Response object.
33
+ def edit(marketing_email, newname = nil)
34
+ params = marketing_email.as_json
35
+ params.merge!(:newname => newname) if newname
36
+ perform_request(Entities::Response, 'newsletter/edit.json', params)
37
+ end
38
+
39
+ # Retrieve the contents of an existing Marketing Email.
40
+ #
41
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/newsletters.html#-get
42
+ # @param marketing_email [String, Entities::MarketingEmail] An existing marketing email name or Entities::MarketingEmail object.
43
+ # @return [Entities::MarketingEmail] An Entities::MarketingEmail object.
44
+ def get(marketing_email)
45
+ params = { :name => extract_marketing_email(marketing_email) }
46
+ perform_request(Entities::MarketingEmail, 'newsletter/get.json', params)
47
+ end
48
+
49
+ # Retrieve a list of all existing Marketing Email.
50
+ #
51
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/newsletters.html#-list
52
+ # @return [Array<Entities::MarketingEmail>] An array of Entities::MarketingEmail objects.
53
+ def list
54
+ perform_request(Entities::MarketingEmail, 'newsletter/list.json')
55
+ end
56
+
57
+ # Remove an existing Marketing Email.
58
+ #
59
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/newsletters.html#-delete
60
+ # @param marketing_email [String, Entities::MarketingEmail] An existing marketing email name or Entities::MarketingEmail object.
61
+ # @return [Entities::Response] An Entities::Response object.
62
+ def delete(marketing_email)
63
+ params = { :name => extract_marketing_email(marketing_email) }
64
+ perform_request(Entities::Response, 'newsletter/delete.json', params)
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,55 @@
1
+ require 'sendgrid/api/service'
2
+ require 'sendgrid/api/entities/list'
3
+ require 'sendgrid/api/entities/response'
4
+ require 'sendgrid/api/newsletter/utils'
5
+
6
+ module Sendgrid
7
+ module API
8
+ module Newsletter
9
+ module Recipients
10
+
11
+ def recipients
12
+ Services.new(resource)
13
+ end
14
+
15
+ class Services < Sendgrid::API::Service
16
+ include Newsletter::Utils
17
+
18
+ # Assign a List to a Marketing Email.
19
+ #
20
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/recipients.html#-add
21
+ # @param list [String, Entities::List] A list name or Entities::List object.
22
+ # @param marketing_email [String, Entities::MarketingEmail] A marketing email name or Entities::MarketingEmail object.
23
+ # @return [Entities::Response] An Entities::Response object.
24
+ def add(list, marketing_email)
25
+ params = { :list => extract_listname(list), :name => extract_marketing_email(marketing_email) }
26
+ perform_request(Entities::Response, 'newsletter/recipients/add.json', params)
27
+ end
28
+
29
+ # Get all lists assigned to a particular Marketing Email.
30
+ #
31
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/recipients.html#-get
32
+ # @param marketing_email [String, Entities::MarketingEmail] A marketing email name or Entities::MarketingEmail object.
33
+ # @return [Array<Entities::List>] An array of Entities::List objects.
34
+ def get(marketing_email)
35
+ params = { :name => extract_marketing_email(marketing_email) }
36
+ perform_request(Entities::List, 'newsletter/recipients/get.json', params)
37
+ end
38
+
39
+ # Remove assigned lists from Marketing Email.
40
+ #
41
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/recipients.html#-delete
42
+ # @param list [String, Entities::List] A list name or Entities::List object.
43
+ # @param marketing_email [String, Entities::MarketingEmail] A marketing email name or Entities::MarketingEmail object.
44
+ # @return [Entities::Response] An Entities::Response object.
45
+ def delete(list, marketing_email)
46
+ params = { :list => extract_listname(list), :name => extract_marketing_email(marketing_email) }
47
+ perform_request(Entities::Response, 'newsletter/recipients/delete.json', params)
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,70 @@
1
+ require 'sendgrid/api/service'
2
+ require 'sendgrid/api/entities/schedule'
3
+ require 'sendgrid/api/entities/response'
4
+ require 'sendgrid/api/newsletter/utils'
5
+
6
+ module Sendgrid
7
+ module API
8
+ module Newsletter
9
+ module Schedule
10
+
11
+ def schedule
12
+ Services.new(resource)
13
+ end
14
+
15
+ class Services < Sendgrid::API::Service
16
+ include Newsletter::Utils
17
+
18
+ # Schedule a delivery time for an existing Marketing Email.
19
+ #
20
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/schedule.html#-add
21
+ # @param marketing_email [String, Entities::MarketingEmail] A marketing email name or Entities::MarketingEmail object.
22
+ # @param options [Hash] A customizable set of options.
23
+ # @option options [String] :at Date/Time to schedule marketing email Delivery. Date/Time must be provided in ISO 8601 format (YYYY-MM-DD HH:MM:SS+-HH:MM)
24
+ # @option options [Fixnum] :after Number of minutes until delivery should occur. Must be a positive integer.
25
+ # @return [Entities::Response] An Entities::Response object.
26
+ def add(marketing_email, options = {})
27
+ options.keep_if {|key, value| [:at, :after].include?(key) }
28
+ options[:at] = format_time(options[:at]) if options.member?(:at)
29
+ params = { :name => extract_marketing_email(marketing_email) }
30
+ params.merge!(options) if options.any?
31
+ perform_request(Entities::Response, 'newsletter/schedule/add.json', params)
32
+ end
33
+
34
+ # Retrieve the scheduled delivery time for an existing Marketing Email.
35
+ #
36
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/schedule.html#-get
37
+ # @param marketing_email [String, Entities::MarketingEmail] A marketing email name or Entities::MarketingEmail object.
38
+ # @return [Entities::Schedule] An Entities::Schedule objects.
39
+ def get(marketing_email)
40
+ params = { :name => extract_marketing_email(marketing_email) }
41
+ perform_request(Entities::Schedule, 'newsletter/schedule/get.json', params)
42
+ end
43
+
44
+ # Cancel a scheduled send for a Marketing Email.
45
+ #
46
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/schedule.html#-delete
47
+ # @param marketing_email [String, Entities::MarketingEmail] A marketing email name or Entities::MarketingEmail object.
48
+ # @return [Entities::Response] An Entities::Response object.
49
+ def delete(marketing_email)
50
+ params = { :name => extract_marketing_email(marketing_email) }
51
+ perform_request(Entities::Response, 'newsletter/schedule/delete.json', params)
52
+ end
53
+
54
+ private
55
+
56
+ def format_time(at)
57
+ case at
58
+ when ::String
59
+ at
60
+ when ::Time
61
+ at.strftime('%Y-%m-%d %H:%M:%S%:z')
62
+ end
63
+ end
64
+
65
+ end
66
+
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,80 @@
1
+ require 'sendgrid/api/service'
2
+ require 'sendgrid/api/entities/sender_address'
3
+ require 'sendgrid/api/entities/response'
4
+
5
+ module Sendgrid
6
+ module API
7
+ module Newsletter
8
+ module SenderAddresses
9
+
10
+ def sender_addresses
11
+ Services.new(resource)
12
+ end
13
+
14
+ class Services < Sendgrid::API::Service
15
+ # Create a new Sender Address.
16
+ #
17
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/sender_address.html#-add
18
+ # @param sender_address [Entities::SenderAddress] An Entities::SenderAddress object.
19
+ # @return [Entities::Response] An Entities::Response object.
20
+ def add(sender_address)
21
+ perform_request(Entities::Response, 'newsletter/identity/add.json', sender_address.as_json)
22
+ end
23
+
24
+ # Edit an existing Sender Address.
25
+ #
26
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/sender_address.html#-edit
27
+ # @param sender_address [Entities::SenderAddress] An existing Entities::SenderAddress object.
28
+ # @param new_identity [String] A new identity for the existing sender address. Optional.
29
+ # @return [Entities::Response] An Entities::Response object.
30
+ def edit(sender_address, new_identity = nil)
31
+ params = sender_address.as_json
32
+ params[:newidentity] = new_identity if new_identity
33
+ perform_request(Entities::Response, 'newsletter/identity/edit.json', params)
34
+ end
35
+
36
+ # Retrieve information associated with a particular Sender Address.
37
+ #
38
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/sender_address.html#-get
39
+ # @param sender_address [String, Entities::SenderAddress] An existing sender address identity or Entities::SenderAddress object.
40
+ # @return [Entities::SenderAddress] An Entities::SenderAddress object.
41
+ def get(sender_address)
42
+ params = { :identity => extract_identity(sender_address) }
43
+ perform_request(Entities::SenderAddress, 'newsletter/identity/get.json', params)
44
+ end
45
+
46
+ # List all Sender Addresses on your account.
47
+ #
48
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/sender_address.html#-list
49
+ # @return [Array<Entities::SenderAddress>] An array of Entities::SenderAddress objects.
50
+ def list
51
+ perform_request(Entities::SenderAddress, 'newsletter/identity/list.json')
52
+ end
53
+
54
+ # Remove a Sender Address from your account.
55
+ #
56
+ # @see http://sendgrid.com/docs/API_Reference/Marketing_Emails_API/sender_address.html#-delete
57
+ # @param sender_address [String, Entities::SenderAddress] An existing sender address identity or Entities::SenderAddress object.
58
+ # @return [Entities::Response] An Entities::Response object.
59
+ def delete(sender_address)
60
+ params = { :identity => extract_identity(sender_address) }
61
+ perform_request(Entities::Response, 'newsletter/identity/delete.json', params)
62
+ end
63
+
64
+ private
65
+
66
+ def extract_identity(sender_address)
67
+ case sender_address
68
+ when ::String
69
+ sender_address
70
+ when Entities::SenderAddress
71
+ sender_address.identity
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,34 @@
1
+ require 'sendgrid/api/entities/list'
2
+ require 'sendgrid/api/entities/marketing_email'
3
+
4
+ module Sendgrid
5
+ module API
6
+ module Newsletter
7
+ module Utils
8
+
9
+ private
10
+
11
+ # Convert the object to an Entities::List.
12
+ def extract_list(object)
13
+ Entities::List.from_object(object)
14
+ end
15
+
16
+ # Retrieve the list name.
17
+ def extract_listname(object)
18
+ extract_list(object).list
19
+ end
20
+
21
+ # Retrieve the marketing email name
22
+ def extract_marketing_email(marketing_email)
23
+ case marketing_email
24
+ when ::String
25
+ marketing_email
26
+ when Entities::MarketingEmail
27
+ marketing_email.name
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,66 @@
1
+ module Sendgrid
2
+ module API
3
+ module REST
4
+ module Errors
5
+
6
+ class Error < StandardError
7
+
8
+ class << self
9
+
10
+ def from_response(env)
11
+ status_error(env) || body_error(env)
12
+ end
13
+
14
+ private
15
+
16
+ def status_error(env)
17
+ body = env[:body]
18
+ status = env[:status].to_i
19
+ if status != 200
20
+ message = body[:error] || body[:errors].join(', ') if body.is_a?(Hash)
21
+ error_class(status).new(message)
22
+ else
23
+ nil
24
+ end
25
+ end
26
+
27
+ def body_error(env)
28
+ body = env[:body]
29
+ if body.is_a?(Hash) && body.has_key?(:error)
30
+ status, message = case body[:error]
31
+ when ::Hash
32
+ [ body[:error][:code], body[:error][:message] ]
33
+ when ::String
34
+ [ 422, body[:error] ]
35
+ end
36
+ error_class(status).new(message)
37
+ else
38
+ nil
39
+ end
40
+ end
41
+
42
+ def error_class(status)
43
+ Errors::CODES[status] || Errors::Unknown
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ class BadRequest < Error; end
51
+ class Unauthorized < Error; end
52
+ class Forbidden < Error; end
53
+ class Unknown < Error; end
54
+ class UnprocessableEntity < Error; end
55
+
56
+ CODES = {
57
+ 400 => BadRequest,
58
+ 401 => Unauthorized,
59
+ 403 => Forbidden,
60
+ 422 => UnprocessableEntity
61
+ }.freeze
62
+
63
+ end
64
+ end
65
+ end
66
+ end