heroku_san 2.2.2 → 3.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Change log (curated)
2
2
 
3
+ ## v3.0.0
4
+
5
+ * New feature: support for Rack apps (e.g. Sinatra)
6
+ * Removes dependency on Rails
7
+ * New feature: deploy strategy class for customizing the :deploy target
8
+ * `Stage#deploy` calls strategy (breaks v2 API)
9
+ * `Stage#push` pushes to Heroku
10
+ * If you have a Rails app, you don't have to do anything; the gem will
11
+ automatically configure itself to use the Rails deploy strategy. See
12
+ the README for how to configure you Rack app's `Rakefile`
13
+
3
14
  ## v2.2.1
4
15
 
5
16
  * New feature: addons from [Matt Burke](https://github.com/spraints)
@@ -30,17 +41,17 @@
30
41
  * Push `REVISION` to Heroku example
31
42
  * Bug fixes
32
43
 
33
- ### New tasks
44
+ ### New tasks
34
45
 
35
- * rake logs:tail
36
- * rake shell
37
- * All HerokuSan tasks inside heroku: namespace, with aliases in the global namespace
46
+ * rake logs:tail
47
+ * rake shell
48
+ * All HerokuSan tasks inside heroku: namespace, with aliases in the global namespace
38
49
 
39
- ### New methods
50
+ ### New methods
40
51
 
41
- * `Stage#deploy`
42
- * `Stage#maintenance` can now take a block, and ensures that maintenance mode is off afterwards.
43
- * `Stage#push_config`
52
+ * `Stage#deploy`
53
+ * `Stage#maintenance` can now take a block, and ensures that maintenance mode is off afterwards.
54
+ * `Stage#push_config`
44
55
 
45
56
  ## v2.0.0
46
57
 
data/README.rdoc CHANGED
@@ -7,7 +7,7 @@ Helpful rake tasks for Heroku.
7
7
 
8
8
  === Rails 3
9
9
 
10
- Add this to your Gemfile:
10
+ Add this to your `Gemfile`:
11
11
 
12
12
  group :development do
13
13
  gem 'heroku_san'
@@ -15,11 +15,11 @@ Add this to your Gemfile:
15
15
 
16
16
  === Rails 2
17
17
 
18
- To install add the following to config/environment.rb:
18
+ To install add the following to `config/environment.rb`:
19
19
 
20
20
  config.gem 'heroku_san'
21
21
 
22
- Rake tasks are not automatically loaded from gems, so you’ll need to add the following to your Rakefile:
22
+ Rake tasks are not automatically loaded from gems, so you’ll need to add the following to your `Rakefile`:
23
23
 
24
24
  begin
25
25
  require 'heroku_san/tasks'
@@ -27,17 +27,39 @@ Rake tasks are not automatically loaded from gems, so you’ll need to add the f
27
27
  STDERR.puts "Run `rake gems:install` to install heroku_san"
28
28
  end
29
29
 
30
+ === Sinatra
31
+
32
+ Update your `Gemfile`:
33
+
34
+ group :development do
35
+ gem 'heroku_san'
36
+ end
37
+
38
+ Update your `Rakefile`:
39
+
40
+ require "bundler/setup"
41
+ require "heroku_san"
42
+ config_file = File.join(File.expand_path(File.dirname(__FILE__)), 'config', 'heroku.yml')
43
+ HerokuSan.project = HerokuSan::Project.new(config_file, :deploy => HerokuSan::Deploy::Sinatra)
44
+ load "heroku_san/tasks.rb"
45
+
30
46
  == Configure
31
47
 
32
- In config/heroku.yml you will need to add the Heroku apps that you would like to attach to this project. You can generate this file by running:
48
+ In `config/heroku.yml` you will need to add the Heroku apps that you would like to attach to this project. You can generate this file by running:
49
+
50
+ === Rails 3
51
+
52
+ rails generate heroku_san
53
+
54
+ === Everything else
33
55
 
34
56
  rake heroku:create_config
35
57
 
36
- Customize the file for your project. If this is a fresh project, heroku_san can create all the applications for you, and set each one's RACK_ENV.
58
+ Customize the file for your project. If this is a fresh project, `heroku_san` can create all the applications for you, and set each one's RACK_ENV.
37
59
 
38
60
  rake all heroku:create heroku:rack_env
39
61
 
40
- Configure your Heroku apps according to config/heroku.yml by running:
62
+ Configure your Heroku apps according to `config/heroku.yml` by running:
41
63
 
42
64
  rake all heroku:config
43
65
 
@@ -55,7 +77,7 @@ is additive, you can easily select which servers to run a command on.
55
77
  rake demo staging restart
56
78
 
57
79
  A special rake task 'all' is created that causes any further commands to
58
- execute on all heroku apps.
80
+ execute on all Heroku apps.
59
81
 
60
82
  Manipulate collaborators on all this project's apps (prompts for email
61
83
  address):
