slining 1.1.0 → 1.2.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 +4 -4
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/CONTRIBUTING.md +1 -1
- data/LICENSE +2 -2
- data/NEWS.md +67 -0
- data/README.md +32 -19
- data/RELEASING.md +19 -0
- data/bin/slining +3 -3
- data/lib/slining.rb +5 -4
- data/lib/slining/adapters/heroku.rb +67 -0
- data/lib/slining/app_builder.rb +109 -67
- data/lib/slining/generators/app_generator.rb +22 -5
- data/lib/slining/version.rb +1 -1
- data/slining.gemspec +1 -0
- data/spec/adapters/heroku_spec.rb +52 -0
- data/spec/features/heroku_spec.rb +56 -30
- data/spec/features/new_project_spec.rb +66 -4
- data/spec/spec_helper.rb +4 -1
- data/spec/support/fake_heroku.rb +5 -3
- data/spec/support/slining.rb +20 -12
- data/templates/Gemfile.erb +6 -4
- data/templates/Procfile +1 -1
- data/templates/README.md.erb +3 -7
- data/templates/bin_setup.erb +1 -11
- data/templates/capybara_webkit.rb +5 -0
- data/templates/circle.yml.erb +9 -0
- data/templates/{development_seeds.rb → dev.rake} +1 -1
- data/templates/disable_xml_params.rb +0 -2
- data/templates/dotfiles/.ctags +2 -0
- data/templates/factories.rb +2 -0
- data/templates/postgresql_database.yml.erb +11 -1
- data/templates/puma.rb +19 -0
- data/templates/rails_helper.rb +1 -2
- data/templates/sample.env +7 -3
- data/templates/shoulda_matchers_config_rspec.rb +6 -0
- data/templates/slining_gitignore +0 -1
- data/templates/spec_helper.rb +1 -0
- metadata +27 -8
- data/.travis.yml +0 -11
- data/Gemfile.lock +0 -123
- data/templates/travis.yml.erb +0 -21
- data/templates/unicorn.rb +0 -30
|
@@ -41,9 +41,11 @@ module Slining
|
|
|
41
41
|
invoke :setup_stylesheets
|
|
42
42
|
invoke :copy_miscellaneous_files
|
|
43
43
|
invoke :customize_error_pages
|
|
44
|
+
invoke :remove_config_comment_lines
|
|
44
45
|
invoke :remove_routes_comment_lines
|
|
45
46
|
invoke :setup_git
|
|
46
47
|
invoke :setup_database
|
|
48
|
+
invoke :setup_dotfiles
|
|
47
49
|
invoke :create_heroku_apps
|
|
48
50
|
invoke :create_github_repo
|
|
49
51
|
invoke :setup_segment
|
|
@@ -57,10 +59,11 @@ module Slining
|
|
|
57
59
|
build :set_ruby_to_version_being_used
|
|
58
60
|
|
|
59
61
|
if options[:heroku]
|
|
60
|
-
build :
|
|
62
|
+
build :set_up_heroku_specific_gems
|
|
61
63
|
end
|
|
62
64
|
|
|
63
65
|
bundle_command 'install'
|
|
66
|
+
build :configure_simple_form
|
|
64
67
|
end
|
|
65
68
|
|
|
66
69
|
def setup_database
|
|
@@ -75,28 +78,34 @@ module Slining
|
|
|
75
78
|
|
|
76
79
|
def setup_development_environment
|
|
77
80
|
say 'Setting up the development environment'
|
|
81
|
+
build :raise_on_missing_assets_in_test
|
|
78
82
|
build :raise_on_delivery_errors
|
|
79
83
|
build :set_test_delivery_method
|
|
84
|
+
build :add_bullet_gem_configuration
|
|
80
85
|
build :raise_on_unpermitted_parameters
|
|
81
86
|
build :provide_setup_script
|
|
82
87
|
build :provide_dev_prime_task
|
|
83
88
|
build :configure_generators
|
|
84
89
|
build :configure_i18n_for_missing_translations
|
|
90
|
+
build :configure_quiet_assets
|
|
85
91
|
end
|
|
86
92
|
|
|
87
93
|
def setup_test_environment
|
|
88
94
|
say 'Setting up the test environment'
|
|
89
95
|
build :set_up_factory_girl_for_rspec
|
|
96
|
+
build :generate_factories_file
|
|
90
97
|
build :set_up_hound
|
|
91
98
|
build :generate_rspec
|
|
92
99
|
build :configure_rspec
|
|
93
100
|
build :configure_background_jobs_for_rspec
|
|
94
101
|
build :enable_database_cleaner
|
|
102
|
+
build :provide_shoulda_matchers_config
|
|
95
103
|
build :configure_spec_support_features
|
|
96
|
-
build :
|
|
104
|
+
build :configure_ci
|
|
97
105
|
build :configure_i18n_for_test_environment
|
|
98
106
|
build :configure_i18n_tasks
|
|
99
107
|
build :configure_action_mailer_in_specs
|
|
108
|
+
build :configure_capybara_webkit
|
|
100
109
|
end
|
|
101
110
|
|
|
102
111
|
def setup_production_environment
|
|
@@ -132,12 +141,11 @@ module Slining
|
|
|
132
141
|
build :configure_action_mailer
|
|
133
142
|
build :configure_active_job
|
|
134
143
|
build :configure_time_formats
|
|
135
|
-
build :configure_simple_form
|
|
136
144
|
build :disable_xml_params
|
|
137
145
|
build :fix_i18n_deprecation_warning
|
|
138
146
|
build :setup_default_rake_task
|
|
139
|
-
build :
|
|
140
|
-
build :
|
|
147
|
+
build :configure_puma
|
|
148
|
+
build :set_up_forego
|
|
141
149
|
end
|
|
142
150
|
|
|
143
151
|
def setup_stylesheets
|
|
@@ -161,6 +169,7 @@ module Slining
|
|
|
161
169
|
build :set_heroku_remotes
|
|
162
170
|
build :set_heroku_rails_secrets
|
|
163
171
|
build :provide_deploy_script
|
|
172
|
+
build :configure_automatic_deployment
|
|
164
173
|
end
|
|
165
174
|
end
|
|
166
175
|
|
|
@@ -176,6 +185,10 @@ module Slining
|
|
|
176
185
|
build :setup_segment
|
|
177
186
|
end
|
|
178
187
|
|
|
188
|
+
def setup_dotfiles
|
|
189
|
+
build :copy_dotfiles
|
|
190
|
+
end
|
|
191
|
+
|
|
179
192
|
def setup_gitignore
|
|
180
193
|
build :gitignore_files
|
|
181
194
|
end
|
|
@@ -204,6 +217,10 @@ module Slining
|
|
|
204
217
|
build :customize_error_pages
|
|
205
218
|
end
|
|
206
219
|
|
|
220
|
+
def remove_config_comment_lines
|
|
221
|
+
build :remove_config_comment_lines
|
|
222
|
+
end
|
|
223
|
+
|
|
207
224
|
def remove_routes_comment_lines
|
|
208
225
|
build :remove_routes_comment_lines
|
|
209
226
|
end
|
data/lib/slining/version.rb
CHANGED
data/slining.gemspec
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
module Slining
|
|
4
|
+
module Adapters
|
|
5
|
+
RSpec.describe Heroku do
|
|
6
|
+
it "sets the heroku remotes" do
|
|
7
|
+
setup_file = "bin/setup"
|
|
8
|
+
app_builder = double(app_name: app_name)
|
|
9
|
+
allow(app_builder).to receive(:append_file)
|
|
10
|
+
|
|
11
|
+
Heroku.new(app_builder).set_heroku_remotes
|
|
12
|
+
|
|
13
|
+
expect(app_builder).to have_received(:append_file).
|
|
14
|
+
with(setup_file, /heroku join --app #{app_name.dasherize}-production/)
|
|
15
|
+
expect(app_builder).to have_received(:append_file).
|
|
16
|
+
with(setup_file, /heroku join --app #{app_name.dasherize}-staging/)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "sets up the heroku specific gems" do
|
|
20
|
+
app_builder = double(app_name: app_name)
|
|
21
|
+
allow(app_builder).to receive(:inject_into_file)
|
|
22
|
+
|
|
23
|
+
Heroku.new(app_builder).set_up_heroku_specific_gems
|
|
24
|
+
|
|
25
|
+
expect(app_builder).to have_received(:inject_into_file).
|
|
26
|
+
with("Gemfile", /rails_stdout_logging/, anything)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "sets the heroku rails secrets" do
|
|
30
|
+
app_builder = double(app_name: app_name)
|
|
31
|
+
allow(app_builder).to receive(:run)
|
|
32
|
+
|
|
33
|
+
Heroku.new(app_builder).set_heroku_rails_secrets
|
|
34
|
+
|
|
35
|
+
expect(app_builder).to(
|
|
36
|
+
have_configured_var("staging", "SECRET_KEY_BASE"),
|
|
37
|
+
)
|
|
38
|
+
expect(app_builder).to(
|
|
39
|
+
have_configured_var("production", "SECRET_KEY_BASE"),
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def app_name
|
|
44
|
+
SliningTestHelpers::APP_NAME
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def have_configured_var(remote_name, var)
|
|
48
|
+
have_received(:run).with(/config:add #{var}=.+ --remote #{remote_name}/)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -1,46 +1,72 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
|
|
3
3
|
RSpec.describe "Heroku" do
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
context "--heroku" do
|
|
5
|
+
before(:all) do
|
|
6
|
+
clean_up
|
|
7
|
+
run_slining("--heroku=true")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "slinings a project for Heroku" do
|
|
11
|
+
app_name = SliningTestHelpers::APP_NAME.dasherize
|
|
12
|
+
|
|
13
|
+
expect(FakeHeroku).to(
|
|
14
|
+
have_gem_included(project_path, "rails_stdout_logging"),
|
|
15
|
+
)
|
|
16
|
+
expect(FakeHeroku).to have_created_app_for("staging")
|
|
17
|
+
expect(FakeHeroku).to have_created_app_for("production")
|
|
18
|
+
expect(FakeHeroku).to have_configured_vars("staging", "SECRET_KEY_BASE")
|
|
19
|
+
expect(FakeHeroku).to have_configured_vars(
|
|
20
|
+
"production",
|
|
21
|
+
"SECRET_KEY_BASE",
|
|
22
|
+
)
|
|
8
23
|
|
|
9
|
-
|
|
10
|
-
|
|
24
|
+
bin_setup_path = "#{project_path}/bin/setup"
|
|
25
|
+
bin_setup = IO.read(bin_setup_path)
|
|
11
26
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
expect(FakeHeroku).to have_created_app_for("staging")
|
|
16
|
-
expect(FakeHeroku).to have_created_app_for("production")
|
|
17
|
-
expect(FakeHeroku).to have_configured_vars("staging", "SECRET_KEY_BASE")
|
|
18
|
-
expect(FakeHeroku).to have_configured_vars("production", "SECRET_KEY_BASE")
|
|
27
|
+
expect(bin_setup).to include("heroku join --app #{app_name}-production")
|
|
28
|
+
expect(bin_setup).to include("heroku join --app #{app_name}-staging")
|
|
29
|
+
expect(File.stat(bin_setup_path)).to be_executable
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
app_name = SliningTestHelpers::APP_NAME.dasherize
|
|
31
|
+
bin_deploy_path = "#{project_path}/bin/deploy"
|
|
32
|
+
bin_deploy = IO.read(bin_deploy_path)
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
expect(File.stat(bin_setup_path)).to be_executable
|
|
34
|
+
expect(bin_deploy).to include("heroku run rake db:migrate")
|
|
35
|
+
expect(File.stat(bin_deploy_path)).to be_executable
|
|
27
36
|
|
|
28
|
-
|
|
29
|
-
bin_deploy = IO.read(bin_deploy_path)
|
|
37
|
+
readme = IO.read("#{project_path}/README.md")
|
|
30
38
|
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
expect(readme).to include("./bin/deploy staging")
|
|
40
|
+
expect(readme).to include("./bin/deploy production")
|
|
33
41
|
|
|
34
|
-
|
|
42
|
+
circle_yml_path = "#{project_path}/circle.yml"
|
|
43
|
+
circle_yml = IO.read(circle_yml_path)
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
expect(circle_yml).to include <<-YML.strip_heredoc
|
|
46
|
+
deployment:
|
|
47
|
+
staging:
|
|
48
|
+
branch: master
|
|
49
|
+
commands:
|
|
50
|
+
- bin/deploy staging
|
|
51
|
+
YML
|
|
52
|
+
end
|
|
38
53
|
end
|
|
39
54
|
|
|
40
|
-
|
|
41
|
-
|
|
55
|
+
context "--heroku with region flag" do
|
|
56
|
+
before(:all) do
|
|
57
|
+
clean_up
|
|
58
|
+
run_slining(%{--heroku=true --heroku-flags="--region eu"})
|
|
59
|
+
end
|
|
42
60
|
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
it "slinings a project with extra Heroku flags" do
|
|
62
|
+
expect(FakeHeroku).to have_created_app_for("staging", "--region eu")
|
|
63
|
+
expect(FakeHeroku).to have_created_app_for("production", "--region eu")
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def clean_up
|
|
68
|
+
drop_dummy_database
|
|
69
|
+
remove_project_directory
|
|
70
|
+
FakeHeroku.clear!
|
|
45
71
|
end
|
|
46
72
|
end
|
|
@@ -29,6 +29,10 @@ RSpec.describe "Slining a new project with default configuration" do
|
|
|
29
29
|
expect(ruby_version_file).to eq "#{RUBY_VERSION}\n"
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
it "copies dotfiles" do
|
|
33
|
+
expect(File).to exist("#{project_path}/.ctags")
|
|
34
|
+
end
|
|
35
|
+
|
|
32
36
|
it "loads secret_key_base from env" do
|
|
33
37
|
secrets_file = IO.read("#{project_path}/config/secrets.yml")
|
|
34
38
|
|
|
@@ -39,6 +43,10 @@ RSpec.describe "Slining a new project with default configuration" do
|
|
|
39
43
|
expect(File).to exist("#{project_path}/spec/support/action_mailer.rb")
|
|
40
44
|
end
|
|
41
45
|
|
|
46
|
+
it "configures capybara-webkit" do
|
|
47
|
+
expect(File).to exist("#{project_path}/spec/support/capybara_webkit.rb")
|
|
48
|
+
end
|
|
49
|
+
|
|
42
50
|
it "adds support file for i18n" do
|
|
43
51
|
expect(File).to exist("#{project_path}/spec/support/i18n.rb")
|
|
44
52
|
end
|
|
@@ -72,6 +80,14 @@ RSpec.describe "Slining a new project with default configuration" do
|
|
|
72
80
|
)
|
|
73
81
|
end
|
|
74
82
|
|
|
83
|
+
it "adds explicit quiet_assets configuration" do
|
|
84
|
+
result = IO.read("#{project_path}/config/application.rb")
|
|
85
|
+
|
|
86
|
+
expect(result).to match(
|
|
87
|
+
/^ +config.quiet_assets = true$/
|
|
88
|
+
)
|
|
89
|
+
end
|
|
90
|
+
|
|
75
91
|
it "raises on missing translations in development and test" do
|
|
76
92
|
%w[development test].each do |environment|
|
|
77
93
|
environment_file =
|
|
@@ -107,6 +123,12 @@ RSpec.describe "Slining a new project with default configuration" do
|
|
|
107
123
|
to match(/^ +config.action_mailer.delivery_method = :test$/)
|
|
108
124
|
end
|
|
109
125
|
|
|
126
|
+
it "uses APPLICATION_HOST, not HOST in the production config" do
|
|
127
|
+
prod_env_file = IO.read("#{project_path}/config/environments/production.rb")
|
|
128
|
+
expect(prod_env_file).to match(/"APPLICATION_HOST"/)
|
|
129
|
+
expect(prod_env_file).not_to match(/"HOST"/)
|
|
130
|
+
end
|
|
131
|
+
|
|
110
132
|
it "configs active job queue adapter" do
|
|
111
133
|
application_config = IO.read("#{project_path}/config/application.rb")
|
|
112
134
|
test_config = IO.read("#{project_path}/config/environments/test.rb")
|
|
@@ -119,16 +141,56 @@ RSpec.describe "Slining a new project with default configuration" do
|
|
|
119
141
|
)
|
|
120
142
|
end
|
|
121
143
|
|
|
144
|
+
it "configs bullet gem in development" do
|
|
145
|
+
test_config = IO.read("#{project_path}/config/environments/development.rb")
|
|
146
|
+
|
|
147
|
+
expect(test_config).to match /^ +Bullet.enable = true$/
|
|
148
|
+
expect(test_config).to match /^ +Bullet.bullet_logger = true$/
|
|
149
|
+
expect(test_config).to match /^ +Bullet.rails_logger = true$/
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "configs missing assets to raise in test" do
|
|
153
|
+
test_config = IO.read("#{project_path}/config/environments/test.rb")
|
|
154
|
+
expect(test_config).to match /^ +config.assets.raise_runtime_errors = true$/
|
|
155
|
+
end
|
|
156
|
+
|
|
122
157
|
it "adds spring to binstubs" do
|
|
123
158
|
expect(File).to exist("#{project_path}/bin/spring")
|
|
124
159
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
160
|
+
bin_stub_files = [
|
|
161
|
+
IO.read("#{project_path}/bin/rails"),
|
|
162
|
+
IO.read("#{project_path}/bin/rake"),
|
|
163
|
+
IO.read("#{project_path}/bin/rspec"),
|
|
164
|
+
]
|
|
165
|
+
|
|
166
|
+
spring_line1 = /^ +spring_bin_path = File.expand_path\('\.\.\/spring', __FILE__\)$/
|
|
167
|
+
spring_line2 = /^ +load spring_bin_path$/
|
|
168
|
+
|
|
169
|
+
bin_stub_files.each do |file|
|
|
170
|
+
expect(file).to match(spring_line1)
|
|
171
|
+
expect(file).to match(spring_line2)
|
|
129
172
|
end
|
|
130
173
|
end
|
|
131
174
|
|
|
175
|
+
it "removes comments and extra newlines from config files" do
|
|
176
|
+
config_files = [
|
|
177
|
+
IO.read("#{project_path}/config/application.rb"),
|
|
178
|
+
IO.read("#{project_path}/config/environment.rb"),
|
|
179
|
+
IO.read("#{project_path}/config/environments/development.rb"),
|
|
180
|
+
IO.read("#{project_path}/config/environments/production.rb"),
|
|
181
|
+
IO.read("#{project_path}/config/environments/test.rb"),
|
|
182
|
+
]
|
|
183
|
+
|
|
184
|
+
config_files.each do |file|
|
|
185
|
+
expect(file).not_to match(/.*#.*/)
|
|
186
|
+
expect(file).not_to match(/^$\n/)
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "copies factories.rb" do
|
|
191
|
+
expect(File).to exist("#{project_path}/spec/factories.rb")
|
|
192
|
+
end
|
|
193
|
+
|
|
132
194
|
def analytics_partial
|
|
133
195
|
IO.read("#{project_path}/app/views/application/_analytics.html.erb")
|
|
134
196
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
require 'bundler/setup'
|
|
2
2
|
|
|
3
|
+
require "codeclimate-test-reporter"
|
|
4
|
+
CodeClimate::TestReporter.start
|
|
5
|
+
|
|
3
6
|
Bundler.require(:default, :test)
|
|
4
7
|
|
|
5
8
|
require (Pathname.new(__FILE__).dirname + '../lib/slining').expand_path
|
|
@@ -10,11 +13,11 @@ RSpec.configure do |config|
|
|
|
10
13
|
config.include SliningTestHelpers
|
|
11
14
|
|
|
12
15
|
config.before(:all) do
|
|
16
|
+
add_fakes_to_path
|
|
13
17
|
create_tmp_directory
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
config.before(:each) do
|
|
17
|
-
FakeHeroku.clear!
|
|
18
21
|
FakeGithub.clear!
|
|
19
22
|
end
|
|
20
23
|
end
|
data/spec/support/fake_heroku.rb
CHANGED
|
@@ -36,8 +36,10 @@ class FakeHeroku
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def self.has_configured_vars?(remote_name, var)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
commands_ran =~ /^config:add #{var}=.+ --remote #{remote_name}\n/
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.commands_ran
|
|
43
|
+
@commands_ran ||= File.read(RECORDER)
|
|
42
44
|
end
|
|
43
45
|
end
|
data/spec/support/slining.rb
CHANGED
|
@@ -12,9 +12,10 @@ module SliningTestHelpers
|
|
|
12
12
|
def run_slining(arguments = nil)
|
|
13
13
|
Dir.chdir(tmp_path) do
|
|
14
14
|
Bundler.with_clean_env do
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
add_fakes_to_path
|
|
16
|
+
`
|
|
17
|
+
#{slining_bin} #{APP_NAME} #{arguments}
|
|
18
|
+
`
|
|
18
19
|
end
|
|
19
20
|
end
|
|
20
21
|
end
|
|
@@ -29,21 +30,28 @@ module SliningTestHelpers
|
|
|
29
30
|
end
|
|
30
31
|
end
|
|
31
32
|
|
|
33
|
+
def add_fakes_to_path
|
|
34
|
+
ENV["PATH"] = "#{support_bin}:#{ENV["PATH"]}"
|
|
35
|
+
end
|
|
36
|
+
|
|
32
37
|
def project_path
|
|
33
38
|
@project_path ||= Pathname.new("#{tmp_path}/#{APP_NAME}")
|
|
34
39
|
end
|
|
35
40
|
|
|
36
41
|
private
|
|
42
|
+
def tmp_path
|
|
43
|
+
@tmp_path ||= Pathname.new("#{root_path}/tmp")
|
|
44
|
+
end
|
|
37
45
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
def slining_bin
|
|
47
|
+
File.join(root_path, 'bin', 'slining')
|
|
48
|
+
end
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
def support_bin
|
|
51
|
+
File.join(root_path, "spec", "fakes", "bin")
|
|
52
|
+
end
|
|
45
53
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
def root_path
|
|
55
|
+
File.expand_path('../../../', __FILE__)
|
|
56
|
+
end
|
|
49
57
|
end
|