voyage 1.44.0.6 → 1.44.0.7
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/TODO.md +4 -0
- data/lib/voyage/README.md +26 -0
- data/lib/voyage/app_builder.rb +293 -91
- data/lib/voyage/generators/app_generator.rb +5 -0
- data/lib/voyage/templates/Gemfile.erb +38 -28
- data/lib/voyage/templates/README.md.erb +17 -12
- data/lib/voyage/templates/admin_users_controller.rb +40 -0
- data/lib/voyage/templates/analytics_alias.html.erb.erb +18 -0
- data/lib/voyage/templates/analytics_identify.html.erb.erb +42 -0
- data/lib/voyage/templates/analytics_ruby_initializer.rb +15 -0
- data/lib/voyage/templates/devise_registrations_controller.rb +17 -0
- data/lib/voyage/templates/rubocop.yml +11 -2
- data/lib/voyage/templates/seeder.rb.erb +3 -1
- data/lib/voyage/templates/seeds.rb.erb +1 -1
- data/lib/voyage/templates/users_index.html.erb +28 -0
- data/lib/voyage/templates/voyage_layout.html.erb.erb +43 -0
- data/lib/voyage/version.rb +1 -1
- metadata +10 -3
- data/lib/voyage/templates/users_index.html.slim.erb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3069f490551d031bd77d95c0f11fafd36608a7c
|
4
|
+
data.tar.gz: 2cf4fe7cc391b8a195be17da2d72bf849d216cd1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa91712c84e2ef27758b693e36ef471788611f97c99454285a2662bd596fae2fa7f24142bcf622f05b74a46b1ac3c8d8e8519bb6ffb8ff99eea752a1c7229201
|
7
|
+
data.tar.gz: c4812939c3c07301063aaf17baaa4cfee6af9c38b052baad26334f283df7077478c1600978cbfe4f30f580b2cb767c9ff9d6178bf6abeb16853a79f1e03a362f
|
data/TODO.md
ADDED
data/lib/voyage/README.md
CHANGED
@@ -20,3 +20,29 @@ Everything else is a new file we want to add.
|
|
20
20
|
## Testing
|
21
21
|
|
22
22
|
Test that the new generator works, manually for now. It'd be awesome to get some [aruba](https://github.com/cucumber/aruba) tests going to test the various command line options / generated app permutations that are possible. For example, with and without devise, which templating language we should use, etc.
|
23
|
+
|
24
|
+
## Pushing a new release
|
25
|
+
|
26
|
+
* Bump the version file: `lib/voyage/version.rb`
|
27
|
+
|
28
|
+
VERSION = '1.44.0.6'.freeze
|
29
|
+
|
30
|
+
* Tag the current commits on master BEFORE squashing (in case we want to refer to that diff history). Add a good commit message with what was done.
|
31
|
+
|
32
|
+
git tag -a 1.44.0.6-voyage
|
33
|
+
|
34
|
+
* Squash all new commits (assumed 3 here) into the 2 main commits (for a total of 5)
|
35
|
+
|
36
|
+
git rebase -i HEAD~5
|
37
|
+
|
38
|
+
* Force push the changes to master
|
39
|
+
|
40
|
+
git push --force-with-lease --no-verify
|
41
|
+
|
42
|
+
* Build the gem
|
43
|
+
|
44
|
+
gem build suspenders.gemspec
|
45
|
+
|
46
|
+
* Publish to rubygems
|
47
|
+
|
48
|
+
gem push voyage-1.44.0.6.gem
|
data/lib/voyage/app_builder.rb
CHANGED
@@ -17,20 +17,24 @@ module Suspenders
|
|
17
17
|
|
18
18
|
def update_gemset_in_gemfile
|
19
19
|
replace_in_file 'Gemfile', '#ruby-gemset', "#ruby-gemset=#{app_name}"
|
20
|
+
|
21
|
+
# Remove commented out lines from template
|
22
|
+
gsub_file('Gemfile', /^\s{2}\n/, '')
|
20
23
|
end
|
21
24
|
|
22
25
|
def use_slim
|
23
26
|
if @@accept_defaults || agree?('Would you like to use slim? (Y/n)')
|
24
27
|
@@use_slim = true
|
25
28
|
run 'gem install html2slim'
|
26
|
-
|
29
|
+
update_application_rb_for_slim
|
27
30
|
else
|
28
31
|
@@use_slim = false
|
32
|
+
gsub_file('Gemfile', /^gem 'slim-rails'\n/, '')
|
29
33
|
end
|
30
34
|
end
|
31
35
|
|
32
36
|
def update_application_layout_for_slim
|
33
|
-
find = <<-RUBY.gsub(/^ {
|
37
|
+
find = <<-RUBY.gsub(/^ {4}/, '')
|
34
38
|
<%#
|
35
39
|
Configure default and controller-, and view-specific titles in
|
36
40
|
config/locales/en.yml. For more see:
|
@@ -38,10 +42,10 @@ module Suspenders
|
|
38
42
|
%>
|
39
43
|
RUBY
|
40
44
|
|
41
|
-
replace = <<-RUBY.gsub(/^ {
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
+
replace = <<-RUBY.gsub(/^ {8}/, '')
|
46
|
+
<% # Configure default and controller-, and view-specific titles in
|
47
|
+
# config/locales/en.yml. For more see:
|
48
|
+
# https://github.com/calebthompson/title#usage %>
|
45
49
|
RUBY
|
46
50
|
|
47
51
|
replace_in_file 'app/views/layouts/application.html.erb', find, replace
|
@@ -49,9 +53,6 @@ module Suspenders
|
|
49
53
|
inside('lib') do # arbitrary, run in context of newly generated app
|
50
54
|
run "erb2slim '../app/views/layouts' '../app/views/layouts'"
|
51
55
|
run "erb2slim -d '../app/views/layouts'"
|
52
|
-
|
53
|
-
run "erb2slim '../app/views/application' '../app/views/application'"
|
54
|
-
run "erb2slim -d '../app/views/application'"
|
55
56
|
end
|
56
57
|
|
57
58
|
# strip trailing space after closing "> in application layout before
|
@@ -60,32 +61,23 @@ module Suspenders
|
|
60
61
|
|
61
62
|
find = <<-RUBY.gsub(/^ {6}/, '')
|
62
63
|
| <body class="
|
64
|
+
= devise_controller? ? 'devise' : 'application'
|
63
65
|
= body_class
|
64
66
|
| ">
|
65
67
|
RUBY
|
66
68
|
|
67
69
|
replace = <<-RUBY.gsub(/^ {6}/, '')
|
68
|
-
body class="\#{body_class}"
|
70
|
+
body class="\#{devise_controller? ? 'devise' : 'application'} \#{body_class}"
|
69
71
|
RUBY
|
70
72
|
|
71
73
|
replace_in_file 'app/views/layouts/application.html.slim', find, replace
|
74
|
+
end
|
72
75
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
RUBY
|
79
|
-
|
80
|
-
# Bump renders in to be nested within body
|
81
|
-
replace = <<-RUBY.gsub(/^ {6}/, '')
|
82
|
-
= render "flashes"
|
83
|
-
= yield
|
84
|
-
= render "javascript"
|
85
|
-
= render "css_overrides"
|
86
|
-
RUBY
|
87
|
-
|
88
|
-
replace_in_file 'app/views/layouts/application.html.slim', find, replace
|
76
|
+
def update_application_rb_for_slim
|
77
|
+
inject_into_file "config/application.rb", after: " g.fixture_replacement :factory_girl, dir: 'spec/factories'\n" do <<-'RUBY'.gsub(/^ {2}/, '')
|
78
|
+
g.template_engine :slim
|
79
|
+
RUBY
|
80
|
+
end
|
89
81
|
end
|
90
82
|
|
91
83
|
# ------------
|
@@ -93,17 +85,20 @@ module Suspenders
|
|
93
85
|
# ------------
|
94
86
|
def install_devise
|
95
87
|
if @@accept_defaults || agree?('Would you like to install Devise? (Y/n)')
|
88
|
+
@@use_devise = true
|
96
89
|
bundle_command 'exec rails generate devise:install'
|
97
90
|
|
98
91
|
if @@accept_defaults || agree?("Would you like to add first_name and last_name to the devise model? (Y/n)")
|
99
92
|
adding_first_and_last_name = true
|
100
93
|
|
101
|
-
bundle_command "exec rails generate resource user first_name:string last_name:string"
|
94
|
+
bundle_command "exec rails generate resource user first_name:string last_name:string uuid:string"
|
102
95
|
|
103
96
|
replace_in_file 'spec/factories/users.rb',
|
104
97
|
'first_name "MyString"', 'first_name { Faker::Name.first_name }'
|
105
98
|
replace_in_file 'spec/factories/users.rb',
|
106
99
|
'last_name "MyString"', 'last_name { Faker::Name.last_name }'
|
100
|
+
replace_in_file 'spec/factories/users.rb',
|
101
|
+
'uuid "MyString"', 'uuid { SecureRandom.uuid }'
|
107
102
|
end
|
108
103
|
|
109
104
|
bundle_command "exec rails generate devise user"
|
@@ -118,12 +113,14 @@ module Suspenders
|
|
118
113
|
|
119
114
|
customize_devise_views if adding_first_and_last_name
|
120
115
|
customize_application_controller_for_devise(adding_first_and_last_name)
|
116
|
+
add_devise_registrations_controller
|
121
117
|
customize_resource_controller_for_devise(adding_first_and_last_name)
|
122
|
-
|
118
|
+
add_admin_views_for_devise_resource(adding_first_and_last_name)
|
119
|
+
add_analytics_initializer
|
123
120
|
authorize_devise_resource_for_index_action
|
124
121
|
add_canard_roles_to_devise_resource
|
125
122
|
update_devise_initializer
|
126
|
-
|
123
|
+
add_custom_routes_for_devise
|
127
124
|
customize_user_factory(adding_first_and_last_name)
|
128
125
|
generate_seeder_templates(using_devise: true)
|
129
126
|
customize_user_spec
|
@@ -153,13 +150,67 @@ module Suspenders
|
|
153
150
|
end
|
154
151
|
|
155
152
|
def customize_application_controller_for_devise(adding_first_and_last_name)
|
153
|
+
inject_into_file 'app/controllers/application_controller.rb', before: "class ApplicationController < ActionController::Base" do <<-RUBY.gsub(/^ {8}/, '')
|
154
|
+
# rubocop:disable Metrics/ClassLength, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/LineLength
|
155
|
+
RUBY
|
156
|
+
end
|
157
|
+
|
156
158
|
inject_into_file 'app/controllers/application_controller.rb', after: " protect_from_forgery with: :exception" do <<-RUBY.gsub(/^ {6}/, '')
|
157
159
|
|
160
|
+
check_authorization unless: :devise_or_pages_controller?
|
161
|
+
impersonates :user
|
162
|
+
|
158
163
|
before_action :configure_permitted_parameters, if: :devise_controller?
|
164
|
+
before_action :authenticate_user!, unless: -> { is_a?(HighVoltage::PagesController) }
|
165
|
+
before_action :add_layout_name_to_gon
|
166
|
+
before_action :detect_device_type
|
167
|
+
|
168
|
+
rescue_from CanCan::AccessDenied do |exception|
|
169
|
+
redirect_to root_path, alert: exception.message
|
170
|
+
end
|
171
|
+
|
172
|
+
# Example Traditional Event: analytics_track(user, 'Created Widget', { widget_name: 'foo' })
|
173
|
+
# Example Page View: analytics_track(user, 'Page Viewed', { page_name: 'Terms and Conditions', url: '/terms' })
|
174
|
+
#
|
175
|
+
# NOTE: setup some defaults that we want to track on every event mixpanel_track
|
176
|
+
# NOTE: the identify step happens on every page load to keep intercom.io and mixpanel people up to date
|
177
|
+
def analytics_track(user, event_name, options = {})
|
178
|
+
return if user.tester?
|
179
|
+
|
180
|
+
sanitized_options = sanitize_hash_javascript(options)
|
181
|
+
|
182
|
+
segment_attributes = {
|
183
|
+
user_id: user.uuid,
|
184
|
+
event: event_name,
|
185
|
+
properties: {
|
186
|
+
browser: "\#{browser.name rescue 'unknown'}",
|
187
|
+
browser_id: "\#{browser.id rescue 'unknown'}",
|
188
|
+
browser_version: "\#{browser.version rescue 'unknown'}",
|
189
|
+
platform: "\#{browser.platform rescue 'unknown'}",
|
190
|
+
roles: "\#{user.roles.map(&:to_s).join(',') rescue ''}",
|
191
|
+
rails_env: Rails.env.to_s,
|
192
|
+
}.merge(sanitized_options),
|
193
|
+
}
|
194
|
+
|
195
|
+
Analytics.track(segment_attributes)
|
196
|
+
end
|
159
197
|
|
160
198
|
protected
|
161
199
|
|
162
|
-
|
200
|
+
def devise_or_pages_controller?
|
201
|
+
devise_controller? || is_a?(HighVoltage::PagesController)
|
202
|
+
end
|
203
|
+
|
204
|
+
def sanitize_hash_javascript(hash)
|
205
|
+
hash.deep_stringify_keys
|
206
|
+
.deep_transform_keys { |k| sanitize_javascript(k) }
|
207
|
+
.transform_values { |v| sanitize_javascript(v) }
|
208
|
+
end
|
209
|
+
|
210
|
+
def sanitize_javascript(value)
|
211
|
+
value.is_a?(String) ? ActionView::Base.new.escape_javascript(value) : value
|
212
|
+
end
|
213
|
+
|
163
214
|
def configure_permitted_parameters
|
164
215
|
devise_parameter_sanitizer.permit(
|
165
216
|
:sign_up,
|
@@ -192,33 +243,79 @@ module Suspenders
|
|
192
243
|
],
|
193
244
|
)
|
194
245
|
end
|
195
|
-
|
246
|
+
|
247
|
+
def add_layout_name_to_gon
|
248
|
+
gon.layout =
|
249
|
+
case devise_controller?
|
250
|
+
when true
|
251
|
+
'devise'
|
252
|
+
else
|
253
|
+
'application'
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def detect_device_type
|
258
|
+
request.variant =
|
259
|
+
case request.user_agent
|
260
|
+
when /iPad/i
|
261
|
+
:tablet
|
262
|
+
when /iPhone/i
|
263
|
+
:phone
|
264
|
+
when /Android/i && /mobile/i
|
265
|
+
:phone
|
266
|
+
when /Android/i
|
267
|
+
:tablet
|
268
|
+
when /Windows Phone/i
|
269
|
+
:phone
|
270
|
+
end
|
271
|
+
end
|
196
272
|
RUBY
|
197
273
|
end
|
198
274
|
end
|
199
275
|
|
276
|
+
def add_devise_registrations_controller
|
277
|
+
template '../templates/devise_registrations_controller.rb',
|
278
|
+
'app/controllers/devise_customizations/registrations_controller.rb'
|
279
|
+
end
|
280
|
+
|
281
|
+
|
282
|
+
def add_analytics_initializer
|
283
|
+
template '../templates/analytics_ruby_initializer.rb', 'config/initializers/analytics_ruby.rb'
|
284
|
+
template '../templates/analytics_alias.html.erb.erb', 'app/views/users/analytics_alias.html.erb'
|
285
|
+
end
|
286
|
+
|
200
287
|
def customize_resource_controller_for_devise(adding_first_and_last_name)
|
201
288
|
bundle_command 'exec rails generate controller users'
|
202
289
|
run 'rm spec/controllers/users_controller_spec.rb'
|
203
290
|
|
204
|
-
inject_into_class
|
291
|
+
inject_into_class 'app/controllers/users_controller.rb', 'UsersController' do <<-RUBY.gsub(/^ {6}/, '')
|
205
292
|
# https://github.com/CanCanCommunity/cancancan/wiki/authorizing-controller-actions
|
206
|
-
load_and_authorize_resource only: [
|
207
|
-
|
208
|
-
end
|
293
|
+
# load_and_authorize_resource only: []
|
294
|
+
skip_authorization_check only: [:analytics_alias]
|
209
295
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
resources :users
|
214
|
-
RUBY
|
296
|
+
def analytics_alias
|
297
|
+
# view file has JS that will identify the anonymous user through segment
|
298
|
+
# after registration via "after devise registration path"
|
215
299
|
end
|
300
|
+
RUBY
|
216
301
|
end
|
217
302
|
end
|
218
303
|
|
219
|
-
def
|
304
|
+
def add_admin_views_for_devise_resource(adding_first_and_last_name)
|
220
305
|
config = { adding_first_and_last_name: adding_first_and_last_name }
|
221
|
-
template '../templates/users_index.html.
|
306
|
+
template '../templates/users_index.html.erb', 'app/views/admin/users/index.html.erb', config
|
307
|
+
|
308
|
+
if @@use_slim
|
309
|
+
inside('lib') do # arbitrary, run in context of newly generated app
|
310
|
+
run "erb2slim '../app/views/users' '../app/views/users'"
|
311
|
+
run "erb2slim -d '../app/views/users'"
|
312
|
+
|
313
|
+
run "erb2slim '../app/views/admin/users' '../app/views/admin/users'"
|
314
|
+
run "erb2slim -d '../app/views/admin/users'"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
template '../templates/admin_users_controller.rb', 'app/controllers/admin/users_controller.rb'
|
222
319
|
end
|
223
320
|
|
224
321
|
def authorize_devise_resource_for_index_action
|
@@ -229,6 +326,25 @@ module Suspenders
|
|
229
326
|
replace_in_file "spec/abilities/#{resource_name}_spec.rb", "require 'cancan/matchers'", "require_relative '../support/matchers/custom_cancan'"
|
230
327
|
end
|
231
328
|
|
329
|
+
find = <<-RUBY.gsub(/^ {4}/, '')
|
330
|
+
it { is_expected.to be_able_to(:manage, user) }
|
331
|
+
RUBY
|
332
|
+
replace = <<-RUBY.gsub(/^ {4}/, '')
|
333
|
+
it { is_expected.to be_able_to(:manage, acting_user) }
|
334
|
+
it { is_expected.to_not be_able_to(:manage, user) }
|
335
|
+
RUBY
|
336
|
+
replace_in_file 'spec/abilities/users_spec.rb', find, replace
|
337
|
+
|
338
|
+
find = <<-RUBY.gsub(/^ {6}/, '')
|
339
|
+
can [:manage], User
|
340
|
+
RUBY
|
341
|
+
replace = <<-RUBY.gsub(/^ {6}/, '')
|
342
|
+
can [:manage], User do |u|
|
343
|
+
u == user
|
344
|
+
end
|
345
|
+
RUBY
|
346
|
+
replace_in_file 'app/abilities/users.rb', find, replace
|
347
|
+
|
232
348
|
generate 'migration add_roles_mask_to_users roles_mask:integer'
|
233
349
|
template '../templates/custom_cancan_matchers.rb', 'spec/support/matchers/custom_cancan.rb'
|
234
350
|
end
|
@@ -236,11 +352,42 @@ module Suspenders
|
|
236
352
|
def add_canard_roles_to_devise_resource
|
237
353
|
inject_into_file 'app/models/user.rb', before: /^end/ do <<-RUBY.gsub(/^ {6}/, '')
|
238
354
|
|
355
|
+
before_create :generate_uuid
|
356
|
+
|
239
357
|
# Permissions cascade/inherit through the roles listed below. The order of
|
240
358
|
# this list is important, it should progress from least to most privelage
|
241
359
|
ROLES = [:admin].freeze
|
242
360
|
acts_as_user roles: ROLES
|
243
361
|
roles ROLES
|
362
|
+
|
363
|
+
validates :email,
|
364
|
+
presence: true,
|
365
|
+
format: /\\A[-a-z0-9_+\\.]+\\@([-a-z0-9]+\\.)+[a-z0-9]{2,8}\\z/i,
|
366
|
+
uniqueness: true
|
367
|
+
|
368
|
+
# NOTE: these password validations won't run if the user has an invite token
|
369
|
+
validates :password,
|
370
|
+
presence: true,
|
371
|
+
length: { within: 8..72 },
|
372
|
+
confirmation: true,
|
373
|
+
on: :create
|
374
|
+
validates :password_confirmation,
|
375
|
+
presence: true,
|
376
|
+
on: :create
|
377
|
+
|
378
|
+
def tester?
|
379
|
+
(email =~ /(example.com|headway.io)$/).present?
|
380
|
+
end
|
381
|
+
|
382
|
+
private
|
383
|
+
|
384
|
+
def generate_uuid
|
385
|
+
loop do
|
386
|
+
uuid = SecureRandom.uuid
|
387
|
+
self.uuid = uuid
|
388
|
+
break unless User.exists?(uuid: uuid)
|
389
|
+
end
|
390
|
+
end
|
244
391
|
RUBY
|
245
392
|
end
|
246
393
|
end
|
@@ -254,23 +401,53 @@ module Suspenders
|
|
254
401
|
"config.mailer_sender = 'user@example.com'"
|
255
402
|
end
|
256
403
|
|
257
|
-
def
|
258
|
-
|
404
|
+
def add_custom_routes_for_devise
|
405
|
+
find = <<-RUBY.gsub(/^ {6}/, '')
|
406
|
+
devise_for :users
|
407
|
+
resources :users
|
408
|
+
RUBY
|
409
|
+
|
410
|
+
replace = <<-RUBY.gsub(/^ {6}/, '')
|
411
|
+
devise_for :users, controllers: {
|
412
|
+
registrations: 'devise_customizations/registrations',
|
413
|
+
}
|
414
|
+
|
415
|
+
resources :users do
|
416
|
+
member do
|
417
|
+
get 'analytics_alias'
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
namespace :admin do
|
422
|
+
resources :users do
|
423
|
+
member do
|
424
|
+
get 'impersonate'
|
425
|
+
end
|
426
|
+
|
427
|
+
collection do
|
428
|
+
get 'stop_impersonating'
|
429
|
+
end
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
259
433
|
authenticated :user do
|
260
434
|
# root to: 'dashboard#show', as: :authenticated_root
|
435
|
+
root to: 'high_voltage/pages#show', id: 'welcome', as: :authenticated_root
|
261
436
|
end
|
262
437
|
|
263
438
|
devise_scope :user do
|
264
439
|
get 'sign-in', to: 'devise/sessions#new'
|
265
440
|
get 'sign-out', to: 'devise/sessions#destroy'
|
266
441
|
end
|
267
|
-
|
268
|
-
|
442
|
+
RUBY
|
443
|
+
|
444
|
+
replace_in_file 'config/routes.rb', find, replace
|
269
445
|
end
|
270
446
|
|
271
447
|
def customize_user_factory(adding_first_and_last_name)
|
272
448
|
inject_into_file 'spec/factories/users.rb', before: /^ end/ do <<-'RUBY'.gsub(/^ {4}/, '')
|
273
|
-
password '
|
449
|
+
password 'asdfjkl123'
|
450
|
+
password_confirmation 'asdfjkl123'
|
274
451
|
sequence(:email) { |n| "user_#{n}@example.com" }
|
275
452
|
|
276
453
|
trait :admin do
|
@@ -311,6 +488,26 @@ module Suspenders
|
|
311
488
|
end
|
312
489
|
end
|
313
490
|
end
|
491
|
+
|
492
|
+
describe 'validations' do
|
493
|
+
it { is_expected.to validate_presence_of(:email) }
|
494
|
+
it { is_expected.to validate_presence_of(:password) }
|
495
|
+
it { is_expected.to validate_presence_of(:password_confirmation) }
|
496
|
+
end
|
497
|
+
|
498
|
+
context '#tester?' do
|
499
|
+
['example.com', 'headway.io'].each do |domain|
|
500
|
+
it "an email including the \#{domain} domain is a tester" do
|
501
|
+
user = build(:user, email: "asdf@\#{domain}")
|
502
|
+
expect(user.tester?).to eq(true)
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
it 'an email including the gmail.com domain is NOT a tester' do
|
507
|
+
user = build(:user, email: 'asdf@gmail.com')
|
508
|
+
expect(user.tester?).to eq(false)
|
509
|
+
end
|
510
|
+
end
|
314
511
|
RUBY
|
315
512
|
|
316
513
|
replace_in_file 'spec/models/user_spec.rb', find, replace
|
@@ -318,11 +515,21 @@ module Suspenders
|
|
318
515
|
|
319
516
|
def customize_application_js
|
320
517
|
template '../templates/application.js', 'app/assets/javascripts/application.js', force: true
|
518
|
+
|
519
|
+
inject_into_file 'app/views/application/_javascript.html.erb', after: '<%= render "analytics" %>' do <<-RUBY.gsub(/^ {8}/, '')
|
520
|
+
|
521
|
+
<%= render "analytics_identify" %>
|
522
|
+
RUBY
|
523
|
+
end
|
321
524
|
end
|
322
525
|
|
323
526
|
def require_files_in_lib
|
324
|
-
create_file 'config/initializers/require_files_in_lib.rb'
|
325
|
-
|
527
|
+
create_file 'config/initializers/require_files_in_lib.rb' do <<-RUBY.gsub(/^ {8}/, '')
|
528
|
+
# rubocop:disable Rails/FilePath
|
529
|
+
Dir[File.join(Rails.root, 'lib', '**', '*.rb')].each { |l| require l }
|
530
|
+
# rubocop:enable Rails/FilePath
|
531
|
+
RUBY
|
532
|
+
end
|
326
533
|
end
|
327
534
|
|
328
535
|
def generate_ruby_version_and_gemset
|
@@ -352,6 +559,7 @@ module Suspenders
|
|
352
559
|
end
|
353
560
|
end
|
354
561
|
|
562
|
+
|
355
563
|
# --------
|
356
564
|
# TEMP FIX
|
357
565
|
# https://github.com/thoughtbot/bourbon/issues/993
|
@@ -372,55 +580,31 @@ module Suspenders
|
|
372
580
|
# -------------------------
|
373
581
|
def generate_refills
|
374
582
|
if @@accept_defaults || agree?('Would you like to install default Refill components? (Y/n)')
|
583
|
+
@@add_refills = true
|
584
|
+
|
375
585
|
bundle_command 'exec rails generate refills:import navigation'
|
376
586
|
bundle_command 'exec rails generate refills:import footer'
|
377
587
|
|
378
|
-
|
379
|
-
|
588
|
+
add_admin_links_to_navigation
|
589
|
+
|
380
590
|
add_refills_to_stylesheets
|
591
|
+
else
|
592
|
+
@@add_refills = false
|
381
593
|
end
|
382
594
|
end
|
383
595
|
|
384
|
-
def
|
385
|
-
|
386
|
-
|
387
|
-
run "erb2slim -d '../app/views/refills'"
|
388
|
-
end
|
596
|
+
def add_admin_links_to_navigation
|
597
|
+
return unless @@use_devise
|
598
|
+
inject_into_file 'app/views/refills/_navigation.html.erb', after: ' <li class="nav-link"><a href="javascript:void(0)">Contact</a></li>' do <<-RUBY
|
389
599
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
div class="flash-\#{key}"
|
399
|
-
= value
|
400
|
-
RUBY
|
401
|
-
|
402
|
-
replace_in_file 'app/views/application/_flashes.html.slim', find, replace
|
403
|
-
end
|
404
|
-
|
405
|
-
def add_refills_to_layout
|
406
|
-
if @@use_slim
|
407
|
-
inject_into_file 'app/views/layouts/application.html.slim', before: ' = yield' do <<-RUBY.gsub(/^ {8}/, '')
|
408
|
-
= render 'refills/navigation'
|
409
|
-
RUBY
|
410
|
-
end
|
411
|
-
inject_into_file 'app/views/layouts/application.html.slim', before: ' = render "javascript"' do <<-RUBY.gsub(/^ {8}/, '')
|
412
|
-
= render 'refills/footer'
|
413
|
-
RUBY
|
414
|
-
end
|
415
|
-
else
|
416
|
-
inject_into_file 'app/views/layouts/application.html.erb', before: ' <%= yield %>' do <<-RUBY.gsub(/^ {8}/, '')
|
417
|
-
<%= render 'refills/navigation' %>
|
418
|
-
RUBY
|
419
|
-
end
|
420
|
-
inject_into_file 'app/views/layouts/application.html.erb', before: ' <%= render "javascript" %>' do <<-RUBY.gsub(/^ {8}/, '')
|
421
|
-
<%= render 'refills/footer' %>
|
422
|
-
RUBY
|
423
|
-
end
|
600
|
+
<% if current_user && true_user.admin? %>
|
601
|
+
<% if current_user != true_user %>
|
602
|
+
<li class='nav-link'><%= link_to 'Stop Impersonating', stop_impersonating_admin_users_path %></li>
|
603
|
+
<% else %>
|
604
|
+
<li class="nav-link"><a href="/admin/users">Admin</a></li>
|
605
|
+
<% end %>
|
606
|
+
<% end %>
|
607
|
+
RUBY
|
424
608
|
end
|
425
609
|
end
|
426
610
|
|
@@ -451,6 +635,16 @@ module Suspenders
|
|
451
635
|
end
|
452
636
|
|
453
637
|
template "../templates/rails_helper.rb.erb", "spec/rails_helper.rb", force: true
|
638
|
+
|
639
|
+
%w(test development).each do |environment|
|
640
|
+
inject_into_file "config/environments/#{environment}.rb", after: /^end/ do <<-RUBY.gsub(/^ {10}/, '')
|
641
|
+
|
642
|
+
# NOTE: console can use create(:factory_name), or build(:factory_name) without
|
643
|
+
# needing to use FactoryGirl.create(:factory_name).
|
644
|
+
include FactoryGirl::Syntax::Methods
|
645
|
+
RUBY
|
646
|
+
end
|
647
|
+
end
|
454
648
|
end
|
455
649
|
|
456
650
|
def add_rubocop_config
|
@@ -507,6 +701,7 @@ module Suspenders
|
|
507
701
|
###############################
|
508
702
|
def configure_generators
|
509
703
|
config = <<-RUBY.gsub(/^ {4}/, '')
|
704
|
+
|
510
705
|
config.generators do |g|
|
511
706
|
g.helper false
|
512
707
|
g.javascript_engine false
|
@@ -516,8 +711,8 @@ module Suspenders
|
|
516
711
|
g.test_framework :rspec
|
517
712
|
g.view_specs false
|
518
713
|
g.fixture_replacement :factory_girl, dir: 'spec/factories'
|
519
|
-
g.template_engine :slim
|
520
714
|
end
|
715
|
+
|
521
716
|
RUBY
|
522
717
|
|
523
718
|
inject_into_class 'config/application.rb', 'Application', config
|
@@ -527,6 +722,13 @@ module Suspenders
|
|
527
722
|
create_file '.ruby-version', "#{Voyage::RUBY_VERSION}\n"
|
528
723
|
end
|
529
724
|
|
725
|
+
def overwrite_application_layout
|
726
|
+
template '../templates/voyage_layout.html.erb.erb', 'app/views/layouts/application.html.erb', force: true, add_refills: @@add_refills
|
727
|
+
update_application_layout_for_slim if @@use_slim
|
728
|
+
|
729
|
+
template '../templates/analytics_identify.html.erb.erb', 'app/views/application/_analytics_identify.html.erb', force: true
|
730
|
+
end
|
731
|
+
|
530
732
|
# --------------------------------
|
531
733
|
# setup_test_environment overrides
|
532
734
|
# --------------------------------
|
@@ -33,6 +33,7 @@ module Suspenders
|
|
33
33
|
invoke :add_high_voltage_static_pages
|
34
34
|
invoke :downgrade_neat_1_8_so_refills_media_mixin_works # this should be temporary until they get refills re-written to take advantage of Neat 2.0
|
35
35
|
invoke :generate_refills
|
36
|
+
invoke :overwrite_application_layout
|
36
37
|
invoke :generate_test_environment
|
37
38
|
invoke :update_test_environment
|
38
39
|
invoke :add_rubocop_config
|
@@ -90,6 +91,10 @@ module Suspenders
|
|
90
91
|
build :generate_refills
|
91
92
|
end
|
92
93
|
|
94
|
+
def overwrite_application_layout
|
95
|
+
build :overwrite_application_layout
|
96
|
+
end
|
97
|
+
|
93
98
|
def generate_test_environment
|
94
99
|
build :generate_test_environment
|
95
100
|
end
|
@@ -13,7 +13,8 @@ gem "normalize-rails", "~> 3.0.0"
|
|
13
13
|
gem "pg"
|
14
14
|
gem "puma"
|
15
15
|
gem "rack-canonical-host"
|
16
|
-
gem "rails", "<%= Voyage::RAILS_VERSION %>"
|
16
|
+
# gem "rails", "<%= Voyage::RAILS_VERSION %>"
|
17
|
+
gem 'rails', git: 'https://github.com/rails/rails.git', branch: '5-0-stable' # OMG Fix deprecation warnings...
|
17
18
|
gem "recipient_interceptor"
|
18
19
|
gem "sass-rails", "~> 5.0"
|
19
20
|
gem "simple_form"
|
@@ -24,39 +25,47 @@ gem "title"
|
|
24
25
|
gem "uglifier"
|
25
26
|
|
26
27
|
# Customizations
|
27
|
-
gem 'responders' # respond to json/html/js more easily in controllers
|
28
|
-
gem 'slim-rails' # templating
|
29
28
|
gem 'font-awesome-rails'
|
30
|
-
gem '
|
31
|
-
gem 'nested_form_fields' # Dynamically add and remove nested has_many association fields in a Ruby on Rails form
|
32
|
-
gem 'devise'
|
29
|
+
gem 'slim-rails'
|
33
30
|
|
34
|
-
|
31
|
+
# Javascript Tweaks
|
32
|
+
gem 'gon' # pass variables betwween rails and javascript. Several examples in the application_controller.rb
|
35
33
|
gem 'jquery-turbolinks'
|
36
34
|
gem 'jquery-ui-rails'
|
37
35
|
gem 'nprogress-rails' # Show request progress when a link is clicked
|
38
|
-
gem '
|
36
|
+
gem 'responders' # respond to json/html/js more easily in controllers
|
37
|
+
gem 'turbolinks'
|
39
38
|
|
40
|
-
|
39
|
+
# Authentication / Authorization
|
41
40
|
gem 'canard', git: 'https://github.com/jondkinney/canard.git', branch: 'feature/fixed-generators-and-rails-5' # ties into cancancan, adds roles for the user
|
41
|
+
gem 'cancancan' # authorization library
|
42
|
+
gem 'devise'
|
43
|
+
gem 'pretender' # impersonate users as an admin
|
42
44
|
|
45
|
+
# Database Tweaks
|
46
|
+
gem 'dynamic_form' # for custom messages without the database column
|
43
47
|
gem 'friendly_id' # slugs in the url auto-generated
|
44
|
-
gem '
|
48
|
+
gem 'nested_form_fields' # Dynamically add and remove nested has_many association fields in a Ruby on Rails form
|
49
|
+
# gem 'nondestructive_migrations' # data migrations go here, not in regular ActiveRecord migrations
|
50
|
+
gem 'nondestructive_migrations', git: 'https://github.com/mfazekas/nondestructive_migrations.git', branch: 'fix-orm-warning'
|
51
|
+
gem 'paper_trail' # version active record models and soft-delete by default
|
45
52
|
gem 'settingslogic' # yaml settings (project wide, non-editable), this is implemented with the model Settings.rb
|
46
53
|
|
47
|
-
#
|
48
|
-
gem 'pry-byebug' # stepwise debugging inside pry
|
49
|
-
gem 'pry-rails' # better REPL than irb
|
50
|
-
gem 'pry-awesome_print' # make pry output legible
|
51
|
-
gem 'pry-remote'
|
52
|
-
|
53
|
-
gem 'nondestructive_migrations'
|
54
|
+
# User Uploads
|
54
55
|
gem 'carrierwave'
|
55
|
-
gem 'mini_magick'
|
56
56
|
gem 'fog'
|
57
|
+
gem 'mini_magick'
|
58
|
+
|
59
|
+
# Cron Jobs
|
57
60
|
gem 'whenever', require: false # provides a clear syntax for writing and deploying cron jobs
|
58
61
|
gem 'whenever-web'
|
59
62
|
|
63
|
+
# Debugging (need at top level if we want pry-remote to work on a deployed prod server)
|
64
|
+
gem 'pry-awesome_print' # make pry output legible
|
65
|
+
gem 'pry-byebug' # stepwise debugging inside pry
|
66
|
+
gem 'pry-rails' # better REPL than irb
|
67
|
+
gem 'pry-remote' # Production debugging
|
68
|
+
|
60
69
|
group :development do
|
61
70
|
gem "listen"
|
62
71
|
gem "spring"
|
@@ -65,13 +74,13 @@ group :development do
|
|
65
74
|
|
66
75
|
# Customizations
|
67
76
|
gem 'annotate' # annotate models automatically when rake db:migrate is called
|
68
|
-
gem 'rails-erd' # auto gen ERD Diagram of models in the app on rake db:migrate
|
69
|
-
gem 'zenflow', git: 'https://github.com/zencoder/zenflow.git'
|
70
77
|
gem 'better_errors' # A better error page for rails when a local 500 (or similar) is thrown
|
71
78
|
gem 'binding_of_caller' # REPL in better_errors to debug in the browser at the point at which it failed
|
72
|
-
gem 'meta_request' # for chrome rails console plugin found here: https://chrome.google.com/webstore/detail/railspanel/gjpfobpafnhjhbajcjgccbbdofdckggg?hl=en-US
|
73
79
|
gem 'bitters', '~> 1.3'
|
80
|
+
gem 'meta_request' # for chrome rails console plugin found here: https://chrome.google.com/webstore/detail/railspanel/gjpfobpafnhjhbajcjgccbbdofdckggg?hl=en-US
|
81
|
+
gem 'rails-erd' # auto gen ERD Diagram of models in the app on rake db:migrate
|
74
82
|
gem 'redcarpet' # used to render the readme inside a static welcome page from the high_voltage gem
|
83
|
+
gem 'zenflow', git: 'https://github.com/zencoder/zenflow.git'
|
75
84
|
end
|
76
85
|
|
77
86
|
group :development, :test do
|
@@ -86,11 +95,9 @@ group :development, :test do
|
|
86
95
|
|
87
96
|
# Customizations
|
88
97
|
gem 'faker' # provides auto generated names for factories, can be customized
|
89
|
-
|
98
|
+
gem 'letter_opener' # auto-open emails when they're sent
|
90
99
|
gem 'rubocop'
|
91
100
|
gem 'rubocop-rspec', require: false
|
92
|
-
|
93
|
-
gem 'letter_opener' # auto-open emails when they're sent
|
94
101
|
end
|
95
102
|
|
96
103
|
group :development, :staging do
|
@@ -109,12 +116,15 @@ group :test do
|
|
109
116
|
|
110
117
|
# Customizations
|
111
118
|
gem 'cadre' # highlights code coverage in vim
|
112
|
-
|
113
|
-
gem '
|
114
|
-
gem '
|
115
|
-
gem 'selenium-webdriver' # brew install chromedriver
|
119
|
+
gem 'capybara' # DSL for finding elements on a page during integration testing
|
120
|
+
gem 'poltergeist' # Headless browser, used in integration tests
|
121
|
+
gem 'selenium-webdriver' # `brew install chromedriver`, used for acceptance tests in an actual browser.
|
116
122
|
end
|
117
123
|
|
118
124
|
group :staging, :production do
|
119
125
|
gem "rack-timeout"
|
120
126
|
end
|
127
|
+
|
128
|
+
group :production do
|
129
|
+
gem 'analytics-ruby', '~> 2.2.2', require: 'segment/analytics'
|
130
|
+
end
|
@@ -7,22 +7,27 @@ with the necessary dependencies to run and test this app:
|
|
7
7
|
|
8
8
|
% ./bin/setup
|
9
9
|
|
10
|
-
It assumes you have a machine equipped with Ruby, Postgres, etc.
|
11
|
-
your machine with [this script].
|
10
|
+
It assumes you have a machine equipped with Ruby, Postgres, etc.
|
12
11
|
|
13
|
-
|
12
|
+
## Seeded Data
|
14
13
|
|
15
|
-
|
14
|
+
Assuming that devise was opted in to, a user and admin have been seeded for you:
|
16
15
|
|
17
|
-
|
16
|
+
admin@example.com -> asdfjkl123
|
17
|
+
user_1@example.com -> asdfjkl123
|
18
18
|
|
19
|
-
|
19
|
+
## Static Pages
|
20
20
|
|
21
|
-
|
21
|
+
The HighVoltage gem is used.
|
22
22
|
|
23
|
-
|
24
|
-
programming in style.
|
23
|
+
## Authorization
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
This repo uses CanCanCan and Canard to authorize user action. `ApplicationController` defines the `check_authorization` method for non-devise non-high voltage controllers. If you want to skip authorization for a specific method in a controller, the following method can be used: `skip_authorization_check`
|
26
|
+
|
27
|
+
## Rubocop
|
28
|
+
|
29
|
+
Take a look at the `.rubocop.yml` file to see what styles are being enforced.
|
30
|
+
|
31
|
+
## Annotations
|
32
|
+
|
33
|
+
Model & spec files are automatically annotated each time `rake db:migrate` is run.
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Admin
|
2
|
+
class UsersController < ApplicationController
|
3
|
+
before_action :require_admin!, except: [:stop_impersonating]
|
4
|
+
skip_authorization_check
|
5
|
+
|
6
|
+
def index
|
7
|
+
@users = User.all
|
8
|
+
end
|
9
|
+
|
10
|
+
def impersonate
|
11
|
+
user = User.find(params[:id])
|
12
|
+
track_impersonation(user, 'Start')
|
13
|
+
impersonate_user(user)
|
14
|
+
redirect_to root_path
|
15
|
+
end
|
16
|
+
|
17
|
+
def stop_impersonating
|
18
|
+
track_impersonation(current_user, 'Stop')
|
19
|
+
stop_impersonating_user
|
20
|
+
redirect_to admin_users_path
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def require_admin!
|
26
|
+
txt = 'You must be an admin to perform that action'
|
27
|
+
redirect_to root_path, notice: txt unless current_user.admin?
|
28
|
+
end
|
29
|
+
|
30
|
+
def track_impersonation(user, status)
|
31
|
+
analytics_track(
|
32
|
+
true_user,
|
33
|
+
"Impersonation #{status}",
|
34
|
+
impersonated_user_id: user.id,
|
35
|
+
impersonated_user_email: user.email,
|
36
|
+
impersonated_by_email: true_user.email,
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%% goto = Rails.application.routes.url_helpers.authenticated_root_path %>
|
2
|
+
|
3
|
+
<%% content_for :javascript do %>
|
4
|
+
<script type='text/javascript'>
|
5
|
+
$(document).ready(function() {
|
6
|
+
console.log('Aliased: 1st');
|
7
|
+
|
8
|
+
if (typeof analytics != 'undefined') {
|
9
|
+
analytics.alias('<%%= current_user.uuid %>');
|
10
|
+
}
|
11
|
+
|
12
|
+
console.log("Redirect to '<%%= goto %>' after alias & identify");
|
13
|
+
|
14
|
+
window.location.replace('<%%= goto %>');
|
15
|
+
});
|
16
|
+
</script>
|
17
|
+
<%% end %>
|
18
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<%% if current_user %>
|
2
|
+
<%% address = current_user.try(:address) %>
|
3
|
+
<%% address_attrs = {} %>
|
4
|
+
<%% address_attrs.merge!(
|
5
|
+
city: (address.city rescue 'unknown'),
|
6
|
+
country: 'United States',
|
7
|
+
postal_code: (address.zip rescue 'unknown'),
|
8
|
+
state: (address.state.name rescue 'unknown'),
|
9
|
+
street: ("#{address.line1} #{address.line2}" rescue 'unknown'),
|
10
|
+
) if address.present? %>
|
11
|
+
|
12
|
+
<script type='text/javascript'>
|
13
|
+
$(document).ready(function() {
|
14
|
+
console.log('Identified: 2nd');
|
15
|
+
|
16
|
+
var analytics_attrs = {
|
17
|
+
email: "<%%= current_user.email %>",
|
18
|
+
first_name: "<%%= escape_javascript(current_user.first_name) %>",
|
19
|
+
last_name: "<%%= escape_javascript(current_user.last_name) %>",
|
20
|
+
address: "<%%= raw controller.send(:sanitize_hash_javascript, address_attrs).to_json %>",
|
21
|
+
created_at: "<%%= current_user.created_at.iso8601 %>",
|
22
|
+
roles: "<%%= current_user.roles.map(&:to_s).join(',') %>",
|
23
|
+
rails_env: "<%%= Rails.env.to_s %>",
|
24
|
+
}
|
25
|
+
|
26
|
+
console.log(analytics_attrs);
|
27
|
+
|
28
|
+
if (typeof analytics != 'undefined') {
|
29
|
+
analytics.identify(
|
30
|
+
"<%%= current_user.uuid %>",
|
31
|
+
analytics_attrs, {
|
32
|
+
integrations: {
|
33
|
+
Intercom : {
|
34
|
+
user_hash: "<%%= OpenSSL::HMAC.hexdigest('sha256', ENV['INTERCOM_SECURE_MODE_SECRET_KEY'].to_s, current_user.uuid.to_s) %>",
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
);
|
39
|
+
}
|
40
|
+
});
|
41
|
+
</script>
|
42
|
+
<%% end %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
if Rails.env.production?
|
2
|
+
require 'segment/analytics'
|
3
|
+
|
4
|
+
Analytics = Segment::Analytics.new(
|
5
|
+
write_key: ENV['SEGMENT_ANALYTICS_RUBY_KEY'],
|
6
|
+
on_error: proc { |_status, msg| Rails.logger.info msg },
|
7
|
+
)
|
8
|
+
else
|
9
|
+
Analytics = Struct.new('Analytics') do
|
10
|
+
def self.track(_segment_attributes)
|
11
|
+
end
|
12
|
+
def self.identify(_segment_attributes)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module DeviseCustomizations
|
2
|
+
class RegistrationsController < Devise::RegistrationsController
|
3
|
+
def create
|
4
|
+
super
|
5
|
+
end
|
6
|
+
|
7
|
+
protected
|
8
|
+
|
9
|
+
def after_sign_up_path_for(resource)
|
10
|
+
if user_signed_in?
|
11
|
+
analytics_alias_user_path(resource)
|
12
|
+
else
|
13
|
+
new_user_session_path(resource)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -27,10 +27,19 @@ AllCops:
|
|
27
27
|
- '.+'
|
28
28
|
Exclude:
|
29
29
|
- 'db/**/*'
|
30
|
-
- 'config
|
30
|
+
- 'config/*'
|
31
|
+
- 'config/environments/*'
|
32
|
+
- 'config/locales/*'
|
33
|
+
- 'config/initializers/devise.rb'
|
34
|
+
- 'config/initializers/simple_form.rb'
|
35
|
+
- 'config/initializers/new_framework_defaults.rb'
|
36
|
+
- 'config/initializers/assets.rb'
|
37
|
+
- 'config/initializers/backtrace_silencers.rb'
|
38
|
+
- 'config/initializers/rack_mini_profiler.rb'
|
39
|
+
- 'config/initializers/wrap_parameters.rb'
|
31
40
|
- 'bin/**/*'
|
32
41
|
Include:
|
33
|
-
- '
|
42
|
+
- 'Gemfile'
|
34
43
|
- '.simplecov'
|
35
44
|
- 'config/initializers/*'
|
36
45
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<h1>Listing Users</h1>
|
2
|
+
|
3
|
+
<table>
|
4
|
+
<thead>
|
5
|
+
<tr><% if config[:adding_first_and_last_name] %>
|
6
|
+
<th>First Name</th>
|
7
|
+
<th>Last Name</th><% end %>
|
8
|
+
<th>Email</th>
|
9
|
+
<th></th>
|
10
|
+
<th></th>
|
11
|
+
<th></th>
|
12
|
+
</tr>
|
13
|
+
</thead>
|
14
|
+
<tbody>
|
15
|
+
<%% @users.each do |user| %>
|
16
|
+
<tr><% if config[:adding_first_and_last_name] %>
|
17
|
+
<td><%%= user.first_name %></td>
|
18
|
+
<td><%%= user.last_name %></td><% end %>
|
19
|
+
<td><%%= link_to user.email, impersonate_admin_user_path(user) %></td>
|
20
|
+
<td><%%= link_to 'Show', user %></td>
|
21
|
+
<td><%%= link_to 'Edit', edit_user_path(user) %></td>
|
22
|
+
<td><%%= link_to 'Destroy', user, data: { confirm: 'Are you sure?' }, method: :delete %></td>
|
23
|
+
</tr>
|
24
|
+
<%% end %>
|
25
|
+
</tbody>
|
26
|
+
</table>
|
27
|
+
|
28
|
+
<br />
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="<%= I18n.locale %>">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<meta name="ROBOTS" content="NOODP" />
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
7
|
+
<meta name="apple-mobile-web-app-capable" content="yes" />
|
8
|
+
<meta name="mobile-web-app-capable" content="yes" />
|
9
|
+
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
10
|
+
<%%#
|
11
|
+
Configure default and controller-, and view-specific titles in
|
12
|
+
config/locales/en.yml. For more see:
|
13
|
+
https://github.com/calebthompson/title#usage
|
14
|
+
%>
|
15
|
+
<title><%%= title %></title>
|
16
|
+
<%%= stylesheet_link_tag :application, media: "all" %>
|
17
|
+
<link rel='apple-touch-icon' href='/assets/apple-touch-icon.png' />
|
18
|
+
<%%= csrf_meta_tags %>
|
19
|
+
<%%= favicon_link_tag 'favicon.ico' %>
|
20
|
+
<%%# Add gon here for gon use inside the compiled js before the page is fully loaded %>
|
21
|
+
<%%= Gon::Base.render_data %>
|
22
|
+
</head>
|
23
|
+
<body class="<%%= devise_controller? ? 'devise' : 'application' %> <%%= body_class %>">
|
24
|
+
<%%# Add gon here for turbolinks benefit %>
|
25
|
+
<%%= Gon::Base.render_data %>
|
26
|
+
<%%= render 'flashes' -%>
|
27
|
+
<%% if devise_controller? %>
|
28
|
+
<% if config[:add_refills] %><%%= render 'refills/navigation' %><% end %>
|
29
|
+
<%%= yield %>
|
30
|
+
<%% else %>
|
31
|
+
<div class='grid-offset'>
|
32
|
+
<div class='work-area'>
|
33
|
+
<% if config[:add_refills] %><%%= render 'refills/navigation' %><% end %>
|
34
|
+
<%%= yield %>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
<%% end %>
|
38
|
+
|
39
|
+
<% if config[:add_refills] %><%%= render 'refills/footer' %><% end %>
|
40
|
+
<%%= render 'javascript' %>
|
41
|
+
<%%= render 'css_overrides' %>
|
42
|
+
</body>
|
43
|
+
</html>
|
data/lib/voyage/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: voyage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.44.0.
|
4
|
+
version: 1.44.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- thoughtbot, headway
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-02-
|
11
|
+
date: 2017-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bitters
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- README.md
|
88
88
|
- RELEASING.md
|
89
89
|
- Rakefile
|
90
|
+
- TODO.md
|
90
91
|
- USAGE
|
91
92
|
- bin/rake
|
92
93
|
- bin/rspec
|
@@ -108,17 +109,23 @@ files:
|
|
108
109
|
- lib/voyage/templates/Gemfile.erb
|
109
110
|
- lib/voyage/templates/README.md.erb
|
110
111
|
- lib/voyage/templates/about.html.erb
|
112
|
+
- lib/voyage/templates/admin_users_controller.rb
|
113
|
+
- lib/voyage/templates/analytics_alias.html.erb.erb
|
114
|
+
- lib/voyage/templates/analytics_identify.html.erb.erb
|
115
|
+
- lib/voyage/templates/analytics_ruby_initializer.rb
|
111
116
|
- lib/voyage/templates/application.js
|
112
117
|
- lib/voyage/templates/auto_annotate_models.rake
|
113
118
|
- lib/voyage/templates/config_locales_en.yml.erb
|
114
119
|
- lib/voyage/templates/controller_helpers.rb
|
115
120
|
- lib/voyage/templates/custom_cancan_matchers.rb
|
121
|
+
- lib/voyage/templates/devise_registrations_controller.rb
|
116
122
|
- lib/voyage/templates/rails_helper.rb.erb
|
117
123
|
- lib/voyage/templates/rubocop.yml
|
118
124
|
- lib/voyage/templates/seeder.rb.erb
|
119
125
|
- lib/voyage/templates/seeds.rb.erb
|
120
126
|
- lib/voyage/templates/simplecov.rb
|
121
|
-
- lib/voyage/templates/users_index.html.
|
127
|
+
- lib/voyage/templates/users_index.html.erb
|
128
|
+
- lib/voyage/templates/voyage_layout.html.erb.erb
|
122
129
|
- lib/voyage/templates/welcome.html.erb
|
123
130
|
- lib/voyage/version.rb
|
124
131
|
- spec/adapters/heroku_spec.rb
|
@@ -1,25 +0,0 @@
|
|
1
|
-
h1 Listing Users
|
2
|
-
|
3
|
-
table
|
4
|
-
thead
|
5
|
-
tr<% if config[:adding_first_and_last_name] %>
|
6
|
-
th First Name
|
7
|
-
th Last Name<% end %>
|
8
|
-
th Email
|
9
|
-
th
|
10
|
-
th
|
11
|
-
th
|
12
|
-
|
13
|
-
tbody
|
14
|
-
- @users.each do |user|
|
15
|
-
tr<% if config[:adding_first_and_last_name] %>
|
16
|
-
td= user.first_name
|
17
|
-
td= user.last_name<% end %>
|
18
|
-
td= user.email
|
19
|
-
td= link_to 'Show', user
|
20
|
-
td= link_to 'Edit', edit_user_path(user)
|
21
|
-
td= link_to 'Destroy', user, data: { confirm: 'Are you sure?' }, method: :delete
|
22
|
-
|
23
|
-
br
|
24
|
-
|
25
|
-
= link_to 'New User', signup_path
|