katapult 0.1.2 → 0.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/README.md +61 -35
- data/bin/katapult +24 -34
- data/features/authenticate.feature +344 -0
- data/features/basics.feature +590 -0
- data/features/binary.feature +33 -1
- data/features/model.feature +9 -13
- data/features/step_definitions/rails_steps.rb +3 -2
- data/features/wui.feature +49 -4
- data/lib/generators/katapult/basics/basics_generator.rb +63 -17
- data/lib/generators/katapult/basics/templates/.gitignore +1 -0
- data/lib/generators/katapult/basics/templates/.ruby-version +1 -1
- data/lib/generators/katapult/basics/templates/Capfile +25 -0
- data/lib/generators/katapult/basics/templates/Gemfile +14 -6
- data/lib/generators/katapult/basics/templates/Guardfile +44 -0
- data/lib/generators/katapult/basics/templates/config/database.sample.yml +3 -2
- data/lib/generators/katapult/basics/templates/config/database.yml +3 -2
- data/lib/generators/katapult/basics/templates/config/deploy/production.rb +8 -0
- data/lib/generators/katapult/basics/templates/config/deploy/staging.rb +7 -0
- data/lib/generators/katapult/basics/templates/config/deploy.rb +37 -0
- data/lib/generators/katapult/basics/templates/config/initializers/ext.rb +3 -0
- data/lib/generators/katapult/basics/templates/features/support/factory_girl.rb +1 -0
- data/lib/generators/katapult/basics/templates/features/support/paths.rb +6 -0
- data/lib/generators/katapult/basics/templates/lib/capistrano/tasks/db.rake +28 -0
- data/lib/generators/katapult/basics/templates/lib/capistrano/tasks/deploy.rake +15 -0
- data/lib/generators/katapult/basics/templates/lib/capistrano/tasks/passenger.rake +8 -0
- data/lib/generators/katapult/basics/templates/{config/initializers → lib/ext/action_view}/form_for_with_development_errors.rb +0 -2
- data/lib/generators/katapult/basics/templates/lib/ext/action_view/spec_label.rb +46 -0
- data/lib/generators/katapult/basics/templates/{config/initializers → lib/ext/active_record}/find_by_anything.rb +0 -0
- data/lib/generators/katapult/basics/templates/lib/ext/active_record/these.rb +7 -0
- data/lib/generators/katapult/basics/templates/lib/ext/array/xss_aware_join.rb +10 -0
- data/lib/generators/katapult/basics/templates/lib/ext/enumerable/natural_sort.rb +15 -0
- data/lib/generators/katapult/basics/templates/lib/ext/hash/infinite.rb +7 -0
- data/lib/generators/katapult/basics/templates/lib/ext/string/html_entities.rb +11 -0
- data/lib/generators/katapult/basics/templates/lib/ext/string/to_sort_atoms.rb +52 -0
- data/lib/generators/katapult/basics/templates/lib/tasks/pending_migrations.rake +24 -0
- data/lib/generators/katapult/basics/templates/spec/factories/factories.rb +9 -0
- data/lib/generators/katapult/basics/templates/spec/support/factory_girl.rb +3 -0
- data/lib/generators/katapult/clearance/clearance_generator.rb +125 -0
- data/lib/generators/katapult/clearance/templates/app/controllers/passwords_controller.rb +16 -0
- data/lib/generators/katapult/clearance/templates/app/views/clearance_mailer/change_password.html.haml +6 -0
- data/lib/generators/katapult/clearance/templates/app/views/clearance_mailer/change_password.text.erb +3 -0
- data/lib/generators/katapult/clearance/templates/app/views/passwords/create.html.haml +5 -0
- data/lib/generators/katapult/clearance/templates/app/views/passwords/edit.html.haml +16 -0
- data/lib/generators/katapult/clearance/templates/app/views/passwords/new.html.haml +14 -0
- data/lib/generators/katapult/clearance/templates/app/views/sessions/new.html.haml +19 -0
- data/lib/generators/katapult/clearance/templates/config/initializers/clearance.rb +15 -0
- data/lib/generators/katapult/clearance/templates/config/locales/clearance.en.yml +59 -0
- data/lib/generators/katapult/clearance/templates/features/authentication.feature +94 -0
- data/lib/generators/katapult/clearance/templates/features/step_definitions/authentication_steps.rb +4 -0
- data/lib/generators/katapult/cucumber_features/templates/feature.feature +11 -7
- data/lib/generators/katapult/haml/haml_generator.rb +5 -0
- data/lib/generators/katapult/haml/templates/_form.html.haml +4 -4
- data/lib/generators/katapult/haml/templates/app/views/layouts/_flashes.html.haml +3 -0
- data/lib/generators/katapult/haml/templates/app/views/layouts/application.html.haml +9 -3
- data/lib/generators/katapult/haml/templates/index.html.haml +1 -1
- data/lib/generators/katapult/haml/templates/show.html.haml +2 -4
- data/lib/generators/katapult/install/templates/lib/katapult/application_model.rb +9 -7
- data/lib/generators/katapult/model/model_generator.rb +1 -1
- data/lib/generators/katapult/w_u_i/templates/controller.rb +1 -1
- data/lib/generators/katapult/w_u_i/w_u_i_generator.rb +4 -2
- data/lib/katapult/application_model.rb +8 -1
- data/lib/katapult/attribute.rb +10 -11
- data/lib/katapult/authentication.rb +25 -0
- data/lib/katapult/binary_util.rb +37 -0
- data/lib/katapult/element.rb +1 -1
- data/lib/katapult/generator.rb +6 -0
- data/lib/katapult/model.rb +13 -1
- data/lib/katapult/parser.rb +7 -0
- data/lib/katapult/version.rb +1 -1
- data/lib/katapult/wui.rb +4 -0
- data/lib/katapult.rb +2 -0
- data/spec/attribute_spec.rb +13 -0
- data/spec/element_spec.rb +5 -0
- data/spec/model_spec.rb +5 -4
- data/spec/util_spec.rb +8 -8
- data/spec/wui_spec.rb +19 -0
- metadata +44 -8
- data/features/katapult.feature +0 -271
- data/lib/katapult/util.rb +0 -16
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
Feature: Katapult in general
|
|
2
|
+
|
|
3
|
+
Background:
|
|
4
|
+
Given a pristine Rails application
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Scenario: Install katapult
|
|
8
|
+
When I install katapult
|
|
9
|
+
Then the file "lib/katapult/application_model.rb" should contain exactly:
|
|
10
|
+
"""
|
|
11
|
+
# Here you define the fundamentals of your application.
|
|
12
|
+
#
|
|
13
|
+
# Add a model:
|
|
14
|
+
# model 'user' do |user|
|
|
15
|
+
# user.attr :name
|
|
16
|
+
# user.attr :birth, type: :datetime
|
|
17
|
+
# user.attr :email
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# Add a web user interface:
|
|
21
|
+
# wui 'user' do |wui|
|
|
22
|
+
# wui.crud # Creates all CRUD actions: index, new, show, etc.
|
|
23
|
+
# wui.action :lock, scope: :member, method: :post
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# Add navigation
|
|
27
|
+
# navigation :main
|
|
28
|
+
#
|
|
29
|
+
# Add authentication
|
|
30
|
+
# authenticate 'user', system_email: 'system@example.com'
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
Scenario: Generate basic files and settings
|
|
36
|
+
Given I install katapult
|
|
37
|
+
|
|
38
|
+
When I generate katapult basics
|
|
39
|
+
Then the file ".ruby-version" should contain "2.3.0"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
And the file "config/cucumber.yml" should contain:
|
|
43
|
+
"""
|
|
44
|
+
default: <%= std_opts %> features
|
|
45
|
+
wip: --tags @wip:3 --wip features
|
|
46
|
+
parallel: <%= std_opts %> features <%= log_failures %>
|
|
47
|
+
rerun: -r features --format pretty --strict <%= rerun_failures %> <%= log_failures %>
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
And the file ".gitignore" should contain "config/database.yml"
|
|
52
|
+
And the file ".bundle/config" should match /NOKOGIRI.*--use-system-libraries/
|
|
53
|
+
And the file "Guardfile" should contain:
|
|
54
|
+
"""
|
|
55
|
+
guard 'livereload' do
|
|
56
|
+
watch %r{app/views/.+\.(erb|haml)$}
|
|
57
|
+
watch 'app/models/navigation.rb' # Navy
|
|
58
|
+
watch 'app/models/power.rb' # Consul
|
|
59
|
+
watch %r{app/helpers/.+\.rb}
|
|
60
|
+
watch %r{public/.+\.(css|js|html)}
|
|
61
|
+
watch %r{config/locales/.+\.yml}
|
|
62
|
+
watch %r{spec/javascripts/} # Jasmine
|
|
63
|
+
|
|
64
|
+
# Rails Assets Pipeline
|
|
65
|
+
watch(%r{(app|vendor)(/assets/\w+/(.+\.(css|sass|js|coffee|html|png|jpg))).*}) do |m|
|
|
66
|
+
filename = m[3]
|
|
67
|
+
# When a .sass (or .css.sass) file was changed, tell the client to load the .css version.
|
|
68
|
+
# Similarly, for .coffee / .js.coffee files we ask the client to reload the .js file.
|
|
69
|
+
filename.gsub! /(\.css)?\.sass$/, '.css'
|
|
70
|
+
filename.gsub! /(\.js)?\.coffee$/, '.js'
|
|
71
|
+
"/assets/#{filename}"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
"""
|
|
75
|
+
And the file "Capfile" should contain:
|
|
76
|
+
"""
|
|
77
|
+
# Load DSL and set up stages
|
|
78
|
+
require 'capistrano/setup'
|
|
79
|
+
|
|
80
|
+
# Include default deployment tasks
|
|
81
|
+
require 'capistrano/deploy'
|
|
82
|
+
|
|
83
|
+
# Include tasks from other gems included in your Gemfile
|
|
84
|
+
require 'capistrano/bundler'
|
|
85
|
+
require 'capistrano/maintenance'
|
|
86
|
+
require 'capistrano/rails/assets'
|
|
87
|
+
require 'capistrano/rails/migrations'
|
|
88
|
+
require 'whenever/capistrano'
|
|
89
|
+
|
|
90
|
+
Dir.glob('lib/capistrano/tasks/*.rake').each do |r|
|
|
91
|
+
# `import r` calls Rake.application.add_import(r), which imports the file only
|
|
92
|
+
# *after* this file has been processed, so the imported tasks would not be
|
|
93
|
+
# available to the hooks below.
|
|
94
|
+
Rake.load_rakefile r
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
before 'deploy:updating', 'db:dump'
|
|
98
|
+
after 'deploy:published', 'deploy:restart'
|
|
99
|
+
after 'deploy:published', 'db:warn_if_pending_migrations'
|
|
100
|
+
after 'deploy:published', 'db:show_dump_usage'
|
|
101
|
+
after 'deploy:finished', 'deploy:cleanup' # https://makandracards.com/makandra/1432
|
|
102
|
+
"""
|
|
103
|
+
And the file "Gemfile" should contain "gem 'rails', '4.2.6'"
|
|
104
|
+
And the file "Gemfile" should contain exactly:
|
|
105
|
+
"""
|
|
106
|
+
source 'https://rubygems.org'
|
|
107
|
+
|
|
108
|
+
gem 'rails', '4.2.6'
|
|
109
|
+
gem 'pg', '~> 0.15'
|
|
110
|
+
gem 'jquery-rails'
|
|
111
|
+
gem 'jbuilder', '~> 2.0'
|
|
112
|
+
gem 'katapult', path: '../../..'
|
|
113
|
+
|
|
114
|
+
# internal
|
|
115
|
+
gem 'exception_notification'
|
|
116
|
+
# gem 'admin_cleaner', git: 'git@code.makandra.de:makandra/admin_cleaner.git'
|
|
117
|
+
|
|
118
|
+
# security
|
|
119
|
+
gem 'breach-mitigation-rails'
|
|
120
|
+
gem 'safe_cookies'
|
|
121
|
+
|
|
122
|
+
# better coding
|
|
123
|
+
gem 'modularity'
|
|
124
|
+
gem 'edge_rider'
|
|
125
|
+
gem 'andand'
|
|
126
|
+
|
|
127
|
+
# models
|
|
128
|
+
gem 'has_defaults'
|
|
129
|
+
gem 'assignable_values'
|
|
130
|
+
|
|
131
|
+
# gem 'carrierwave'
|
|
132
|
+
# gem 'mini_magick'
|
|
133
|
+
|
|
134
|
+
# gem 'spreadsheet'
|
|
135
|
+
# gem 'vcard'
|
|
136
|
+
|
|
137
|
+
# views
|
|
138
|
+
# gem 'simple_form'
|
|
139
|
+
# gem 'nested_form'
|
|
140
|
+
gem 'will_paginate'
|
|
141
|
+
gem 'makandra-navy', require: 'navy'
|
|
142
|
+
|
|
143
|
+
# assets
|
|
144
|
+
gem 'haml-rails'
|
|
145
|
+
gem 'bootstrap-sass'
|
|
146
|
+
gem 'sass-rails'
|
|
147
|
+
gem 'autoprefixer-rails'
|
|
148
|
+
gem 'coffee-rails'
|
|
149
|
+
gem 'therubyracer', platform: :ruby
|
|
150
|
+
gem 'uglifier'
|
|
151
|
+
gem 'compass-rails'
|
|
152
|
+
gem 'compass-rgbapng'
|
|
153
|
+
|
|
154
|
+
group :development do
|
|
155
|
+
gem 'query_diet'
|
|
156
|
+
gem 'better_errors'
|
|
157
|
+
gem 'binding_of_caller'
|
|
158
|
+
gem 'thin'
|
|
159
|
+
|
|
160
|
+
gem 'parallel_tests'
|
|
161
|
+
gem 'guard-livereload', require: false
|
|
162
|
+
gem 'rack-livereload'
|
|
163
|
+
gem 'spring-commands-rspec'
|
|
164
|
+
gem 'spring-commands-cucumber'
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
group :development, :test do
|
|
168
|
+
gem 'byebug'
|
|
169
|
+
gem 'factory_girl_rails'
|
|
170
|
+
gem 'rspec-rails'
|
|
171
|
+
gem 'spring'
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
group :test do
|
|
175
|
+
gem 'database_cleaner'
|
|
176
|
+
gem 'timecop'
|
|
177
|
+
gem 'launchy'
|
|
178
|
+
|
|
179
|
+
gem 'capybara'
|
|
180
|
+
gem 'capybara-screenshot'
|
|
181
|
+
gem 'cucumber', '< 2' # Incompatible with Cucumber Factory
|
|
182
|
+
gem 'cucumber-rails', require: false
|
|
183
|
+
gem 'cucumber_factory'
|
|
184
|
+
gem 'selenium-webdriver'
|
|
185
|
+
gem 'spreewald'
|
|
186
|
+
|
|
187
|
+
gem 'rspec'
|
|
188
|
+
gem 'shoulda-matchers', require: false
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
group :deploy do
|
|
192
|
+
gem 'capistrano-rails', require: false
|
|
193
|
+
gem 'capistrano-bundler', require: false
|
|
194
|
+
gem 'capistrano-maintenance'
|
|
195
|
+
end
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
And the file "app/controllers/application_controller.rb" should contain:
|
|
199
|
+
"""
|
|
200
|
+
before_filter :make_action_mailer_use_request_host_and_protocol
|
|
201
|
+
|
|
202
|
+
private
|
|
203
|
+
|
|
204
|
+
def make_action_mailer_use_request_host_and_protocol
|
|
205
|
+
ActionMailer::Base.default_url_options[:protocol] = request.protocol
|
|
206
|
+
ActionMailer::Base.default_url_options[:host] = request.host_with_port
|
|
207
|
+
end
|
|
208
|
+
"""
|
|
209
|
+
|
|
210
|
+
# Just checking turbolinks was properly removed
|
|
211
|
+
And the file "app/views/layouts/application.html.erb" should not contain "turbolinks"
|
|
212
|
+
But the file "app/views/layouts/application.html.erb" should contain:
|
|
213
|
+
"""
|
|
214
|
+
<%= stylesheet_link_tag 'application', media: 'all' %>
|
|
215
|
+
<%= javascript_include_tag 'application' %>
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
# Config
|
|
221
|
+
And the file "config/application.rb" should contain "config.time_zone = 'Berlin'"
|
|
222
|
+
And the file "config/environments/development.rb" should contain "config.assets.debug = false"
|
|
223
|
+
And the file "config/environments/development.rb" should contain:
|
|
224
|
+
"""
|
|
225
|
+
config.middleware.use Rack::LiveReload
|
|
226
|
+
"""
|
|
227
|
+
And a file named "config/environments/staging.rb" should exist
|
|
228
|
+
And the file "config/database.yml" should contain exactly:
|
|
229
|
+
"""
|
|
230
|
+
common: &common
|
|
231
|
+
adapter: postgresql
|
|
232
|
+
encoding: unicode
|
|
233
|
+
host: localhost
|
|
234
|
+
username: katapult
|
|
235
|
+
password: secret
|
|
236
|
+
|
|
237
|
+
development:
|
|
238
|
+
<<: *common
|
|
239
|
+
database: katapult_test_app_development
|
|
240
|
+
|
|
241
|
+
test: &test
|
|
242
|
+
<<: *common
|
|
243
|
+
database: katapult_test_app_test<%= ENV['TEST_ENV_NUMBER'] %>
|
|
244
|
+
"""
|
|
245
|
+
|
|
246
|
+
And the file "config/database.sample.yml" should contain exactly:
|
|
247
|
+
"""
|
|
248
|
+
common: &common
|
|
249
|
+
adapter: postgresql
|
|
250
|
+
encoding: unicode
|
|
251
|
+
host: localhost
|
|
252
|
+
username: root
|
|
253
|
+
password:
|
|
254
|
+
|
|
255
|
+
development:
|
|
256
|
+
<<: *common
|
|
257
|
+
database: katapult_test_app_development
|
|
258
|
+
|
|
259
|
+
test:
|
|
260
|
+
<<: *common
|
|
261
|
+
database: katapult_test_app_test<%= ENV['TEST_ENV_NUMBER'] %>
|
|
262
|
+
"""
|
|
263
|
+
|
|
264
|
+
And the file "config/cucumber.yml" should contain:
|
|
265
|
+
"""
|
|
266
|
+
default: <%= std_opts %> features
|
|
267
|
+
wip: --tags @wip:3 --wip features
|
|
268
|
+
parallel: <%= std_opts %> features <%= log_failures %>
|
|
269
|
+
rerun: -r features --format pretty --strict <%= rerun_failures %> <%= log_failures %>
|
|
270
|
+
"""
|
|
271
|
+
And the file "config/deploy.rb" should contain:
|
|
272
|
+
"""
|
|
273
|
+
abort 'You must run this using "bundle exec ..."' unless ENV['BUNDLE_BIN_PATH'] || ENV['BUNDLE_GEMFILE']
|
|
274
|
+
|
|
275
|
+
# config valid only for current version of Capistrano
|
|
276
|
+
lock '3.4.0'
|
|
277
|
+
|
|
278
|
+
# Default value for :format is :pretty
|
|
279
|
+
# set :format, :pretty
|
|
280
|
+
|
|
281
|
+
set :log_level, :info # %i(debug info error), default: :debug
|
|
282
|
+
|
|
283
|
+
# Default value for :pty is false
|
|
284
|
+
# set :pty, true
|
|
285
|
+
|
|
286
|
+
# Default value for :linked_files is []
|
|
287
|
+
# set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml')
|
|
288
|
+
set :linked_files, %w(config/database.yml)
|
|
289
|
+
|
|
290
|
+
# Default value for linked_dirs is []
|
|
291
|
+
# set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
|
|
292
|
+
set :linked_dirs, %w(log public/system)
|
|
293
|
+
|
|
294
|
+
# Default value for default_env is {}
|
|
295
|
+
# set :default_env, { path: "/opt/ruby/bin:$PATH" }
|
|
296
|
+
|
|
297
|
+
set :application, 'katapult_test_app'
|
|
298
|
+
set :keep_releases, 10
|
|
299
|
+
set :ssh_options, {
|
|
300
|
+
forward_agent: true
|
|
301
|
+
}
|
|
302
|
+
set :scm, :git
|
|
303
|
+
set :repo_url, 'git@code.makandra.de:makandra/katapult_test_app.git'
|
|
304
|
+
|
|
305
|
+
# set :whenever_roles, :cron
|
|
306
|
+
# set :whenever_environment, defer { stage }
|
|
307
|
+
# set :whenever_command, 'bundle exec whenever'
|
|
308
|
+
|
|
309
|
+
set :maintenance_template_path, 'public/maintenance.html.erb'
|
|
310
|
+
"""
|
|
311
|
+
And the file "config/deploy/staging.rb" should contain:
|
|
312
|
+
"""
|
|
313
|
+
set :stage, :staging
|
|
314
|
+
|
|
315
|
+
set :deploy_to, '/var/www/katapult_test_app-staging'
|
|
316
|
+
set :rails_env, 'staging'
|
|
317
|
+
set :branch, ENV['DEPLOY_BRANCH'] || 'master'
|
|
318
|
+
|
|
319
|
+
# server 'example.com', user: 'deploy-user', roles: %w(app web cron db)
|
|
320
|
+
"""
|
|
321
|
+
And the file "config/deploy/production.rb" should contain exactly:
|
|
322
|
+
"""
|
|
323
|
+
set :stage, :production
|
|
324
|
+
|
|
325
|
+
set :deploy_to, '/var/www/katapult_test_app'
|
|
326
|
+
set :rails_env, 'production'
|
|
327
|
+
set :branch, 'production'
|
|
328
|
+
|
|
329
|
+
# server 'one.example.com', user: 'deploy-user', roles: %w(app web cron db)
|
|
330
|
+
# server 'two.example.com', user: 'deploy-user', roles: %w(app web)
|
|
331
|
+
"""
|
|
332
|
+
And the file "config/initializers/ext.rb" should contain exactly:
|
|
333
|
+
"""
|
|
334
|
+
Dir.glob(Rails.root.join('lib/ext/**/*.rb')).each do |filename|
|
|
335
|
+
require filename
|
|
336
|
+
end
|
|
337
|
+
"""
|
|
338
|
+
And the file "config/initializers/exception_notification.rb" should contain:
|
|
339
|
+
"""
|
|
340
|
+
ExceptionNotification.configure do |config|
|
|
341
|
+
|
|
342
|
+
config.add_notifier :email, {
|
|
343
|
+
email_prefix: '[katapult_test_app] ',
|
|
344
|
+
exception_recipients: %w[fail@makandra.de],
|
|
345
|
+
"""
|
|
346
|
+
And the file "config/secrets.yml" should contain:
|
|
347
|
+
"""
|
|
348
|
+
staging:
|
|
349
|
+
secret_key_base:
|
|
350
|
+
|
|
351
|
+
"""
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
# Lib
|
|
355
|
+
And the file "lib/capistrano/tasks/db.rake" should contain:
|
|
356
|
+
"""
|
|
357
|
+
namespace :db do
|
|
358
|
+
desc 'Warn about pending migrations'
|
|
359
|
+
task :warn_if_pending_migrations do
|
|
360
|
+
on primary :db do
|
|
361
|
+
within current_path do
|
|
362
|
+
with rails_env: fetch(:rails_env, 'production') do
|
|
363
|
+
rake 'db:warn_if_pending_migrations'
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
desc 'Do a dump of the DB on the remote machine using dumple'
|
|
370
|
+
task :dump do
|
|
371
|
+
on primary :db do
|
|
372
|
+
within current_path do
|
|
373
|
+
execute :dumple, '--fail-gently', fetch(:rails_env, 'production')
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
desc 'Show usage of ~/dumps/ on remote host'
|
|
379
|
+
task :show_dump_usage do
|
|
380
|
+
on primary :db do
|
|
381
|
+
info capture :dumple, '-i'
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
"""
|
|
386
|
+
And the file "lib/capistrano/tasks/deploy.rake" should contain:
|
|
387
|
+
"""
|
|
388
|
+
namespace :deploy do
|
|
389
|
+
desc 'Restart application'
|
|
390
|
+
task :restart do
|
|
391
|
+
invoke 'passenger:restart'
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
desc 'Show deployed revision'
|
|
395
|
+
task :revision do
|
|
396
|
+
on roles :app do
|
|
397
|
+
within current_path do
|
|
398
|
+
info "Revision: #{ capture :cat, 'REVISION' }"
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
"""
|
|
404
|
+
And the file "lib/capistrano/tasks/passenger.rake" should contain:
|
|
405
|
+
"""
|
|
406
|
+
namespace :passenger do
|
|
407
|
+
desc 'Restart Application'
|
|
408
|
+
task :restart do
|
|
409
|
+
on roles :app do
|
|
410
|
+
execute "sudo passenger-config restart-app --ignore-app-not-running #{ fetch(:deploy_to) }"
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
"""
|
|
415
|
+
And the file "lib/ext/active_record/find_by_anything.rb" should contain:
|
|
416
|
+
"""
|
|
417
|
+
ActiveRecord::Base.class_eval do
|
|
418
|
+
|
|
419
|
+
def self.find_by_anything(identifier)
|
|
420
|
+
"""
|
|
421
|
+
And the file "lib/ext/action_view/spec_label.rb" should contain:
|
|
422
|
+
"""
|
|
423
|
+
ActionView::Helpers::FormBuilder.class_eval do
|
|
424
|
+
|
|
425
|
+
def spec_label(field, text = nil, options = {})
|
|
426
|
+
"""
|
|
427
|
+
And the file "lib/ext/action_view/form_for_with_development_errors.rb" should contain:
|
|
428
|
+
"""
|
|
429
|
+
if Rails.env == 'development'
|
|
430
|
+
|
|
431
|
+
ActionView::Helpers::FormHelper.class_eval do
|
|
432
|
+
|
|
433
|
+
def form_for_with_development_errors(*args, &block)
|
|
434
|
+
"""
|
|
435
|
+
And the file "lib/ext/active_record/these.rb" should contain:
|
|
436
|
+
"""
|
|
437
|
+
ActiveRecord::Base.class_eval do
|
|
438
|
+
|
|
439
|
+
def self.these(arg)
|
|
440
|
+
where(id: arg.collect_ids)
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
end
|
|
444
|
+
"""
|
|
445
|
+
And the file "lib/ext/array/xss_aware_join.rb" should contain:
|
|
446
|
+
"""
|
|
447
|
+
Array.class_eval do
|
|
448
|
+
def xss_aware_join(delimiter = '')
|
|
449
|
+
''.html_safe.tap do |str|
|
|
450
|
+
each_with_index do |element, i|
|
|
451
|
+
str << delimiter if i > 0
|
|
452
|
+
str << element
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
"""
|
|
458
|
+
And the file "lib/ext/enumerable/natural_sort.rb" should contain:
|
|
459
|
+
"""
|
|
460
|
+
module Enumerable
|
|
461
|
+
|
|
462
|
+
def natural_sort
|
|
463
|
+
"""
|
|
464
|
+
And the file "lib/ext/hash/infinite.rb" should contain:
|
|
465
|
+
"""
|
|
466
|
+
class Hash
|
|
467
|
+
|
|
468
|
+
def self.infinite
|
|
469
|
+
new { |h, k| h[k] = new(&h.default_proc) }
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
end
|
|
473
|
+
"""
|
|
474
|
+
And the file "lib/ext/string/html_entities.rb" should contain:
|
|
475
|
+
"""
|
|
476
|
+
class String
|
|
477
|
+
|
|
478
|
+
def self.nbsp
|
|
479
|
+
' '
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
def self.ndash
|
|
483
|
+
'–'
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
end
|
|
487
|
+
"""
|
|
488
|
+
And the file "lib/ext/string/to_sort_atoms.rb" should contain:
|
|
489
|
+
"""
|
|
490
|
+
String.class_eval do
|
|
491
|
+
|
|
492
|
+
def to_sort_atoms
|
|
493
|
+
SmartSortAtom.parse(self)
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
end
|
|
497
|
+
"""
|
|
498
|
+
And the file "lib/tasks/pending_migrations.rake" should contain:
|
|
499
|
+
"""
|
|
500
|
+
pending_migrations = ActiveRecord::Migrator.new(:up, all_migrations).pending_migrations
|
|
501
|
+
|
|
502
|
+
if pending_migrations.any?
|
|
503
|
+
puts ''
|
|
504
|
+
puts '======================================================='
|
|
505
|
+
puts "You have #{ pending_migrations.size } pending migrations:"
|
|
506
|
+
"""
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
# Tests
|
|
510
|
+
And the file "features/support/env-custom.rb" should contain:
|
|
511
|
+
"""
|
|
512
|
+
require 'spreewald/all_steps'
|
|
513
|
+
"""
|
|
514
|
+
And the file "features/support/cucumber_factory.rb" should contain:
|
|
515
|
+
"""
|
|
516
|
+
Cucumber::Factory.add_steps(self)
|
|
517
|
+
"""
|
|
518
|
+
And the file "features/support/capybara_screenshot.rb" should contain:
|
|
519
|
+
"""
|
|
520
|
+
require 'capybara-screenshot/cucumber'
|
|
521
|
+
|
|
522
|
+
# Keep up to the number of screenshots specified in the hash
|
|
523
|
+
Capybara::Screenshot.prune_strategy = { keep: 10 }
|
|
524
|
+
"""
|
|
525
|
+
And the file "features/support/database_cleaner.rb" should contain:
|
|
526
|
+
"""
|
|
527
|
+
DatabaseCleaner.clean_with(:deletion) # clean once, now
|
|
528
|
+
DatabaseCleaner.strategy = :transaction
|
|
529
|
+
Cucumber::Rails::Database.javascript_strategy = :deletion
|
|
530
|
+
"""
|
|
531
|
+
And the file "features/support/factory_girl.rb" should contain:
|
|
532
|
+
"""
|
|
533
|
+
World(FactoryGirl::Syntax::Methods)
|
|
534
|
+
"""
|
|
535
|
+
And a file named "features/support/paths.rb" should exist
|
|
536
|
+
And a file named "features/support/selectors.rb" should exist
|
|
537
|
+
And the file "spec/rails_helper.rb" should match /^Dir.Rails.root.join.+spec.support/
|
|
538
|
+
And the file "spec/support/shoulda_matchers.rb" should contain:
|
|
539
|
+
"""
|
|
540
|
+
require 'shoulda/matchers'
|
|
541
|
+
|
|
542
|
+
Shoulda::Matchers.configure do |config|
|
|
543
|
+
config.integrate do |with|
|
|
544
|
+
with.test_framework :rspec
|
|
545
|
+
with.library :rails
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
"""
|
|
549
|
+
And the file "spec/support/factory_girl.rb" should contain:
|
|
550
|
+
"""
|
|
551
|
+
RSpec.configure do |config|
|
|
552
|
+
config.include FactoryGirl::Syntax::Methods
|
|
553
|
+
end
|
|
554
|
+
"""
|
|
555
|
+
And the file "spec/factories/factories.rb" should contain:
|
|
556
|
+
"""
|
|
557
|
+
FactoryGirl.define do
|
|
558
|
+
|
|
559
|
+
factory :EXAMPLE do
|
|
560
|
+
status 'pending'
|
|
561
|
+
uuid { SecureRandom.uuid }
|
|
562
|
+
sequence(:title) { |i| "Titel #{ i }"}
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
end
|
|
566
|
+
"""
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
# styles
|
|
571
|
+
And the file "app/assets/stylesheets/application.sass" should contain:
|
|
572
|
+
"""
|
|
573
|
+
@import compass
|
|
574
|
+
@import bootstrap
|
|
575
|
+
|
|
576
|
+
@import application/blocks/all
|
|
577
|
+
|
|
578
|
+
"""
|
|
579
|
+
And the file "app/assets/stylesheets/application/blocks/_all.sass" should contain exactly:
|
|
580
|
+
"""
|
|
581
|
+
@import items
|
|
582
|
+
@import layout
|
|
583
|
+
@import navigation
|
|
584
|
+
@import tools
|
|
585
|
+
|
|
586
|
+
"""
|
|
587
|
+
And a file named "app/assets/stylesheets/application/blocks/_items.sass" should exist
|
|
588
|
+
And a file named "app/assets/stylesheets/application/blocks/_layout.sass" should exist
|
|
589
|
+
And a file named "app/assets/stylesheets/application/blocks/_navigation.sass" should exist
|
|
590
|
+
And a file named "app/assets/stylesheets/application/blocks/_tools.sass" should exist
|
data/features/binary.feature
CHANGED
|
@@ -9,6 +9,7 @@ Feature: Katapult binary `katapult`
|
|
|
9
9
|
Then the output should contain "Creating new Rails application"
|
|
10
10
|
And the output should contain "Installing katapult"
|
|
11
11
|
And the output should contain "Generating katapult basics"
|
|
12
|
+
And the output should contain "Using rails 4.2.6"
|
|
12
13
|
And the output should contain:
|
|
13
14
|
"""
|
|
14
15
|
Application initialization done.
|
|
@@ -47,7 +48,7 @@ Feature: Katapult binary `katapult`
|
|
|
47
48
|
|
|
48
49
|
Scenario: Run without arguments
|
|
49
50
|
When I run `katapult # without arguments`
|
|
50
|
-
Then the output should contain "Usage: katapult [new APP_NAME | fire]"
|
|
51
|
+
Then the output should contain "Usage: katapult [new APP_NAME | fire [path/to/model] ]"
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
Scenario: Transform the application model
|
|
@@ -71,3 +72,34 @@ Feature: Katapult binary `katapult`
|
|
|
71
72
|
When I run `git log`
|
|
72
73
|
Then the output should contain "rails generate katapult:transform lib/katapult/application_model.rb"
|
|
73
74
|
And the output should contain "Author: katapult <katapult@makandra.com>"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
Scenario: Transform a custom application model
|
|
78
|
+
Given a pristine Rails application
|
|
79
|
+
And I install katapult
|
|
80
|
+
And I generate katapult basics
|
|
81
|
+
|
|
82
|
+
When I write to "lib/katapult/custom_model.rb" with:
|
|
83
|
+
"""
|
|
84
|
+
model 'custom'
|
|
85
|
+
"""
|
|
86
|
+
And I run `katapult fire lib/katapult/custom_model.rb`
|
|
87
|
+
Then the output should contain "Loading katapult"
|
|
88
|
+
And the output should contain "parse lib/katapult/custom_model"
|
|
89
|
+
And a file named "app/models/custom.rb" should exist
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
Scenario: When the transformation fails, an error message is printed
|
|
93
|
+
Given a pristine Rails application
|
|
94
|
+
And I install katapult
|
|
95
|
+
And I generate katapult basics
|
|
96
|
+
|
|
97
|
+
When I overwrite "lib/katapult/application_model.rb" with:
|
|
98
|
+
"""
|
|
99
|
+
model 'failing example' do |ex|
|
|
100
|
+
ex.attr :fail, type: :nonexistent
|
|
101
|
+
end
|
|
102
|
+
"""
|
|
103
|
+
And I run `katapult fire`
|
|
104
|
+
Then the output should not contain "Model transformation done"
|
|
105
|
+
But the output should contain "x Something went wrong"
|
data/features/model.feature
CHANGED
|
@@ -63,10 +63,13 @@ Feature: Generate Models
|
|
|
63
63
|
person.attr :hobby # string is default
|
|
64
64
|
|
|
65
65
|
# Special types
|
|
66
|
-
person.attr :email # type is detected as email
|
|
66
|
+
person.attr :email # type is auto-detected as email
|
|
67
67
|
person.attr :income, type: :money
|
|
68
68
|
person.attr :homepage, type: :url, default: 'http://www.makandra.de'
|
|
69
69
|
person.attr :locked, type: :flag, default: false
|
|
70
|
+
person.attr :hobbies, type: :text
|
|
71
|
+
person.attr :indexable_json, type: :json
|
|
72
|
+
person.attr :plain_json, type: :plain_json
|
|
70
73
|
end
|
|
71
74
|
"""
|
|
72
75
|
And I successfully transform the application model
|
|
@@ -94,6 +97,9 @@ Feature: Generate Models
|
|
|
94
97
|
t.decimal :income, precision: 10, scale: 2
|
|
95
98
|
t.string :homepage
|
|
96
99
|
t.boolean :locked
|
|
100
|
+
t.text :hobbies
|
|
101
|
+
t.jsonb :indexable_json
|
|
102
|
+
t.json :plain_json
|
|
97
103
|
|
|
98
104
|
t.timestamps null: false
|
|
99
105
|
end
|
|
@@ -223,24 +229,14 @@ Feature: Generate Models
|
|
|
223
229
|
"""
|
|
224
230
|
Rails.application.routes.draw do
|
|
225
231
|
root 'cars#index'
|
|
226
|
-
resources :cars
|
|
227
|
-
member do
|
|
228
|
-
end
|
|
229
|
-
collection do
|
|
230
|
-
end
|
|
231
|
-
end
|
|
232
|
+
resources :cars
|
|
232
233
|
"""
|
|
233
234
|
And I successfully transform the application model
|
|
234
235
|
Then the file named "config/routes.rb" should contain:
|
|
235
236
|
"""
|
|
236
237
|
Rails.application.routes.draw do
|
|
237
238
|
root 'cars#index'
|
|
238
|
-
resources :cars
|
|
239
|
-
member do
|
|
240
|
-
end
|
|
241
|
-
collection do
|
|
242
|
-
end
|
|
243
|
-
end
|
|
239
|
+
resources :cars
|
|
244
240
|
"""
|
|
245
241
|
And the file named "config/routes.rb" should contain "root 'cars#index'" exactly once
|
|
246
242
|
And the file named "config/routes.rb" should contain "resources :cars" exactly once
|