@@ -139,4 +161,4 @@ Issue Tracker:: http://github.com/fastestforward/heroku_san/issues
139
161
 
140
162
  == License
141
163
 
142
- License:: Copyright (c) 2009-2012 Elijah Miller <mailto:elijah.miller@gmail.com>, released under the MIT license.
164
+ License:: Copyright (c) 2008-2012 Elijah Miller <mailto:elijah.miller@gmail.com>, released under the MIT license.
@@ -1,7 +1,7 @@
1
1
  Feature: Command Line
2
2
 
3
3
  Background:
4
- Given I run `rails new heroku_san_test -O`
4
+ Given I run `rails new heroku_san_test --quiet --force --database=postgresql --skip-bundle --skip-javascript --skip-test-unit --skip-sprockets`
5
5
  And I cd to "heroku_san_test"
6
6
  And I overwrite "Gemfile" with:
7
7
  """
@@ -20,7 +20,8 @@ Feature: Command Line
20
20
  demo:
21
21
  app: awesomeapp-demo
22
22
  development:
23
- app:
23
+ app:
24
+
24
25
  """
25
26
 
26
27
  When I run `rake --trace heroku:apps:local`
@@ -72,3 +73,11 @@ Feature: Command Line
72
73
  When I run `rake EDITOR=echo --trace heroku:create_config`
73
74
  And the output should match /Copied example config to ".*.config.heroku.yml"/
74
75
  And the output should match /^echo .*.config.heroku.yml$/
76
+
77
+ Scenario: rails generate heroku_san
78
+ When I run `rails generate`
79
+ Then the output should not contain "Could not find generator heroku_san."
80
+ And the output should contain "HerokuSan:\n heroku_san"
81
+ When I run `rails generate heroku_san`
82
+ Then a file named "config/heroku.yml" should exist
83
+ And the output should contain "create config/heroku.yml"
@@ -14,7 +14,7 @@ Feature: Extended config
14
14
  And I run `git add .`
15
15
  And I run `git commit -m 'Initial commit'`
16
16
  And I cd to ".."
17
- Given I run `rails new heroku_san_test -O`
17
+ Given I run `rails new heroku_san_test --quiet --force --database=postgresql --skip-bundle --skip-javascript --skip-test-unit --skip-sprockets`
18
18
  And I cd to "heroku_san_test"
19
19
  And I overwrite "Gemfile" with:
