objectified_environments 1.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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +29 -0
- data/Gemfile +17 -0
- data/LICENSE +21 -0
- data/README.md +196 -0
- data/Rakefile +6 -0
- data/lib/objectified_environments/base.rb +16 -0
- data/lib/objectified_environments/data_provider.rb +58 -0
- data/lib/objectified_environments/environment_builder.rb +97 -0
- data/lib/objectified_environments/errors.rb +5 -0
- data/lib/objectified_environments/rails_requirer.rb +8 -0
- data/lib/objectified_environments/railtie.rb +25 -0
- data/lib/objectified_environments/version.rb +3 -0
- data/lib/objectified_environments.rb +24 -0
- data/lib/objectified_environments_generator.rb +206 -0
- data/objectified_environments.gemspec +43 -0
- data/spec/objectified_environments/helpers/command_helpers.rb +46 -0
- data/spec/objectified_environments/helpers/rails_helper.rb +299 -0
- data/spec/objectified_environments/system/rails_integration_spec.rb +111 -0
- data/spec/objectified_environments/unit/base_spec.rb +34 -0
- data/spec/objectified_environments/unit/data_provider_spec.rb +155 -0
- data/spec/objectified_environments/unit/environment_builder_spec.rb +232 -0
- data/spec/objectified_environments/unit/errors_spec.rb +17 -0
- data/spec/objectified_environments/unit/version_spec.rb +7 -0
- metadata +149 -0
@@ -0,0 +1,206 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'objectified_environments/rails_requirer')
|
2
|
+
|
3
|
+
require 'rails/generators'
|
4
|
+
|
5
|
+
class ObjectifiedEnvironmentsGenerator < Rails::Generators::Base
|
6
|
+
def create_environment_files
|
7
|
+
needed_environments = all_environments.select { |e| (! environment_defined?(e)) }
|
8
|
+
|
9
|
+
needed_environments.each do |environment|
|
10
|
+
create_environment(environment)
|
11
|
+
end
|
12
|
+
|
13
|
+
create_superclasses_for(needed_environments)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def create_environment(environment)
|
18
|
+
target_file = File.join(objenv_dir, "#{environment.underscore}.rb")
|
19
|
+
|
20
|
+
if File.exist?(target_file)
|
21
|
+
puts "skip #{target_file}"
|
22
|
+
else
|
23
|
+
create_file(target_file) do
|
24
|
+
content_for_environment(environment)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_superclasses_for(environments)
|
30
|
+
superclasses = environments.map { |e| superclass_for_environment(e) }.uniq
|
31
|
+
superclasses -= [ "ObjectifiedEnvironments::Base" ]
|
32
|
+
superclasses = superclasses.map do |sc|
|
33
|
+
if sc =~ /::([A-Z0-9_]+)$/i
|
34
|
+
$1
|
35
|
+
else
|
36
|
+
sc
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
unless superclasses.length == 0
|
41
|
+
superclasses.each { |sc| create_environment(sc) }
|
42
|
+
create_superclasses_for(superclasses)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
DEFAULT_ENVIRONMENT_SUPERCLASS = 'Objenv::Environment'
|
47
|
+
ENVIRONMENT_HIERARCHY = {
|
48
|
+
'Environment' => "ObjectifiedEnvironments::Base",
|
49
|
+
|
50
|
+
'LocalEnvironment' => 'Environment',
|
51
|
+
'Development' => 'LocalEnvironment',
|
52
|
+
'Test' => 'LocalEnvironment',
|
53
|
+
|
54
|
+
'ProductionEnvironment' => 'Environment',
|
55
|
+
'Production' => 'ProductionEnvironment'
|
56
|
+
}
|
57
|
+
ENVIRONMENTS_MODULE = "Objenv"
|
58
|
+
|
59
|
+
CLASS_COMMENTS = { }
|
60
|
+
CLASS_COMMENTS['Environment'] = <<-EOS
|
61
|
+
# This is the root class of all of your objectified environments -- i.e., all the other
|
62
|
+
# classes in config/lib/objenv. As such, it defines the behavior of a "default" environment,
|
63
|
+
# with subclasses overriding its methods as needed.
|
64
|
+
#
|
65
|
+
# You might think that this is useless -- after all, the whole point of environments is to
|
66
|
+
# define things that *aren't* common across RAILS_ENV settings, so what could possibly go
|
67
|
+
# here? However, you'll find that several things are useful about this class:
|
68
|
+
#
|
69
|
+
# - If you define all methods here and simply call #must_implement (defined in
|
70
|
+
# ObjectifiedEnvironments::Base) in them, then you'll have an elegant template that
|
71
|
+
# immediately shows everybody exactly what varies based on environment and what they
|
72
|
+
# need to think about/override when creating a new environment.
|
73
|
+
#
|
74
|
+
# - Often, you'll want to define methods on the environment that actually include a
|
75
|
+
# little bit of functionality -- like creating and returning a Memcached client, for
|
76
|
+
# example. This can therefore be a nice place to put the structure of those methods.
|
77
|
+
# (The method that the rest of the code actually calls directly can be defined here,
|
78
|
+
# while subclasses override methods that provide crucial information -- like the name
|
79
|
+
# of the Memcached host, for example -- that this method uses to do its work.)
|
80
|
+
#
|
81
|
+
# - You may well have cases where nearly all environments behave identically, but only
|
82
|
+
# one or two vary. It therefore makes a lot of sense to put the default behavior
|
83
|
+
# here, and override as necessary only in those one or two cases.
|
84
|
+
#
|
85
|
+
# Note that the inheritance hierarchy here is only suggested and part of the
|
86
|
+
# objectified_environments generator, but not the core Gem code itself. You can change and
|
87
|
+
# rearrange things to your heart's content.
|
88
|
+
EOS
|
89
|
+
|
90
|
+
CLASS_COMMENTS['LocalEnvironment'] = <<-EOS
|
91
|
+
# This class is a descendent of the base Environment class and is inherited by Development
|
92
|
+
# and Test, the two environments that typically run locally (i.e., not on a remote server).
|
93
|
+
# It's very common that these two environments share a lot of settings in common -- hence
|
94
|
+
# the case for this class.
|
95
|
+
#
|
96
|
+
# Note that the inheritance hierarchy here is only suggested and part of the
|
97
|
+
# objectified_environments generator, but not the core Gem code itself. You can change and
|
98
|
+
# rearrange things to your heart's content.
|
99
|
+
EOS
|
100
|
+
|
101
|
+
CLASS_COMMENTS['Development'] = <<-EOS
|
102
|
+
# This class defines environment settings when RAILS_ENV == 'development'.
|
103
|
+
#
|
104
|
+
# If you have settings to define that also apply to Test, please consider placing them
|
105
|
+
# in LocalEnvironment, the superclass of this class, instead. You'll keep your code DRYer.
|
106
|
+
#
|
107
|
+
# Note that the inheritance hierarchy here is only suggested and part of the
|
108
|
+
# objectified_environments generator, but not the core Gem code itself. You can change and
|
109
|
+
# rearrange things to your heart's content.
|
110
|
+
EOS
|
111
|
+
|
112
|
+
CLASS_COMMENTS['Test'] = <<-EOS
|
113
|
+
# This class defines environment settings when RAILS_ENV == 'test'.
|
114
|
+
#
|
115
|
+
# If you have settings to define that also apply to Development, please consider placing them
|
116
|
+
# in LocalEnvironment, the superclass of this class, instead. You'll keep your code DRYer.
|
117
|
+
#
|
118
|
+
# Note that the inheritance hierarchy here is only suggested and part of the
|
119
|
+
# objectified_environments generator, but not the core Gem code itself. You can change and
|
120
|
+
# rearrange things to your heart's content.
|
121
|
+
EOS
|
122
|
+
|
123
|
+
CLASS_COMMENTS['ProductionEnvironment'] = <<-EOS
|
124
|
+
# This class is a descendent of the base Environment class and is inherited by Production.
|
125
|
+
# While this may seem a bit silly -- why have an intermediate class between Environment and
|
126
|
+
# Production at all? -- there's a good reason for it. It's exceptionally common to create
|
127
|
+
# 'production-like' environments, like 'qa', 'beta', and so on. These environments very often
|
128
|
+
# share a great number of environment settings, and this class is a perfect place to put
|
129
|
+
# that code. If you start from the beginning separating out settings that apply to "any
|
130
|
+
# environment that's like production" from "only production itself", adding these environments
|
131
|
+
# in the future gets to be a whole lot easier.
|
132
|
+
#
|
133
|
+
# Note that the inheritance hierarchy here is only suggested and part of the
|
134
|
+
# objectified_environments generator, but not the core Gem code itself. You can change and
|
135
|
+
# rearrange things to your heart's content.
|
136
|
+
EOS
|
137
|
+
|
138
|
+
CLASS_COMMENTS['Production'] = <<-EOS
|
139
|
+
# This class defines environment settings when RAILS_ENV == 'production'.
|
140
|
+
#
|
141
|
+
# Please see the comment at the top of ProductionEnvironment, as well. If you have settings
|
142
|
+
# that apply to 'any production-like environment' rather than 'only production itself', putting
|
143
|
+
# that code in ProductionEnvironment instead of in this class will likely serve you better
|
144
|
+
# in the long run.
|
145
|
+
#
|
146
|
+
# Note that the inheritance hierarchy here is only suggested and part of the
|
147
|
+
# objectified_environments generator, but not the core Gem code itself. You can change and
|
148
|
+
# rearrange things to your heart's content.
|
149
|
+
EOS
|
150
|
+
|
151
|
+
def content_for_environment(environment)
|
152
|
+
%{#{CLASS_COMMENTS[environment.camelize] || ''}
|
153
|
+
module #{ENVIRONMENTS_MODULE}
|
154
|
+
class #{environment.camelize} < #{superclass_for_environment(environment)}
|
155
|
+
# Add your own method definitions here!
|
156
|
+
end
|
157
|
+
end
|
158
|
+
}
|
159
|
+
end
|
160
|
+
|
161
|
+
def superclass_for_environment(environment)
|
162
|
+
ENVIRONMENT_HIERARCHY[environment.camelize] || DEFAULT_ENVIRONMENT_SUPERCLASS
|
163
|
+
end
|
164
|
+
|
165
|
+
def environment_defined?(environment)
|
166
|
+
target_class_name = "#{ENVIRONMENTS_MODULE}::#{environment.camelize}"
|
167
|
+
begin
|
168
|
+
target_class_name.constantize
|
169
|
+
true
|
170
|
+
rescue NameError => ne
|
171
|
+
false
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def all_environments
|
176
|
+
config_environments | [ current_environment ]
|
177
|
+
end
|
178
|
+
|
179
|
+
def config_environments
|
180
|
+
return [ ] unless File.directory?(config_environments_dir)
|
181
|
+
|
182
|
+
Dir.entries(config_environments_dir).map do |entry|
|
183
|
+
$1.downcase if entry =~ /^([A-Z0-9_]+)\.rb$/i
|
184
|
+
end.compact
|
185
|
+
end
|
186
|
+
|
187
|
+
def config_dir
|
188
|
+
@config_dir ||= File.expand_path(File.join(Rails.root, 'config'))
|
189
|
+
end
|
190
|
+
|
191
|
+
def config_environments_dir
|
192
|
+
@config_environments_dir ||= File.join(config_dir, 'environments')
|
193
|
+
end
|
194
|
+
|
195
|
+
def config_lib_dir
|
196
|
+
@config_lib_dir ||= File.join(config_dir, 'lib')
|
197
|
+
end
|
198
|
+
|
199
|
+
def objenv_dir
|
200
|
+
@objenv_dir ||= File.join(config_lib_dir, ENVIRONMENTS_MODULE.underscore)
|
201
|
+
end
|
202
|
+
|
203
|
+
def current_environment
|
204
|
+
Rails.env
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'objectified_environments/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "objectified_environments"
|
8
|
+
spec.version = ObjectifiedEnvironments::VERSION
|
9
|
+
spec.authors = ["Andrew Geweke"]
|
10
|
+
spec.email = ["andrew@geweke.org"]
|
11
|
+
spec.description = %q{Exposes your Rails.env as an object you can invoke methods on, use inheritance to structure, and otherwise use all modern powerful programming techniques on. In large projects, this can make an enormous difference in maintainability and reliability.}
|
12
|
+
spec.summary = %q{Vastly improve maintainability of your Rails.env-dependent code by using object-oriented environments.}
|
13
|
+
spec.homepage = "https://github.com/ageweke/objectified_environments"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
24
|
+
|
25
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
26
|
+
spec.add_development_dependency "activerecord-jdbcsqlite3-adapter"
|
27
|
+
else
|
28
|
+
spec.add_development_dependency "sqlite3"
|
29
|
+
end
|
30
|
+
|
31
|
+
rails_version = ENV['OBJECTIFIED_ENVIRONMENTS_RAILS_TEST_VERSION']
|
32
|
+
rails_version = rails_version.strip if rails_version
|
33
|
+
|
34
|
+
version_spec = case rails_version
|
35
|
+
when nil then [ ">= 3.0", "<= 4.99.99" ]
|
36
|
+
when 'master' then nil# { :git => 'git://github.com/rails/rails.git' }
|
37
|
+
else [ "=#{rails_version}" ]
|
38
|
+
end
|
39
|
+
|
40
|
+
if version_spec
|
41
|
+
spec.add_dependency("rails", *version_spec)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ObjectifiedEnvironments
|
2
|
+
module Specs
|
3
|
+
module Helpers
|
4
|
+
module CommandHelpers
|
5
|
+
def safe_system(command, options = { })
|
6
|
+
# Ugh. Bundler sets environment variables that causes subprocesses to use the same Bundler Gemfiles, etc.
|
7
|
+
# While I'm sure this is exactly what you want in most circumstances, it breaks our handling of different
|
8
|
+
# Rails versions. So we remove these explicitly when we execute a subprocess.
|
9
|
+
old_env = { }
|
10
|
+
ENV.keys.select { |k| k =~ /^BUNDLE_/ }.each do |key|
|
11
|
+
old_env[key] = ENV[key]
|
12
|
+
ENV.delete(key)
|
13
|
+
end
|
14
|
+
|
15
|
+
output = `#{command} 2>&1`
|
16
|
+
|
17
|
+
old_env.each { |k,v| ENV[k] = v }
|
18
|
+
|
19
|
+
successful = $?.success?
|
20
|
+
successful = false if options[:output_must_match] && (! (output =~ options[:output_must_match]))
|
21
|
+
|
22
|
+
unless successful
|
23
|
+
what_we_were_doing = options[:what_we_were_doing] || "run a command"
|
24
|
+
|
25
|
+
raise <<-EOS
|
26
|
+
Unable to #{what_we_were_doing}. In this directory:
|
27
|
+
|
28
|
+
#{Dir.pwd}
|
29
|
+
|
30
|
+
...we ran:
|
31
|
+
|
32
|
+
#{command}
|
33
|
+
|
34
|
+
...but it returned this result: #{$?.inspect}
|
35
|
+
...and gave this output:
|
36
|
+
|
37
|
+
#{output}
|
38
|
+
EOS
|
39
|
+
end
|
40
|
+
|
41
|
+
output
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,299 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'command_helpers')
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module ObjectifiedEnvironments
|
5
|
+
module Specs
|
6
|
+
module Helpers
|
7
|
+
class RailsHelper
|
8
|
+
include ObjectifiedEnvironments::Specs::Helpers::CommandHelpers
|
9
|
+
|
10
|
+
DEFAULT_RAILS_ENV = 'test'
|
11
|
+
|
12
|
+
def initialize(container_dir, options = { })
|
13
|
+
@container_dir = container_dir
|
14
|
+
@options = options
|
15
|
+
|
16
|
+
@root = nil
|
17
|
+
@version = nil
|
18
|
+
@running = false
|
19
|
+
@rails_env = (options[:rails_env] || DEFAULT_RAILS_ENV).to_s.strip
|
20
|
+
|
21
|
+
raise "This is not a valid Rails.env: #{@rails_env.inspect}" if @rails_env.length == 0
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :root, :version, :rails_env
|
25
|
+
|
26
|
+
def run!(&block)
|
27
|
+
begin
|
28
|
+
@running = true
|
29
|
+
preserve_state do
|
30
|
+
new_rails_installation!
|
31
|
+
|
32
|
+
Dir.chdir(root)
|
33
|
+
ENV['RAILS_ENV'] = rails_env
|
34
|
+
|
35
|
+
block.call(self)
|
36
|
+
|
37
|
+
FileUtils.rm_rf(File.dirname(root)) unless options[:always_keep_installation]
|
38
|
+
end
|
39
|
+
ensure
|
40
|
+
@running = false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def major_version
|
45
|
+
Integer($1) if version && version =~ /^(\d+)\./i
|
46
|
+
end
|
47
|
+
|
48
|
+
def major_and_minor_version
|
49
|
+
Float($1) if version && version =~ /^(\d+\.\d+)\./i
|
50
|
+
end
|
51
|
+
|
52
|
+
def run_script_command
|
53
|
+
if major_version <= 2
|
54
|
+
"ruby #{File.join('script', 'runner')}"
|
55
|
+
else
|
56
|
+
"rails runner"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def run_script!(script_path, *args)
|
61
|
+
opts = args.pop if args && args[-1] && args[-1].kind_of?(Hash)
|
62
|
+
opts ||= { }
|
63
|
+
|
64
|
+
must_be_running!
|
65
|
+
Dir.chdir(root) do
|
66
|
+
cmd = "bundle exec #{run_script_command} #{script_path}"
|
67
|
+
if args.length > 0
|
68
|
+
cmd << " "
|
69
|
+
cmd << args.join(" ")
|
70
|
+
end
|
71
|
+
safe_system(cmd, opts)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def run_as_script!(contents, opts = { })
|
76
|
+
script_file = opts[:script_name] || "temp_rails_script_#{rand(1_000_000)}"
|
77
|
+
script_file << ".rb" unless script_file =~ /\.rb$/i
|
78
|
+
|
79
|
+
File.open(script_file, 'w') { |f| f.puts contents }
|
80
|
+
|
81
|
+
run_script!(script_file, opts)
|
82
|
+
end
|
83
|
+
|
84
|
+
def run_generator(*args)
|
85
|
+
cmd = if major_version <= 2
|
86
|
+
"script/generate"
|
87
|
+
else
|
88
|
+
"rails generate"
|
89
|
+
end
|
90
|
+
|
91
|
+
cmd = "bundle exec #{cmd} #{args.join(" ")}"
|
92
|
+
safe_system(cmd)
|
93
|
+
end
|
94
|
+
|
95
|
+
def running?
|
96
|
+
!! @running
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
attr_reader :container_dir, :options
|
101
|
+
|
102
|
+
def must_be_running!
|
103
|
+
unless running?
|
104
|
+
raise "You can only call this while the Rails helper is running, and it isn't right now."
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def project_name
|
109
|
+
options[:project_name] || 'rails_project'
|
110
|
+
end
|
111
|
+
|
112
|
+
def preserve_state(&block)
|
113
|
+
old_dir = Dir.pwd
|
114
|
+
old_rails_env = ENV['RAILS_ENV']
|
115
|
+
|
116
|
+
begin
|
117
|
+
block.call
|
118
|
+
ensure
|
119
|
+
Dir.chdir(old_dir)
|
120
|
+
ENV['RAILS_ENV'] = old_rails_env
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def notify(string, &block)
|
125
|
+
$stdout << "[#{string}..."
|
126
|
+
$stdout.flush
|
127
|
+
|
128
|
+
block.call
|
129
|
+
|
130
|
+
$stdout << "]"
|
131
|
+
$stdout.flush
|
132
|
+
end
|
133
|
+
|
134
|
+
def create_rails_holder!
|
135
|
+
raise "No version yet?!?" unless version
|
136
|
+
out = File.join(container_dir, "rails-#{Time.now.strftime("%Y%m%d-%H%M%S")}-#{rand(1_000_000)}-#{version}")
|
137
|
+
FileUtils.mkdir_p(out)
|
138
|
+
out
|
139
|
+
end
|
140
|
+
|
141
|
+
def new_rails_installation!
|
142
|
+
fetch_rails_version!
|
143
|
+
rails_holder = create_rails_holder!
|
144
|
+
|
145
|
+
Dir.chdir(rails_holder)
|
146
|
+
create_rails_project!
|
147
|
+
|
148
|
+
@root = File.join(rails_holder, project_name)
|
149
|
+
Dir.chdir(root)
|
150
|
+
|
151
|
+
set_gemfile!
|
152
|
+
modify_database_yml_as_needed!
|
153
|
+
copy_environment_as_needed!
|
154
|
+
run_bundle_install!
|
155
|
+
|
156
|
+
check_installed_rails_version!
|
157
|
+
end
|
158
|
+
|
159
|
+
def set_gemfile!
|
160
|
+
# For reasons I don't understand at all, running 'bundle install' against our installed Rails instance
|
161
|
+
# absolutely refuses to install remote gems -- all it will do is use ones that have already been installed.
|
162
|
+
# And that means it can only safely use gems in the top-level Gemfile of whatever gem or other code we're
|
163
|
+
# running under.
|
164
|
+
#
|
165
|
+
# As a result, we overwrite the Gemfile here to contain only the reference to Rails itself, rather than
|
166
|
+
# the additional stuff that the default Rails Gemfile contains. This, despite the fact that the command_helper
|
167
|
+
# explicitly strips out all BUNDLE_* environment variables before executing a subcommand.
|
168
|
+
#
|
169
|
+
# This is unfortunate, because it would be safer to use all the default gems. If a subsequent contributor
|
170
|
+
# knows what's going on here and how to make it work, by all means, please do!
|
171
|
+
|
172
|
+
|
173
|
+
# We need to specify the version for Rails exactly like the outer Gemfile specifies it, and it might be
|
174
|
+
# from git (e.g., if we're testing against the master branch of Rails), so we can't just use #version in this
|
175
|
+
# class. Rather, we go grab the spec from Bundler.
|
176
|
+
rails_spec = Bundler.environment.specs.detect { |s| s.name == 'rails' }
|
177
|
+
raise "Can't find Bundler spec for 'rails'" unless rails_spec
|
178
|
+
rails_spec_version = case rails_spec.source
|
179
|
+
when Bundler::Source::Git then ":git => '#{rails_spec.source.uri}'"
|
180
|
+
else "'#{rails_spec.version}'"
|
181
|
+
end
|
182
|
+
|
183
|
+
gem_lines = [
|
184
|
+
"source 'http://rubygems.org'",
|
185
|
+
"gem 'rails', #{rails_spec_version}"
|
186
|
+
]
|
187
|
+
|
188
|
+
# Rails >= 3.2 uses sqlite3 by default, and won't even boot by default unless you add that to your Gemfile.
|
189
|
+
if major_and_minor_version >= 3.2
|
190
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
191
|
+
gem_lines << "gem 'activerecord-jdbcsqlite3-adapter'"
|
192
|
+
else
|
193
|
+
gem_lines << "gem 'sqlite3'"
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
if gem_lines.length > 0
|
198
|
+
notify("adding required lines to Gemfile") do
|
199
|
+
File.open("Gemfile", "w") { |f| f.puts gem_lines.join("\n") }
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# If we're using a RAILS_ENV other than one of the three defaults, then database.yml needs to contain
|
205
|
+
# configuration for that environment, even if we never actually touch the database, because certain Rails
|
206
|
+
# versions refuse to even start if it's not present.
|
207
|
+
def modify_database_yml_as_needed!
|
208
|
+
require 'yaml'
|
209
|
+
|
210
|
+
db_yaml_file = File.join('config', 'database.yml')
|
211
|
+
db_yaml = YAML.load_file(db_yaml_file)
|
212
|
+
|
213
|
+
unless db_yaml[rails_env]
|
214
|
+
notify("adding environment '#{rails_env}' to database.yml") do
|
215
|
+
test_content = db_yaml['test']
|
216
|
+
raise "No default database.yml entry for 'test'?!?" unless test_content
|
217
|
+
|
218
|
+
db_yaml[rails_env] = test_content.dup
|
219
|
+
new_yaml = YAML.dump(db_yaml)
|
220
|
+
# Get rid of the silly '---' line that YAML.dump puts at the start.
|
221
|
+
new_yaml = new_yaml.split("\n").map { |l| l unless l =~ /^\-+$/i }.compact.join("\n")
|
222
|
+
File.open(db_yaml_file, 'w') { |f| f.puts new_yaml }
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# Similarly, if we're using a non-default RAILS_ENV setting, we need to make sure we have an environment
|
228
|
+
# file for it.
|
229
|
+
def copy_environment_as_needed!
|
230
|
+
env_directory = File.join('config', 'environments')
|
231
|
+
env_file = File.join(env_directory, "#{rails_env}.rb")
|
232
|
+
|
233
|
+
unless File.exist?(env_file)
|
234
|
+
test_env_file = File.join(env_directory, "test.rb")
|
235
|
+
raise "No test.rb file at: #{test_env_file}?!?" unless File.exist?(test_env_file)
|
236
|
+
FileUtils.cp(test_env_file, env_file)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def check_installed_rails_version!
|
241
|
+
notify "checking version of Rails in our new project" do
|
242
|
+
output = run_as_script!(%{puts "Rails version: " + Rails.version},
|
243
|
+
:script_name => "check_rails_version",
|
244
|
+
:output_must_match => /^\s*Rails\s+version\s*:\s*\S+\s*$/mi,
|
245
|
+
:what_we_were_doing => "running a small script to check the version of Rails we installed")
|
246
|
+
|
247
|
+
if output =~ /^\s*Rails\s+version\s*:\s*(\S+)\s*$/mi
|
248
|
+
installed_version = $1
|
249
|
+
|
250
|
+
unless installed_version == version
|
251
|
+
raise "Whoa: the Rails project we created is reporting itself as version '#{installed_version}', but 'rails --version' gave us '#{version}'. Something is horribly wrong."
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def fetch_rails_version!
|
258
|
+
v = nil
|
259
|
+
|
260
|
+
notify "checking version of Rails we're using" do
|
261
|
+
version_text = safe_system("rails --version", :output_must_match => /^\s*Rails\s+(\d+\.\d+\.\d+)/i, :what_we_were_doing => "checking the version of Rails used by the 'rails' command")
|
262
|
+
v = if version_text =~ /^\s*Rails\s+(\d+\.\d+\.\d+)/i
|
263
|
+
$1
|
264
|
+
else
|
265
|
+
raise "Unable to determine version of Rails; we got: #{version_text.inspect}"
|
266
|
+
end
|
267
|
+
|
268
|
+
$stdout << v
|
269
|
+
$stdout.flush
|
270
|
+
end
|
271
|
+
|
272
|
+
@version = v
|
273
|
+
end
|
274
|
+
|
275
|
+
def create_rails_project_command
|
276
|
+
if major_version <= 2
|
277
|
+
"rails"
|
278
|
+
else
|
279
|
+
"rails new"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def create_rails_project!
|
284
|
+
notify "creating new Rails installation" do
|
285
|
+
safe_system("#{create_rails_project_command} #{project_name}",
|
286
|
+
:what_we_were_doing => 'create a Rails project for our spec',
|
287
|
+
:output_must_match => %r{create.*config/boot}mi)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def run_bundle_install!
|
292
|
+
notify "running 'bundle install'" do
|
293
|
+
safe_system("bundle install", :what_we_were_doing => "run 'bundle install' for our test Rails project")
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|