railsapp_factory 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +43 -0
- data/.travis.yml +36 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +168 -0
- data/Rakefile +8 -0
- data/lib/railsapp_factory/build_error.rb +7 -0
- data/lib/railsapp_factory/build_methods.rb +141 -0
- data/lib/railsapp_factory/class_methods.rb +155 -0
- data/lib/railsapp_factory/helper_methods.rb +118 -0
- data/lib/railsapp_factory/run_in_app_methods.rb +157 -0
- data/lib/railsapp_factory/server_methods.rb +82 -0
- data/lib/railsapp_factory/string_inquirer.rb +26 -0
- data/lib/railsapp_factory/template_methods.rb +54 -0
- data/lib/railsapp_factory/version.rb +3 -0
- data/lib/railsapp_factory.rb +50 -0
- data/railsapp_factory.gemspec +25 -0
- data/spec/railsapp_factory/class_methods_spec.rb +121 -0
- data/spec/railsapp_factory/helper_methods_spec.rb +124 -0
- data/spec/railsapp_factory/string_inquirer_spec.rb +24 -0
- data/spec/railsapp_factory/template_methods_spec.rb +98 -0
- data/spec/railsapp_factory_spec.rb +387 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/templates/add-file.rb +6 -0
- data/spec/templates/add-ruby_version-controller.rb +9 -0
- data/spec/templates/add-yet-another-file.rb +6 -0
- data/templates/add_json_pure.rb +5 -0
- data/templates/add_necessary_gems.rb +55 -0
- data/templates/use_bundler_with_rails23.rb +187 -0
- metadata +157 -0
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'railsapp_factory/string_inquirer'
|
3
|
+
|
4
|
+
class RailsappFactory
|
5
|
+
module HelperMethods
|
6
|
+
|
7
|
+
attr_writer :logger
|
8
|
+
|
9
|
+
attr_accessor :gem_source, :db, :timeout, :logger
|
10
|
+
|
11
|
+
def override_ENV
|
12
|
+
@override_ENV ||= {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def logger
|
16
|
+
@logger ||= Logger.new(STDERR)
|
17
|
+
end
|
18
|
+
|
19
|
+
def uri(path = '', query_args = {})
|
20
|
+
URI(self.url(path, query_args))
|
21
|
+
end
|
22
|
+
|
23
|
+
def url(path = '', query_args = {})
|
24
|
+
"http://127.0.0.1:#{self.port}/" + path.to_s.sub(/^\//, '') + self.class.encode_query(query_args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def env=(value)
|
28
|
+
self.override_ENV['RAILS_ENV'] = value
|
29
|
+
self.override_ENV['RACK_ENV'] = value
|
30
|
+
self.env
|
31
|
+
end
|
32
|
+
|
33
|
+
def env
|
34
|
+
rails_env = self.override_ENV['RAILS_ENV'] || self.override_ENV['RACK_ENV'] || 'test'
|
35
|
+
@_env = nil unless @_env.to_s == rails_env
|
36
|
+
@_env ||= RailsappFactory::StringInquirer.new(rails_env)
|
37
|
+
end
|
38
|
+
|
39
|
+
#def rubies(rails_v = @version)
|
40
|
+
# self.class.rubies(rails_v)
|
41
|
+
#end
|
42
|
+
|
43
|
+
def alive?
|
44
|
+
if @pid
|
45
|
+
begin
|
46
|
+
Process.kill(0, @pid)
|
47
|
+
self.logger.debug "Process #{@pid} is alive"
|
48
|
+
true
|
49
|
+
rescue Errno::EPERM
|
50
|
+
self.logger.warning "Process #{@pid} has changed uid - we will not be able to signal it to finish"
|
51
|
+
true # changed uid
|
52
|
+
rescue Errno::ESRCH
|
53
|
+
self.logger.debug "Process #{@pid} not found"
|
54
|
+
false # NOT running
|
55
|
+
rescue Exception => ex
|
56
|
+
self.logger.warning "Process #{@pid} in unknown state: #{ex}"
|
57
|
+
nil # Unable to determine status
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# get backtrace except for this method
|
65
|
+
|
66
|
+
def get_backtrace
|
67
|
+
raise 'get backtrace'
|
68
|
+
rescue => ex
|
69
|
+
trace = ex.backtrace
|
70
|
+
trace.shift
|
71
|
+
trace
|
72
|
+
end
|
73
|
+
|
74
|
+
def see_log(file)
|
75
|
+
self.logger.debug? ? '' : " - see #{file}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def append_log(file)
|
79
|
+
self.logger.debug? ? '' : " >> #{file} 2>&1"
|
80
|
+
end
|
81
|
+
|
82
|
+
def bundle_command
|
83
|
+
"#{self.class.ruby_command_prefix(self.using)} bundle"
|
84
|
+
end
|
85
|
+
|
86
|
+
def ruby_command(bundled = true)
|
87
|
+
"#{self.class.ruby_command_prefix(self.using)} #{bundled ? 'bundle exec' : ''} ruby"
|
88
|
+
end
|
89
|
+
|
90
|
+
def find_command(script_name, rails_arg)
|
91
|
+
result = Dir.chdir(root) do
|
92
|
+
if File.exists?("script/#{script_name}")
|
93
|
+
"#{bundle_command} exec script/#{script_name}"
|
94
|
+
elsif File.exists?('script/rails')
|
95
|
+
"#{bundle_command} exec script/rails #{rails_arg}"
|
96
|
+
else
|
97
|
+
"#{ruby_command(false)} .bundle/bin/rails #{rails_arg}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
self.logger.info("find_command(#{script_name.inspect}, #{rails_arg.inspect}) returned #{result.inspect}")
|
101
|
+
result
|
102
|
+
end
|
103
|
+
|
104
|
+
def generate_command
|
105
|
+
find_command('generate', 'generate')
|
106
|
+
end
|
107
|
+
|
108
|
+
def runner_command
|
109
|
+
find_command('runner', 'runner')
|
110
|
+
end
|
111
|
+
|
112
|
+
def server_command
|
113
|
+
find_command('server', 'server')
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'yaml'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
class RailsappFactory
|
7
|
+
module RunInAppMethods
|
8
|
+
|
9
|
+
def using
|
10
|
+
@using ||= nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def use(ruby_v)
|
14
|
+
if block_given?
|
15
|
+
begin
|
16
|
+
orig_using = self.using
|
17
|
+
@using = ruby_v.to_s
|
18
|
+
result = yield
|
19
|
+
ensure
|
20
|
+
@using = orig_using
|
21
|
+
end
|
22
|
+
else
|
23
|
+
result = @using = ruby_v.to_s
|
24
|
+
end
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
def in_app(in_directory = built? ? root : base_dir)
|
29
|
+
Dir.chdir(in_directory) do
|
30
|
+
setup_env do
|
31
|
+
if @timeout > 0
|
32
|
+
Timeout.timeout(@timeout) do
|
33
|
+
yield
|
34
|
+
end
|
35
|
+
else
|
36
|
+
yield
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# returns value from ruby command run in ruby, serialized via to_json to keep to simple values
|
43
|
+
def ruby_eval(expression, serialize_with = :json, evaluate_with = :ruby)
|
44
|
+
result = nil
|
45
|
+
|
46
|
+
evaluate_with = :runner if RUBY_VERSION =~ /^1\.8/ and serialize_with == :json
|
47
|
+
script_dir = File.join(base_dir, 'scripts')
|
48
|
+
FileUtils.mkdir_p script_dir
|
49
|
+
script_file = Tempfile.new(["#{evaluate_with}_", '.rb'], script_dir)
|
50
|
+
expression_file = script_file.path
|
51
|
+
output_file = "#{expression_file.sub(/\.rb$/, '')}.output"
|
52
|
+
script_contents = <<-EOF
|
53
|
+
require '#{serialize_with}'; value = begin; def value_of_expression; #{expression}
|
54
|
+
end
|
55
|
+
{ 'value' => value_of_expression }
|
56
|
+
rescue Exception => ex
|
57
|
+
{ 'exception' => ex.class.to_s, 'message' => ex.message, 'backtrace' => ex.backtrace }
|
58
|
+
end
|
59
|
+
File.open('#{output_file}', 'w') do |_script_output|
|
60
|
+
_script_output.puts value.to_#{serialize_with}
|
61
|
+
end
|
62
|
+
EOF
|
63
|
+
script_file.puts script_contents
|
64
|
+
script_file.close
|
65
|
+
self.logger.debug "#{evaluate_with}_eval running script #{expression_file} #{see_log('eval.log')}"
|
66
|
+
command = if evaluate_with == :ruby
|
67
|
+
ruby_command(bundled?)
|
68
|
+
elsif evaluate_with == :runner
|
69
|
+
runner_command
|
70
|
+
else
|
71
|
+
raise ArgumentError.new('invalid evaluate_with argument')
|
72
|
+
end
|
73
|
+
system_in_app "sh -xc '#{command} #{expression_file}' #{append_log('eval.log')}"
|
74
|
+
self.logger.info("#{evaluate_with}_eval of #{expression} returned exit status of #{$?} - #{expression_file}")
|
75
|
+
if File.size?(output_file)
|
76
|
+
res = if serialize_with == :json
|
77
|
+
JSON.parse(File.read(output_file))
|
78
|
+
else
|
79
|
+
YAML.load_file(output_file)
|
80
|
+
end
|
81
|
+
FileUtils.rm_f output_file
|
82
|
+
FileUtils.rm_f expression_file
|
83
|
+
if res.include? 'value'
|
84
|
+
result = res['value']
|
85
|
+
elsif res.include? 'exception'
|
86
|
+
result = begin
|
87
|
+
Object.const_get(res['exception']).new(res['message'] || 'Unknown')
|
88
|
+
rescue
|
89
|
+
RuntimeError.new("#{res['exception']}: #{res['message']}")
|
90
|
+
end
|
91
|
+
result.set_backtrace(res['backtrace'] + get_backtrace) if res['backtrace']
|
92
|
+
raise result
|
93
|
+
end
|
94
|
+
else
|
95
|
+
result = ArgumentError.new("unknown error, possibly a syntax error, (missing #{output_file}) #{see_log('eval.log')} - #{expression_file} contains:\n#{command}")
|
96
|
+
raise result
|
97
|
+
end
|
98
|
+
result
|
99
|
+
end
|
100
|
+
|
101
|
+
# returns value from expression passed to runner, serialized via to_json to keep to simple values
|
102
|
+
def rails_eval(expression, serialize_with = :json)
|
103
|
+
ruby_eval(expression, serialize_with, :runner)
|
104
|
+
end
|
105
|
+
|
106
|
+
def shell_eval(*args)
|
107
|
+
arg = prepend_ruby_version_command_to_arg(args)
|
108
|
+
in_app { IO.popen(arg, 'r').read }
|
109
|
+
end
|
110
|
+
|
111
|
+
def prepend_ruby_version_command_to_arg(args)
|
112
|
+
arg = args.count == 1 ? args.first : args
|
113
|
+
command_prefix = RailsappFactory.ruby_command_prefix(@using)
|
114
|
+
if arg.kind_of?(Array)
|
115
|
+
arg = command_prefix.split(' ') + arg
|
116
|
+
else
|
117
|
+
arg = "#{command_prefix} #{arg}"
|
118
|
+
end
|
119
|
+
self.logger.info("prepend_ruby_version_command_to_arg returned: #{arg.inspect}")
|
120
|
+
arg
|
121
|
+
end
|
122
|
+
|
123
|
+
def system_in_app(*args)
|
124
|
+
arg = prepend_ruby_version_command_to_arg(args)
|
125
|
+
in_app { Kernel.system(arg) }
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def setup_env
|
131
|
+
result = nil
|
132
|
+
Bundler.with_clean_env do
|
133
|
+
self.override_ENV.each do |key, value|
|
134
|
+
unless %w{RAILS_ENV RACK_ENV}.include? key
|
135
|
+
self.logger.debug "setup_env: setting ENV[#{key.inspect}] = #{value.inspect}"
|
136
|
+
ENV[key] = value
|
137
|
+
end
|
138
|
+
end
|
139
|
+
rails_env = self.env.to_s
|
140
|
+
ENV['RAILS_ENV'] = ENV['RACK_ENV'] = rails_env
|
141
|
+
self.logger.debug "setup_env: setting ENV['RAILS_ENV'] = ENV['RACK_ENV'] = #{rails_env.inspect}"
|
142
|
+
ENV['RAILS_LTS'] = if @version =~ /lts/ then
|
143
|
+
'true'
|
144
|
+
elsif @version =~ /^2\.3/
|
145
|
+
'false'
|
146
|
+
else
|
147
|
+
nil
|
148
|
+
end
|
149
|
+
ENV['GEM_SOURCE'] = @gem_source if ENV['RAILS_LTS']
|
150
|
+
self.logger.debug "setup_env: setting ENV['GEM_SOURCE'] = #{@gem_source.inspect}, ENV['RAILS_LTS'] = #{ENV['RAILS_LTS'].inspect}" if ENV['RAILS_LTS']
|
151
|
+
result = yield
|
152
|
+
end
|
153
|
+
result
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
class RailsappFactory
|
5
|
+
module ServerMethods
|
6
|
+
|
7
|
+
attr_reader :pid
|
8
|
+
attr_reader :port
|
9
|
+
|
10
|
+
def stop
|
11
|
+
if alive?
|
12
|
+
self.logger.info "Stopping server (pid #{pid})"
|
13
|
+
Kernel.system "ps -fp #{@pid}" if self.logger.debug?
|
14
|
+
Process.kill('INT', @pid) rescue nil
|
15
|
+
sleep(1)
|
16
|
+
Process.kill('INT', @pid) rescue nil
|
17
|
+
20.times do
|
18
|
+
sleep(1)
|
19
|
+
break unless alive?
|
20
|
+
end
|
21
|
+
if alive?
|
22
|
+
self.logger.info "Gave up waiting (terminating process #{pid} with extreme prejudice)"
|
23
|
+
Process.kill('KILL', @pid) rescue nil
|
24
|
+
end
|
25
|
+
@pid = nil
|
26
|
+
end
|
27
|
+
if @server_handle
|
28
|
+
self.logger.debug 'Closing pipe to server process'
|
29
|
+
Timeout.timeout(@timeout) do
|
30
|
+
@server_handle.close
|
31
|
+
end
|
32
|
+
@server_handle = nil
|
33
|
+
end
|
34
|
+
self.logger.info 'Server has stopped'
|
35
|
+
end
|
36
|
+
|
37
|
+
def start
|
38
|
+
build unless built?
|
39
|
+
# find random unassigned port
|
40
|
+
server = TCPServer.new('127.0.0.1', 0)
|
41
|
+
@port = server.addr[1]
|
42
|
+
server.close
|
43
|
+
unless self.logger.debug?
|
44
|
+
log_dir = File.join(base_dir, 'logs')
|
45
|
+
FileUtils.mkdir_p log_dir
|
46
|
+
file = Tempfile.new(['server_', '.log'], log_dir)
|
47
|
+
@server_logfile = file.path
|
48
|
+
file.close
|
49
|
+
end
|
50
|
+
self.logger.info "Running Rails #{@version} server on port #{port} #{see_log @server_logfile}"
|
51
|
+
exec_arg = defined?(JRUBY_VERSION) ? '' : 'exec'
|
52
|
+
in_app { @server_handle = IO.popen("#{exec_arg} /bin/sh -xc 'exec #{server_command} -p #{port}' #{append_log @server_logfile}", 'w') }
|
53
|
+
@pid = @server_handle.pid
|
54
|
+
# Detach process so alive? will detect if process dies (zombies still accept signals)
|
55
|
+
Process.detach(@pid)
|
56
|
+
serving_requests = false
|
57
|
+
t1 = Time.new
|
58
|
+
while true
|
59
|
+
raise TimeoutError.new("Waiting for server to be available on the port #{see_log @server_logfile}") if t1 + @timeout < Time.new
|
60
|
+
raise RailsappFactory::BuildError.new("Error starting server #{see_log @server_logfile}") unless alive?
|
61
|
+
sleep(1)
|
62
|
+
begin
|
63
|
+
response = Net::HTTP.get(self.uri)
|
64
|
+
if response
|
65
|
+
t2 = Time.new
|
66
|
+
self.logger.info 'Server responded to http GET after %3.1f seconds' % (t2 - t1)
|
67
|
+
serving_requests = true
|
68
|
+
break
|
69
|
+
end
|
70
|
+
rescue Errno::ECONNREFUSED
|
71
|
+
# do nothing
|
72
|
+
rescue Exception => ex
|
73
|
+
self.logger.debug "Ignoring exception #{ex} whilst waiting for server to start"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
Kernel.system 'ps -f' if defined?(JRUBY_VERSION) #DEBUG
|
77
|
+
serving_requests
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class RailsappFactory
|
2
|
+
# Wrapping a string in this class gives you a prettier way to test
|
3
|
+
# for equality. The value returned by <tt>Rails.env</tt> is wrapped
|
4
|
+
# in a StringInquirer object so instead of calling this:
|
5
|
+
#
|
6
|
+
# Rails.env == 'production'
|
7
|
+
#
|
8
|
+
# you can call this:
|
9
|
+
#
|
10
|
+
# Rails.env.production?
|
11
|
+
class StringInquirer < String
|
12
|
+
private
|
13
|
+
|
14
|
+
def respond_to_missing?(method_name, include_private = false)
|
15
|
+
method_name.to_s[-1, 1] == '?'
|
16
|
+
end
|
17
|
+
|
18
|
+
def method_missing(method_name, *arguments)
|
19
|
+
if method_name.to_s[-1, 1] == '?'
|
20
|
+
self == method_name.to_s[0..-2]
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
require 'railsapp_factory/build_error'
|
5
|
+
|
6
|
+
class RailsappFactory
|
7
|
+
module TemplateMethods
|
8
|
+
|
9
|
+
attr_reader :template
|
10
|
+
|
11
|
+
def process_template
|
12
|
+
if self.template
|
13
|
+
if self.built?
|
14
|
+
if self.version =~ /^2/
|
15
|
+
# recheck config/environment.rb in case the template/s add more config.gem lines
|
16
|
+
use_template 'templates/use_bundler_with_rails23.rb'
|
17
|
+
end
|
18
|
+
self.logger.info "Processing template #{@template}"
|
19
|
+
unless self.system_in_app "sh -xc '.bundle/bin/rake rails:template LOCATION=#{@template}' #{append_log 'template.log'}"
|
20
|
+
raise RailsappFactory::BuildError.new("rake rails:template returned exist status #{$?} #{see_log 'rails_new.log'}")
|
21
|
+
end
|
22
|
+
clear_template
|
23
|
+
else
|
24
|
+
# build actions template
|
25
|
+
self.build
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def append_to_template(text, source="append_to_template")
|
31
|
+
unless @template
|
32
|
+
template_dir = File.join(base_dir, 'templates')
|
33
|
+
FileUtils.mkdir_p(template_dir) unless File.directory?(template_dir)
|
34
|
+
@template = Tempfile.new('append_', template_dir).path + '.rb'
|
35
|
+
end
|
36
|
+
open(@template, 'a+') do |f|
|
37
|
+
f.puts "\n# #{source}:"
|
38
|
+
f.puts text
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def use_template(template)
|
43
|
+
append_to_template(open(template).read, "use_template(#{template}")
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def clear_template
|
49
|
+
@template = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
require 'railsapp_factory/class_methods'
|
5
|
+
|
6
|
+
require 'railsapp_factory/build_methods'
|
7
|
+
require 'railsapp_factory/helper_methods'
|
8
|
+
require 'railsapp_factory/run_in_app_methods'
|
9
|
+
require 'railsapp_factory/server_methods'
|
10
|
+
require 'railsapp_factory/string_inquirer'
|
11
|
+
require 'railsapp_factory/template_methods'
|
12
|
+
|
13
|
+
require 'railsapp_factory/build_error'
|
14
|
+
|
15
|
+
require 'railsapp_factory/version'
|
16
|
+
|
17
|
+
class RailsappFactory
|
18
|
+
|
19
|
+
extend RailsappFactory::ClassMethods
|
20
|
+
include RailsappFactory::BuildMethods
|
21
|
+
include RailsappFactory::HelperMethods
|
22
|
+
include RailsappFactory::RunInAppMethods
|
23
|
+
include RailsappFactory::ServerMethods
|
24
|
+
include RailsappFactory::TemplateMethods
|
25
|
+
|
26
|
+
TMPDIR = File.expand_path('tmp/railsapps')
|
27
|
+
|
28
|
+
attr_reader :version # version requested, may be specific release, or the first part of a release number
|
29
|
+
|
30
|
+
def initialize(version = nil, logger = Logger.new(STDERR))
|
31
|
+
self.logger = logger
|
32
|
+
@version = version
|
33
|
+
unless @version
|
34
|
+
@version = RailsappFactory.versions(RUBY_VERSION).last || '4.0'
|
35
|
+
end
|
36
|
+
self.logger.info("RailsappFactory.new(#{version.inspect}) called - version set to #{@version}")
|
37
|
+
raise ArgumentError.new("Invalid version (#{@version})") if @version.to_s !~ /^[2-9](\.\d+){1,2}(-lts)?$/
|
38
|
+
self.gem_source = 'https://rubygems.org'
|
39
|
+
self.db = defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'
|
40
|
+
# 5 minutes
|
41
|
+
self.timeout = 300
|
42
|
+
# clears build vars
|
43
|
+
destroy
|
44
|
+
# clear template vars
|
45
|
+
clear_template
|
46
|
+
# use default ruby
|
47
|
+
use(nil)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'railsapp_factory/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'railsapp_factory'
|
8
|
+
spec.version = RailsappFactory::VERSION
|
9
|
+
spec.authors = ['Ian Heggie']
|
10
|
+
spec.email = ['ian@heggie.biz']
|
11
|
+
spec.description = %q{Rails application factory to make testing gems against multiple versions easier}
|
12
|
+
spec.summary = %q{The prupose of this gem is to make integration testing of gems and libraries against multiple versions of rails easy and avoid having to keep copies of the framework in the gem being tested}
|
13
|
+
spec.homepage = ''
|
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_dependency 'bundler', '~> 1.3'
|
22
|
+
spec.add_dependency 'json_pure'
|
23
|
+
spec.add_development_dependency 'rake'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 2.12'
|
25
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require "spec_helper"
|
3
|
+
require 'railsapp_factory/class_methods'
|
4
|
+
|
5
|
+
describe 'RailsappFactory::ClassMethods' do
|
6
|
+
|
7
|
+
class SubjectClass
|
8
|
+
extend RailsappFactory::ClassMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '::versions' do
|
12
|
+
|
13
|
+
it "should list some rails versions that are compatible with ruby #{RUBY_VERSION}" do
|
14
|
+
list = SubjectClass.versions
|
15
|
+
list.should be_a_kind_of(Array)
|
16
|
+
list.should_not be_empty
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should return an empty list for unknown ruby versions' do
|
20
|
+
list = SubjectClass.versions('1.5.0')
|
21
|
+
list.should be_a_kind_of(Array)
|
22
|
+
list.should be_empty
|
23
|
+
end
|
24
|
+
|
25
|
+
# taken from http://www.devalot.com/articles/2012/03/ror-compatibility
|
26
|
+
{
|
27
|
+
'1.something' => [],
|
28
|
+
'1.8.6' => %w{2.3},
|
29
|
+
'1.8.7' => %w{2.3 2.3-lts 3.0 3.1 3.2},
|
30
|
+
'1.9.1' => %w{2.3},
|
31
|
+
'1.9.2' => %w{3.0 3.1 3.2},
|
32
|
+
'1.9.3' => %w{3.0 3.1 3.2 4.0},
|
33
|
+
'2.0.x' => %w{4.0},
|
34
|
+
'unknown' => %w{4.0},
|
35
|
+
'' => %w{2.3 2.3-lts 3.0 3.1 3.2 4.0}
|
36
|
+
}.each do |ruby_v, expected|
|
37
|
+
it "should list rails versions that are compatible with ruby #{ruby_v}" do
|
38
|
+
list = SubjectClass.versions(ruby_v)
|
39
|
+
list.should be_a_kind_of(Array)
|
40
|
+
list.should == expected
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '::rubies' do
|
47
|
+
|
48
|
+
it 'should list some ruby versions' do
|
49
|
+
list = SubjectClass.rubies
|
50
|
+
list.should be_a_kind_of(Array)
|
51
|
+
list.should_not be_empty
|
52
|
+
end
|
53
|
+
|
54
|
+
#it 'should return an empty list for unknown rails versions' do
|
55
|
+
# list = SubjectClass.rubies('1.5.0')
|
56
|
+
# list.should be_a_kind_of(Array)
|
57
|
+
# list.should be_empty
|
58
|
+
#end
|
59
|
+
|
60
|
+
#SubjectClass.versions(nil).each do |rails_v|
|
61
|
+
# it "should only list ruby versions that are compatible with rails #{rails_v}" do
|
62
|
+
# SubjectClass.rubies(rails_v).each do |ruby_v|
|
63
|
+
# SubjectClass.versions(ruby_v).should include(rails_v)
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
#end
|
67
|
+
end
|
68
|
+
|
69
|
+
it '::ruby_command_prefix should return a string' do
|
70
|
+
res = SubjectClass.ruby_command_prefix
|
71
|
+
res.should be_a(String)
|
72
|
+
end
|
73
|
+
|
74
|
+
it '::has_ruby_version_manager? should return a Boolean' do
|
75
|
+
res = SubjectClass.has_ruby_version_manager?
|
76
|
+
res.should be_a(res ? TrueClass : FalseClass)
|
77
|
+
end
|
78
|
+
|
79
|
+
it '::using_system_ruby? should return a Boolean' do
|
80
|
+
res = SubjectClass.using_system_ruby?
|
81
|
+
res.should be_a(res ? TrueClass : FalseClass)
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '::ruby_command_prefix' do
|
85
|
+
include ::SpecHelper
|
86
|
+
|
87
|
+
SubjectClass.rubies.each do |ruby_v|
|
88
|
+
it "provides a command prefix that will run ruby #{ruby_v}" do
|
89
|
+
prefix = SubjectClass.ruby_command_prefix(ruby_v)
|
90
|
+
#puts "RailsappFactory.ruby_command_prefix(#{ruby_v}) = '#{prefix}'"
|
91
|
+
actual_ruby_v=`#{prefix} ruby -v`
|
92
|
+
actual_version_should_match_rubies_version(actual_ruby_v, ruby_v)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '::encode_query' do
|
99
|
+
|
100
|
+
it 'should encode a simple argument' do
|
101
|
+
SubjectClass.encode_query(:ian => 23).should == '?ian=23'
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should encode a nested argument' do
|
105
|
+
SubjectClass.encode_query(:author => {:ian => 23}).should == '?author%5Bian%5D=23'
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should encode a multiple arguments' do
|
109
|
+
res = SubjectClass.encode_query(:ian => 23, :john => '45')
|
110
|
+
#order not guaranteed
|
111
|
+
if res =~ /^.ian/
|
112
|
+
res.should == '?ian=23&john=45'
|
113
|
+
else
|
114
|
+
res.should == '?john=45&ian=23'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|