20
20
  """
@@ -12,9 +12,31 @@ Feature: heroku_san can control a project on Heroku
12
12
  And I run bundle install
13
13
  Then rake reports that the heroku: tasks are available
14
14
 
15
- Scenario: Manipulates the project on Heroku
15
+ Scenario: Manipulates a Rails app on Heroku
16
16
  Given I have a new Rails project
17
17
  When I am in the project directory
18
+ And I commit any changes with "Initial commit"
19
+ And I add heroku_san to the Gemfile
20
+ And I run bundle install
21
+ And I generate a new config file
22
+ And I create my project on Heroku
23
+ And I list the remote configuration
24
+ And I curl the app home page
25
+ And I configure my project
26
+ And I turn maintenance on
27
+ And I generate a scaffold
28
+ And I commit any changes with "Added droids"
29
+ And I deploy my project
30
+ And I turn maintenance off
31
+ And I restart my project
32
+ And I list all apps on Heroku
33
+ And I install an addon
34
+ Then heroku_san is green
35
+
36
+ Scenario: Manipulates a Sinatra app on Heroku
37
+ Given I have a new Sinatra project
38
+ When I am in the project directory
39
+ And I commit any changes with "Initial commit"
18
40
  And I add heroku_san to the Gemfile
19
41
  And I run bundle install
20
42
  And I create a new config/heroku.yml file
@@ -23,6 +45,8 @@ Feature: heroku_san can control a project on Heroku
23
45
  And I curl the app home page
24
46
  And I configure my project
25
47
  And I turn maintenance on
48
+ And I add a new action
49
+ And I commit any changes with "Added droids"
26
50
  And I deploy my project
27
51
  And I turn maintenance off
28
52
  And I restart my project
@@ -1,62 +1,102 @@
1
1
  World(Aruba::Api)
2
+ require 'active_support/core_ext/string/strip'
2
3
 
3
4
  Given /^I have a new Rails project$/ do
4
- cmd = "rails new heroku_san_test --quiet --force --database=postgresql --skip-bundle --skip-javascript --skip-test-unit --skip-sprockets"
5
+ cmd = "rails new test_app --quiet --force --database=postgresql --skip-bundle --skip-javascript --skip-test-unit --skip-sprockets"
5
6
  run_simple unescape(cmd)
6
7
  end
7
8
 
9
+ Given /^I have a new Sinatra project$/ do
10
+ create_dir 'test_app/config'
11
+ write_file 'test_app/app.rb', <<EOT.strip_heredoc
12
+ require 'sinatra'
13
+
14
+ get '/' do
15
+ 'Hello, world.'
16
+ end
17
+ EOT
18
+
19
+ write_file 'test_app/config.ru', <<EOT.strip_heredoc
20
+ require './app'
21
+ run Sinatra::Application
22
+ EOT
23
+
24
+ write_file 'test_app/Gemfile', <<EOT.strip_heredoc
25
+ source 'http://rubygems.org'
26
+ gem 'sinatra'
27
+ EOT
28
+
29
+ write_file 'test_app/Rakefile', <<EOT.strip_heredoc
30
+ require "bundler/setup"
31
+ require "heroku_san"
32
+ config_file = File.join(File.expand_path(File.dirname(__FILE__)), 'config', 'heroku.yml')
33
+ HerokuSan.project = HerokuSan::Project.new(config_file, :deploy => HerokuSan::Deploy::Sinatra)
34
+ load "heroku_san/tasks.rb"
35
+ EOT
36
+
37
+ end
38
+
8
39
  When /^I am in the project directory$/ do
9
- cd '/heroku_san_test'
40
+ cd '/test_app'
41
+ run_simple 'git init .'
42
+ end
43
+
44
+ When /^I commit any changes with "(.*)"$/ do |message|
45
+ run_simple 'git add .'
46
+ run_simple "git commit -m '#{message}'"
10
47
  end
11
48
 
12
49
  When /^I add heroku_san to the Gemfile$/ do
13
- append_to_file 'Gemfile', <<EOT
50
+ append_to_file 'Gemfile', <<EOT.strip_heredoc
14
51
  group :development, :test do
15
52
  gem 'heroku_san', :path => '../../../.'
16
53
  end
17
54
  EOT
55
+
18
56
  end
19
57
 
20
58
  When /^I run bundle install$/ do
21
59
  use_clean_gemset 'heroku_san_test'
22
60
  run_simple 'bundle install --quiet'
23
- write_file '.rvmrc', "rvm use default@heroku_san_test\n"
24
61
  end
25
62
 
26
63
  Then /^rake reports that the heroku: tasks are available$/ do
27
- run_simple 'rake -T heroku:'
28
- output = stdout_from 'rake -T heroku:'
64
+ run_simple 'bundle exec rake -T heroku:'
65
+ output = stdout_from 'bundle exec rake -T heroku:'
29
66
  assert_partial_output 'rake heroku:apps', output
30
67
  end
31
68
 
69
+ When /^I generate a new config file$/ do
70
+ run_simple 'bundle exec rails generate heroku_san'
71
+ output = stdout_from 'bundle exec rails generate heroku_san'
72
+ assert_partial_output 'create config/heroku.yml', output
73
+ overwrite_simple_config_file
74
+ end
75
+
32
76
  When /^I create a new config\/heroku\.yml file$/ do
33
- run_simple 'rake heroku:create_config'
34
- output = stdout_from 'rake heroku:create_config'
77
+ run_simple 'bundle exec rake heroku:create_config'
78
+ output = stdout_from 'bundle exec rake heroku:create_config'
35
79
  assert_matching_output %q{Copied example config to ".*.config.heroku.yml"}, output
36
80
  assert_matching_output %q{Please edit ".*.config.heroku.yml" with your application's settings.}, output
37
-
38
- overwrite_file 'config/heroku.yml', <<EOT
39
- ---
40
- test_app:
41
- EOT
81
+ overwrite_simple_config_file
42
82
  end
43
83
 
44
84
  When /^I create my project on Heroku$/ do
45
- cmd = 'rake test_app heroku:create'
85
+ cmd = 'bundle exec rake test_app heroku:create'
46
86
  run_simple unescape(cmd)
47
87
  output = stdout_from cmd
48
88
  assert_matching_output %q{test_app: Created ([\w-]+)}, output
49
89
 
50
90
  @app = output.match(/test_app: Created ([\w-]+)/)[1]
51
- overwrite_file 'config/heroku.yml', <<EOT
52
- ---
53
- test_app:
54
- app: #{@app}
91
+ overwrite_file 'config/heroku.yml', <<EOT.strip_heredoc
92
+ ---
93
+ test_app:
94
+ app: #{@app}
55
95
  EOT
56
96
  end
57
97
 
58
98
  When /^I list the remote configuration$/ do
59
- cmd = 'rake test_app heroku:config:list'
99
+ cmd = 'bundle exec rake test_app heroku:config:list'
60
100
  run_simple unescape(cmd)
61
101
  output = stdout_from cmd
62
102
  assert_partial_output "APP_NAME: #{@app}", output
@@ -73,22 +113,22 @@ When /^I curl the app home page$/ do
73
113
  end
74
114
 
75
115
  When /^I configure my project$/ do
76
- overwrite_file 'config/heroku.yml', <<EOT
77
- ---
78
- test_app:
79
- app: #{@app}
80
- config:
81
- DROIDS: marvin
116
+ overwrite_file 'config/heroku.yml', <<EOT.strip_heredoc
117
+ ---
118
+ test_app:
119
+ app: #{@app}
120
+ config:
121
+ DROIDS: marvin
82
122
  EOT
83
- cmd = 'rake test_app heroku:config'
123
+ cmd = 'bundle exec rake test_app heroku:config'
84
124
  run_simple cmd
85
125
  output = stdout_from cmd
86
126
  assert_partial_output 'DROIDS: marvin', output
87
127
  end
88
128
 
89
129
  When /^I turn maintenance on$/ do
90
- run_simple 'rake test_app heroku:maintenance_on'
91
- output = stdout_from 'rake test_app heroku:maintenance_on'
130
+ run_simple 'bundle exec rake test_app heroku:maintenance_on'
131
+ output = stdout_from 'bundle exec rake test_app heroku:maintenance_on'
92
132
  assert_partial_output 'test_app: Maintenance mode enabled.', output
93
133
 
94
134
  run_simple @curl
@@ -97,26 +137,35 @@ When /^I turn maintenance on$/ do
97
137
  end
98
138
 
99
139
  When /^I turn maintenance off$/ do
100
- run_simple 'rake test_app heroku:maintenance_off'
101
- output = stdout_from 'rake test_app heroku:maintenance_off'
140
+ run_simple 'bundle exec rake test_app heroku:maintenance_off'
141
+ output = stdout_from 'bundle exec rake test_app heroku:maintenance_off'
102
142
  assert_partial_output 'test_app: Maintenance mode disabled.', output
103
143
  assert_app_is_running
104
144
  end
105
145
 
106
146
  When /^I restart my project$/ do
107
- run_simple 'rake test_app heroku:restart'
108
- output = stdout_from 'rake test_app heroku:restart'
147
+ run_simple 'bundle exec rake test_app heroku:restart'
148
+ output = stdout_from 'bundle exec rake test_app heroku:restart'
109
149
  assert_partial_output 'test_app: Restarted.', output
110
150
  assert_app_is_running
111
151
  end
112
152
 
113
- When /^I deploy my project$/ do
114
- run_simple 'git init .'
115
- run_simple 'rails generate scaffold droid'
153
+ When /^I generate a scaffold$/ do
154
+ run_simple 'bundle exec rails generate scaffold droid'
116
155
  append_to_file 'app/views/droids/index.html.erb', %Q{\n<div><code><%= ENV['DROIDS'] -%></code></div>\n}
117
- run_simple 'git add .'
118
- run_simple 'git commit -m "Initial commit"'
119
- run_simple 'rake test_app deploy'
156
+ end
157
+
158
+ When /^I add a new action$/ do
159
+ append_to_file 'app.rb', <<'EOT'.strip_heredoc
160
+
161
+ get '/droids' do
162
+ "<div><code>#{ENV['DROIDS']}</code></div>"
163
+ end
164
+ EOT
165
+ end
166
+
167
+ When /^I deploy my project$/ do
168
+ run_simple 'bundle exec rake test_app deploy'
120
169
  assert_partial_output "http://#{@app}.heroku.com deployed to Heroku", all_output
121
170
  end
122
171
 
@@ -124,8 +173,8 @@ When /^I list all apps on Heroku$/ do
124
173
  sha = in_current_dir do
125
174
  `git rev-parse HEAD`.chomp
126
175
  end
127
- run_simple 'rake heroku:apps'
128
- output = stdout_from 'rake heroku:apps'
176
+ run_simple 'bundle exec rake heroku:apps'
177
+ output = stdout_from 'bundle exec rake heroku:apps'
129
178
  assert_partial_output "test_app is shorthand for the Heroku app #{@app} located at:", output
130
179
  assert_partial_output "git@heroku.com:#{@app}.git", output
131
180
  assert_partial_output "@ #{sha} master", output
@@ -133,14 +182,15 @@ end
133
182
 
134
183
  When /^I install an addon$/ do
135
184
  # Install the campfire addon.
136
- overwrite_file 'config/heroku.yml', <<END_CONFIG
137
- test_app:
138
- app: #{@app}
139
- addons:
140
- - deployhooks:campfire
185
+ overwrite_file 'config/heroku.yml', <<END_CONFIG.strip_heredoc
186
+ test_app:
187
+ app: #{@app}
188
+ addons:
189
+ - deployhooks:campfire
141
190
  END_CONFIG
142
- run_simple 'rake test_app heroku:addons'
143
- output = stdout_from 'rake test_app heroku:addons'
191
+
192
+ run_simple 'bundle exec rake test_app heroku:addons'
193
+ output = stdout_from 'bundle exec rake test_app heroku:addons'
144
194
  # The output should show the default addons...
145
195
  assert_partial_output "shared-database:5mb", output
146
196
  # ... and the new one ...
@@ -150,7 +200,7 @@ END_CONFIG
150
200
  end
151
201
 
152
202
  Then /^heroku_san is green$/ do
153
- run_simple "heroku apps:destroy #{@app} --confirm #{@app}"
203
+ run_simple "bundle exec heroku apps:destroy #{@app} --confirm #{@app}"
154
204
  end
155
205
 
156
206
  def assert_app_is_running
@@ -158,3 +208,11 @@ def assert_app_is_running
158
208
  output = stdout_from @curl + "/droids"
159
209
  assert_partial_output %Q{<code>marvin</code>}, output
160
210
  end
211
+
212
+ def overwrite_simple_config_file
213
+ overwrite_file 'config/heroku.yml', <<EOT.strip_heredoc
214
+ ---
215
+ test_app:
216
+ EOT
217
+
218
+ end
data/heroku_san.gemspec CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.add_runtime_dependency(%q<heroku>, ['>= 2'])
27
27
  s.add_runtime_dependency(%q<heroku-api>, ['>= 0.1.2'])
28
28
  s.add_runtime_dependency(%q<rake>)
29
+ s.add_runtime_dependency('activesupport')
29
30
  s.add_development_dependency(%q<aruba>)
30
31
  s.add_development_dependency(%q<cucumber>)
31
32
  s.add_development_dependency(%q<rake>)
@@ -0,0 +1,7 @@
1
+ class HerokuSanGenerator < Rails::Generators::Base
2
+ source_root File.expand_path("../../templates", __FILE__)
3
+
4
+ def copy_initializer_file
5
+ copy_file "heroku.example.yml", "config/heroku.yml"
6
+ end
7
+ end
@@ -0,0 +1,14 @@
1
+ module HerokuSan
2
+ module Deploy
3
+ class Base
4
+ def initialize(stage, args = {})
5
+ @stage = stage
6
+ @args = args
7
+ end
8
+
9
+ def deploy
10
+ @stage.push(@args[:commit], @args[:force])
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ require 'heroku_san/deploy/base'
2
+
3
+ module HerokuSan
4
+ module Deploy
5
+ class Rails < HerokuSan::Deploy::Base
6
+ def deploy
7
+ $stderr.puts super
8
+ $stderr.puts @stage.rake('db:migrate')
9
+ $stderr.puts @stage.restart
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ require 'heroku_san/deploy/base'
2
+
3
+ module HerokuSan
4
+ module Deploy
5
+ class Sinatra < HerokuSan::Deploy::Base
6
+ def deploy
7
+ $stderr.puts super
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,16 +1,19 @@
1
+ require 'active_support/core_ext/string/inflections'
2
+ require 'active_support/core_ext/hash/slice'
3
+
1
4
  module HerokuSan
2
5
  class Project
3
6
  attr_reader :config_file
4
7
 
5
8
  include Git
6
9
 
7
- def initialize(config_file)
10
+ def initialize(config_file, options = {})
8
11
  @apps = []
9
12
  @config_file = config_file
10
13
  @app_settings = {}
11
14
  config = parse(@config_file)
12
15
  config.each do |stage, settings|
13
- @app_settings[stage] = HerokuSan::Stage.new(stage, settings)
16
+ @app_settings[stage] = HerokuSan::Stage.new(stage, settings.merge(options.slice(:deploy)))
14
17
  end
15
18
  end
16
19
 
@@ -1,6 +1,8 @@
1
1
  require 'heroku'
2
2
  require 'heroku/api'
3
3
  require 'json'
4
+ require 'active_support/core_ext/object/blank'
5
+ require 'active_support/core_ext/hash/keys'
4
6
 
5
7
  MOCK = false unless defined?(MOCK)
6
8
 
@@ -10,8 +12,11 @@ module HerokuSan
10
12
  include Git
11
13
 
12
14
  def initialize(stage, options = {})
15
+ default_options = {
16
+ 'deploy' => HerokuSan::Deploy::Rails
17
+ }
13
18
  @name = stage
14
- @options = options
19
+ @options = default_options.merge(options.stringify_keys)
15
20
  end
16
21
 
17
22
  def heroku
@@ -50,7 +55,7 @@ module HerokuSan
50
55
  end
51
56
  end
52
57
 
53
- def deploy(sha = nil, force = false)
58
+ def push(sha = nil, force = false)
54
59
  sha ||= git_parsed_tag(tag)
55
60
  git_push(sha, repo, force ? %w[--force] : [])
56
61
  end
@@ -60,6 +65,11 @@ module HerokuSan
60
65
  restart
61
66
  end
62
67
 
68
+ def deploy(args = {})
69
+ strategy = @options['deploy'].new(self, args)
70
+ strategy.deploy
71
+ end
72
+
63
73
  def rake(*args)
64
74
  run 'rake', args.join(' ')
65
75
  # heroku.rake app, args.join(' ')
@@ -79,7 +89,7 @@ module HerokuSan
79
89
  end
80
90
  end
81
91
 
82
- def create # DEPREC?
92
+ def create
83
93
  params = Hash[@options.select{|k,v| %w[app stack].include? k}].stringify_keys
84
94
  params['name'] = params.delete('app')
85
95
  response = heroku.post_app(params)
@@ -134,19 +144,3 @@ module HerokuSan
134
144
  end
135
145
  end
136
146
  end
137
-
138
- # from ActiveSupport
139
- class Hash
140
- # Return a new hash with all keys converted to strings.
141
- def stringify_keys
142
- dup.stringify_keys!
143
- end
144
-
145
- # Destructively convert all keys to strings.
146
- def stringify_keys!
147
- keys.each do |key|
148
- self[key.to_s] = delete(key)
149
- end
150
- self
151
- end
152
- end