browsercms-artirix 4.0.0.rc1.art4 → 4.0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/cms/attachments_controller.rb +1 -1
  3. data/app/controllers/cms/cas_sessions_controller.rb +13 -0
  4. data/app/controllers/cms/sections_controller.rb +1 -1
  5. data/app/controllers/cms/users_controller.rb +1 -1
  6. data/app/helpers/cms/sites/authentication_helper.rb +1 -0
  7. data/app/helpers/cms/sites/devise_shim_helper.rb +1 -1
  8. data/app/models/cms/default_user.rb +6 -0
  9. data/app/models/cms/external_user.rb +1 -1
  10. data/app/models/cms/group.rb +7 -3
  11. data/app/models/cms/guest_user.rb +2 -41
  12. data/app/models/cms/permission.rb +4 -0
  13. data/app/models/cms/persistent_user.rb +17 -110
  14. data/app/models/cms/section.rb +10 -6
  15. data/app/models/cms/user.rb +2 -2
  16. data/app/models/cms/user_group_membership.rb +2 -2
  17. data/app/portlets/login_portlet.rb +2 -2
  18. data/config/routes.rb +33 -34
  19. data/db/browsercms.seeds.rb +7 -4
  20. data/doc/release_notes.md +3 -3
  21. data/lib/browsercms.rb +2 -0
  22. data/lib/cms/authentication/controller.rb +8 -5
  23. data/lib/cms/authentication/test_password_strategy.rb +1 -1
  24. data/lib/cms/behaviors.rb +15 -0
  25. data/lib/cms/behaviors/attaching.rb +1 -1
  26. data/lib/cms/behaviors/userstamping.rb +1 -1
  27. data/lib/cms/behaviors/versioning.rb +3 -4
  28. data/lib/cms/configuration.rb +108 -10
  29. data/lib/cms/configuration/devise.rb +75 -4
  30. data/lib/cms/engine.rb +55 -2
  31. data/lib/cms/users_service.rb +26 -190
  32. data/lib/cms/users_service/cms_login_user_controller_concern.rb +19 -0
  33. data/lib/cms/users_service/cms_user_compatibility_module.rb +137 -0
  34. data/lib/cms/users_service/guest_user_module.rb +42 -0
  35. data/lib/cms/users_service/user_groups_by_codes_module.rb +13 -0
  36. data/lib/cms/users_service/users_factory.rb +50 -0
  37. data/lib/cms/version.rb +1 -1
  38. data/lib/generators/browser_cms/demo_site/templates/demo.seeds.rb +1 -1
  39. metadata +27 -6
@@ -1,6 +1,6 @@
1
1
  require 'cms/data_loader'
2
2
 
3
- Cms::User.current = cmsadmin = Cms::User.new(login: "cmsadmin", first_name: "CMS", last_name: "Administrator", email: "cmsadmin@example.com")
3
+ cmsadmin = Cms::User.new(login: "cmsadmin", first_name: "CMS", last_name: "Administrator", email: "cmsadmin@example.com")
4
4
  if %w[development test dev local].include?(Rails.env)
5
5
  pwd = cmsadmin.change_password('cmsadmin')
6
6
  else
@@ -8,7 +8,10 @@ else
8
8
  end
9
9
  cmsadmin.save
10
10
 
11
- Cms::UsersService.use_user cmsadmin.login
11
+ default_cmsadmin = Cms::DefaultUser.new login: 'cmsadmin', full_name: 'CMS Administrator'
12
+ default_cmsadmin.save!
13
+
14
+ Cms::UsersService.use_user_by_login cmsadmin.login
12
15
 
13
16
  create_permission(:administrate, :name => "administrate", :full_name => "Administer CMS", :description => "Allows users to administer the CMS, including adding users and groups.")
14
17
  create_permission(:edit_content, :name => "edit_content", :full_name => "Edit Content", :description => "Allows users to Add, Edit and Delete both Pages and Blocks. Can Save (but not Publish) and Assign them as well.")
@@ -22,8 +25,8 @@ group_types(:cms_user).permissions<<permissions(:edit_content)
22
25
  group_types(:cms_user).permissions<<permissions(:publish_content)
23
26
 
24
27
  create_group(:guest, :name => 'Guest', :code => 'guest', :group_type => group_types(:guest_group_type))
25
- create_group(:content_admin, :name => 'Cms Administrators', :code => 'cms-admin', :group_type => group_types(:cms_user))
26
- create_group(:content_editor, :name => 'Content Editors', :code => 'content-editor', :group_type => group_types(:cms_user))
28
+ create_group(:content_admin, :name => 'Cms Administrators', :code => Cms::UsersService::GROUP_CMS_ADMIN, :group_type => group_types(:cms_user))
29
+ create_group(:content_editor, :name => 'Content Editors', :code => Cms::UsersService::GROUP_CONTENT_EDITOR, :group_type => group_types(:cms_user))
27
30
  cmsadmin.groups << groups(:content_admin)
28
31
  cmsadmin.groups << groups(:content_editor)
29
32
 
data/doc/release_notes.md CHANGED
@@ -186,7 +186,7 @@ Devise is now the standard authentication mechanism for BrowserCMS. This adds so
186
186
 
187
187
  Upgrading to 4.0 means all user passwords will need to be reset. This doesn't apply where external user databases are used (i.e. CAS) for authentication. Just user accounts stored in the CMS itself.
188
188
 
189
- This reset is a side effect of using a more secure password encryption algorithm (bcrypt). When users try to log in, they will have to request a password reset. This feature is provided on /cms/login as a standard feature. Users will need to provide an email, and a link for reseting their password will be sent to them. Alternatively, developers may choose to change passwords via the admin interface (or rails console) before turning over sites to the site maintainers.
189
+ This reset is a side effect of using a more secure password encryption algorithm (bcrypt). When users try to log in, they will have to request a password reset. This feature is provided on /cms/users/login as a standard feature. Users will need to provide an email, and a link for reseting their password will be sent to them. Alternatively, developers may choose to change passwords via the admin interface (or rails console) before turning over sites to the site maintainers.
190
190
 
191
191
  ### Avoiding a reset
192
192
 
@@ -202,7 +202,7 @@ Note that preserving the old password data is just the first step. The new encry
202
202
 
203
203
  ### Forgot Password
204
204
 
205
- Users can reset their password via the admin UI. On /cms/login, a link to 'Forgot Password' is available. Users can enter an email and have the reset link mailed to them.
205
+ Users can reset their password via the admin UI. On /cms/users/login, a link to 'Forgot Password' is available. Users can enter an email and have the reset link mailed to them.
206
206
 
207
207
  Configuration: For Forgot Password to work, need to ensure the following is present for mailer in BrowserCMS setups.
208
208
  * config.action_mailer.default_url_options = { :host => "yourhost" }
@@ -236,7 +236,7 @@ This implementation is intended to replace CAS based strategies used in BrowserC
236
236
  7. Password Reset - Users will need to reset their password after the upgrade. See Devise Integration/Avoiding a reset if this is concern.
237
237
  8. Forgot Password - Consider removing any existing ForgotPassword portlets and just use /forgot-password controller. Creation is disabled by default.
238
238
  9. Reset Password Portlet - These have been removed as they were no longer necessary. Any remaining instances have been converted to 'DeprecatedPlaceholders'. Find and remove these portlets (and the page they were on) from your site.
239
- 10. Login Portlet - Consider removing these and using the built in /login route. Creation is disabled by default.
239
+ 10. Login Portlet - Consider removing these and using the built in /users/login route. Creation is disabled by default.
240
240
 
241
241
  ### Migration Cleanup
242
242
 
data/lib/browsercms.rb CHANGED
@@ -4,6 +4,7 @@ require 'cms/configuration'
4
4
  require 'cms/version'
5
5
  require 'browsercms'
6
6
 
7
+ require 'sass'
7
8
  require 'sass-rails'
8
9
  require 'compass-rails'
9
10
  require 'bootstrap-sass'
@@ -25,6 +26,7 @@ require 'actionpack/page_caching'
25
26
  require 'panoramic'
26
27
  require 'simple_form'
27
28
  require 'devise'
29
+ require 'devise_cas_authenticatable'
28
30
 
29
31
  require 'cms/engine'
30
32
  require 'cms/extensions'
@@ -25,6 +25,7 @@ module Cms
25
25
  def self.included(base)
26
26
  base.send :helper_method, :current_user, :logged_in? if base.respond_to? :helper_method
27
27
  base.extend ClassMethods
28
+ base.send :include, Cms::UsersService.controller_module
28
29
  end
29
30
 
30
31
 
@@ -58,9 +59,11 @@ module Cms
58
59
  # Returns the current user if logged in. If no user is logged in, returns the 'Guest' user which represents a
59
60
  # what a visitor can do without being logged in.
60
61
  def current_user
61
- @current_user ||= begin
62
- Cms::PersistentUser.current = current_cms_user || Cms::User.guest
63
- end
62
+ @current_user ||= load_current_user
63
+ end
64
+
65
+ def load_current_user
66
+ Cms::UsersService.use_user(current_cms_user || Cms::User.guest)
64
67
  end
65
68
 
66
69
  # Redirect as appropriate when an access request fails.
@@ -101,8 +104,8 @@ module Cms
101
104
  # However, **all session state variables should be unset here**.
102
105
  def logout_keeping_session!
103
106
  # Kill server-side auth cookie
104
- Cms::PersistentUser.current.forget_me if Cms::User.current.is_a? User
105
- Cms::PersistentUser.current = false # not logged in, and don't do it for me
107
+ Cms::UsersService.current.try :forget_me if Cms::UsersService.current.is_a? User
108
+ Cms::UsersService.current = false # not logged in, and don't do it for me
106
109
  session[:user_id] = nil # keeps the session but kill our variable
107
110
  # explicitly kill any other session variables you set
108
111
  end
@@ -6,7 +6,7 @@ module Cms
6
6
  def authenticate!
7
7
  if(authentication_hash[:login] == password && password == EXPECTED_PASSWORD)
8
8
  user = Cms::ExternalUser.authenticate(authentication_hash[:login], 'Test Password', {first_name: "Test", last_name: "User"})
9
- user.authorize('cms-admin', 'content-editor')
9
+ user.authorize(Cms::UsersService::GROUP_CMS_ADMIN, Cms::UsersService::GROUP_CONTENT_EDITOR)
10
10
  success!(user)
11
11
  else
12
12
  pass
data/lib/cms/behaviors.rb CHANGED
@@ -32,3 +32,18 @@ Dir["#{File.dirname(__FILE__)}/behaviors/*.rb"].each do |b|
32
32
  ActiveRecord::Base.send(:include, "Cms::Behaviors::#{File.basename(b, ".rb").camelize}".constantize)
33
33
  end
34
34
 
35
+ module ARCompatibilityModule
36
+ # TODO: modification of changed_attributes is forbidden in later rails -> find alternative
37
+
38
+ def compatible_clear_changes_information
39
+ # for rails 4.2 compat
40
+ if respond_to?(:clear_changes_information) # rails 4.2
41
+ clear_changes_information
42
+ elsif respond_to?(:reset_changes) # rails 4.1
43
+ reset_changes
44
+ else
45
+ changed_attributes.clear # rails < 4.1
46
+ end
47
+ end
48
+ end
49
+ ActiveRecord::Base.send(:include, ARCompatibilityModule)
@@ -85,7 +85,7 @@ module Cms
85
85
  end
86
86
 
87
87
  def validates_attachment_presence(name, options = {})
88
- message = options[:message] || "Must provide at least one #{name}"
88
+ message = options.delete(:message) || "Must provide at least one #{name}"
89
89
  validate(options) do |record|
90
90
  return if record.deleted?
91
91
  unless record.attachments.any? { |a| a.attachment_name == name.to_s }
@@ -30,7 +30,7 @@ module Cms
30
30
 
31
31
  module InstanceMethods
32
32
  def set_userstamps
33
- current_user = Cms::User.current ? Cms::User.current : nil
33
+ current_user = Cms::UsersService.current.presence
34
34
  if new_record?
35
35
  self.created_by = current_user
36
36
  end
@@ -36,9 +36,7 @@ module Cms
36
36
  obj.after_as_of_version if obj.respond_to?(:after_as_of_version)
37
37
 
38
38
  # Last but not least, clear the changed attributes
39
- if changed_attrs = obj.send(:changed_attributes)
40
- changed_attrs.clear
41
- end
39
+ obj.compatible_clear_changes_information
42
40
 
43
41
  obj
44
42
  end
@@ -233,7 +231,8 @@ module Cms
233
231
  self.version = 1
234
232
  # This should call ActiveRecord::Callbacks#create_or_update, which will correctly trigger the :save callback_chain
235
233
  saved_correctly = super
236
- changed_attributes.clear
234
+
235
+ compatible_clear_changes_information
237
236
  else
238
237
  logger.debug { "#{self.class}#update" }
239
238
  # Because we are 'skipping' the normal ActiveRecord update here, we must manually call the save callback chain.
@@ -29,27 +29,125 @@ module Cms
29
29
  end
30
30
 
31
31
  # User Class
32
- attr_writer :user_class_name
32
+ def user_key_field
33
+ Rails.application.config.cms.user_key_field
34
+ end
35
+
36
+ def user_name_field
37
+ Rails.application.config.cms.user_name_field
38
+ end
39
+
33
40
  def user_class_name
34
- @user_class_name ||= 'Cms::User'
41
+ Rails.application.config.cms.user_class_name
35
42
  end
36
43
 
37
44
  def user_class
38
45
  user_class_name.to_s.constantize
39
46
  end
40
47
 
41
- # User key
42
- attr_writer :user_key_field
43
- def user_key_field
44
- @user_key_field ||= :login
48
+ def user_class_devise_options
49
+ Rails.application.config.cms.user_class_devise_options.dup.tap do |opts|
50
+ if devise_use_cas_only?
51
+ opts.delete :database_authenticatable
52
+ opts.delete :rememberable
53
+ opts.delete :recoverable
54
+ opts.unshift(:cas_authenticatable) unless opts.include? :cas_authenticatable
55
+ end
56
+ end
45
57
  end
46
58
 
47
- # User name field
48
- attr_writer :user_name_field
49
- def user_name_field
50
- @user_name_field ||= :full_name
59
+ def user_cas_extra_attributes_setter
60
+ Rails.application.config.cms.user_cas_extra_attributes_setter
61
+ end
62
+
63
+ # DEVISE AND CAS
64
+ def cas_base_url
65
+ Rails.application.config.cms.cas_base_url
66
+ end
67
+
68
+ def cas_destination_url
69
+ Rails.application.config.cms.cas_destination_url
70
+ end
71
+
72
+ def cas_follow_url
73
+ Rails.application.config.cms.cas_follow_url
74
+ end
75
+
76
+ def cas_logout_url_param
77
+ Rails.application.config.cms.cas_logout_url_param
78
+ end
79
+
80
+ def cas_login_url
81
+ Rails.application.config.cms.cas_login_url
82
+ end
83
+
84
+ def cas_logout_url
85
+ Rails.application.config.cms.cas_logout_url
86
+ end
87
+
88
+ def cas_validate_url
89
+ Rails.application.config.cms.cas_validate_url
90
+ end
91
+
92
+ def cas_destination_logout_param_name
93
+ Rails.application.config.cms.cas_destination_logout_param_name
51
94
  end
52
95
 
96
+ def cas_create_user
97
+ Rails.application.config.cms.cas_create_user
98
+ end
99
+
100
+ def cas_enable_single_sign_out
101
+ Rails.application.config.cms.cas_enable_single_sign_out
102
+ end
103
+
104
+ def cas_user_identifier
105
+ Rails.application.config.cms.cas_user_identifier
106
+ end
107
+
108
+ def user_class_devise_validatable?
109
+ Rails.application.config.cms.user_class_devise_validatable
110
+ end
111
+
112
+ def user_class_devise_recoverable?
113
+ Rails.application.config.cms.user_class_devise_recoverable
114
+ end
115
+
116
+ def routes_devise_for_options
117
+ opts = Rails.application.config.cms.routes_devise_for_options.dup
118
+
119
+ unless opts.key? :class_name
120
+ opts[:class_name] = user_class_name
121
+ end
122
+
123
+ opts[:skip] ||= []
124
+
125
+ # always skip sessions, we'll add them outside, as BCMS intended.
126
+ # opts[:skip] << :sessions unless opts[:skip].include? :sessions
127
+
128
+ unless devise_allow_registrations?
129
+ opts[:skip] << :registrations unless opts[:skip].include? :registrations
130
+ end
131
+
132
+ opts
133
+ end
134
+
135
+ def routes_devise_sessions_controller
136
+ key = devise_use_cas_only? ? :cas_sessions : :sessions
137
+ cnts = routes_devise_for_options[:controllers] || {}
138
+ controller_name = cnts[key] || "devise/#{key}"
139
+
140
+ # remove 'cms/' prefix
141
+ controller_name.gsub /^cms\//, ''
142
+ end
143
+
144
+ def devise_use_cas_only?
145
+ !!Rails.application.config.cms.devise_use_cas_only
146
+ end
147
+
148
+ def devise_allow_registrations?
149
+ !!Rails.application.config.cms.devise_allow_registrations
150
+ end
53
151
  end
54
152
 
55
153
  module Errors
@@ -31,7 +31,7 @@ Devise.setup do |config|
31
31
  # session. If you need permissions, you should implement that in a before filter.
32
32
  # You can also supply a hash where the value is a boolean determining whether
33
33
  # or not authentication should be aborted when the value is not present.
34
- config.authentication_keys = [ :login ]
34
+ config.authentication_keys = [:login]
35
35
 
36
36
  # Configure parameters from the request object used for authentication. Each entry
37
37
  # given should be a request method and it will automatically be passed to the
@@ -43,12 +43,12 @@ Devise.setup do |config|
43
43
  # Configure which authentication keys should be case-insensitive.
44
44
  # These keys will be downcased upon creating or modifying a user and when used
45
45
  # to authenticate or find a user. Default is :email.
46
- config.case_insensitive_keys = [ :login ]
46
+ config.case_insensitive_keys = [:login]
47
47
 
48
48
  # Configure which authentication keys should have whitespace stripped.
49
49
  # These keys will have whitespace before and after removed upon creating or
50
50
  # modifying a user and when used to authenticate or find a user. Default is :email.
51
- config.strip_whitespace_keys = [ :login ]
51
+ config.strip_whitespace_keys = [:login]
52
52
 
53
53
  # Tell if authentication through request.params is enabled. True by default.
54
54
  # It can be set to an array that will enable params authentication only for the
@@ -224,7 +224,7 @@ Devise.setup do |config|
224
224
  # config.navigational_formats = ['*/*', :html]
225
225
 
226
226
  # The default HTTP method used to sign out a resource. Default is :delete.
227
- config.sign_out_via = :delete
227
+ config.sign_out_via = [:delete, :post, :get]
228
228
 
229
229
  # ==> OmniAuth
230
230
  # Add a new OmniAuth provider. Check the wiki for more information on setting
@@ -254,3 +254,74 @@ Devise.setup do |config|
254
254
  # so you need to do it manually. For the users scope, it would be:
255
255
  # config.omniauth_path_prefix = '/my_engine/users/auth'
256
256
  end
257
+
258
+ # override DEVISE CAS
259
+ module Devise
260
+ def self.cas_action_url(base_url, mapping, action)
261
+ cas_action_url_factory_class.new(base_url, mapping, action).call
262
+ end
263
+
264
+ def self.cas_action_url_factory_class
265
+ @cas_action_url_factory_class ||= CasActionUrlFactoryBase.prepare_class
266
+ end
267
+
268
+ class CasActionUrlFactoryBase
269
+ attr_reader :base_url, :mapping, :action
270
+
271
+ def self.prepare_class
272
+ Class.new(self) do
273
+ include Rails.application.routes.url_helpers
274
+ include Rails.application.routes.mounted_helpers if Rails.application.routes.try(:mounted_helpers)
275
+ end
276
+ end
277
+
278
+ def initialize(base_url, mapping, action)
279
+ @base_url = base_url
280
+ @mapping = mapping
281
+ @action = action
282
+ end
283
+
284
+ def call
285
+ uri = URI.parse(base_url).tap { |uri| uri.query = nil }
286
+ uri.path = load_base_path
287
+ uri.to_s
288
+ end
289
+
290
+ alias_method :build, :call
291
+
292
+ private
293
+ def load_base_path
294
+ load_routes_path || load_mapping_path
295
+ end
296
+
297
+ def load_routes_path
298
+ router_name = mapping.router_name || Devise.available_router_name
299
+ context = send(router_name)
300
+
301
+ route = "#{mapping.singular}_#{action}_path"
302
+ if context.respond_to? route
303
+ context.send route
304
+ else
305
+ nil
306
+ end
307
+ rescue NameError, NoMemoryError
308
+ nil
309
+ end
310
+
311
+ def load_mapping_path
312
+ path = mapping_fullpath || mapping_raw_path
313
+ path << "/" unless path =~ /\/$/
314
+ path << action
315
+ path
316
+ end
317
+
318
+ def mapping_fullpath
319
+ return nil unless mapping.respond_to?(:fullpath)
320
+ "#{ENV['RAILS_RELATIVE_URL_ROOT']}#{mapping.fullpath}"
321
+ end
322
+
323
+ def mapping_raw_path
324
+ "#{ENV['RAILS_RELATIVE_URL_ROOT']}#{mapping.raw_path}"
325
+ end
326
+ end
327
+ end
data/lib/cms/engine.rb CHANGED
@@ -7,6 +7,59 @@ module Cms
7
7
  isolate_namespace Cms
8
8
 
9
9
  config.cms = ActiveSupport::OrderedOptions.new
10
+
11
+ # USER BASE defaults
12
+ config.cms.user_class_name = 'Cms::PersistentUser'
13
+ config.cms.user_key_field = :login
14
+ config.cms.user_name_field = :full_name
15
+
16
+ # DEVISE and CAS
17
+ config.cms.user_class_devise_options = [
18
+ :database_authenticatable,
19
+ :rememberable,
20
+ :recoverable,
21
+ authentication_keys: [:login]
22
+ ]
23
+
24
+ config.cms.devise_use_cas_only = false
25
+ config.cms.devise_allow_registrations = true
26
+
27
+ config.cms.routes_devise_for_options = {
28
+ skip: [],
29
+ path: :users,
30
+ path_names: {
31
+ sign_in: 'login',
32
+ sign_out: 'logout'
33
+ },
34
+ router_name: :cms, # we repeat it in the mapping so devise_cas_authenticatable can work nicely
35
+ controllers: {
36
+ sessions: 'cms/sessions',
37
+ passwords: 'cms/passwords',
38
+ cas_sessions: 'cms/cas_sessions',
39
+ },
40
+ module: :devise,
41
+ # class_name: nil, # this one is set by Cms Config, using Cms.user_class_name if it's not set
42
+ }
43
+
44
+ # Override this with a callable object that will get the user and the extra attributes
45
+ # on a cas_extra_attributes.
46
+ config.cms.user_cas_extra_attributes_setter = ->(_user, _extra_attributes) { nil }
47
+
48
+ config.cms.user_class_devise_validatable = true
49
+ config.cms.user_class_devise_recoverable = true
50
+
51
+ config.cms.cas_base_url = "https://cas.myorganization.com"
52
+ config.cms.cas_destination_url = nil
53
+ config.cms.cas_follow_url = nil
54
+ config.cms.cas_logout_url_param = nil
55
+ config.cms.cas_login_url = nil
56
+ config.cms.cas_logout_url = nil
57
+ config.cms.cas_validate_url = nil
58
+ config.cms.cas_destination_logout_param_name = nil
59
+ config.cms.cas_create_user = false
60
+ config.cms.cas_enable_single_sign_out = true
61
+ config.cms.cas_user_identifier = nil
62
+
10
63
  config.cms.attachments = ActiveSupport::OrderedOptions.new
11
64
 
12
65
  # Allows additional menu items to be added to the 'Tools' menu on the Admin tab.
@@ -71,7 +124,7 @@ module Cms
71
124
  # Keys are looked up based on Class.name.underscore
72
125
  # @example:
73
126
  # config.cms.templates['cms/form'] = 'my-form-layout' # app/views/layouts/templates/my-form-layout
74
- # config.cms.templates['cms/sites/sessions_controller'] = 'subpage' # For /login
127
+ # config.cms.templates['cms/sites/sessions_controller'] = 'subpage' # For /users/login
75
128
  #
76
129
  app.config.cms.templates = {}
77
130
 
@@ -98,7 +151,7 @@ module Cms
98
151
  end
99
152
 
100
153
  # Needed to ensure routes added to the main app by the Engine are available. (Since engine draws its routes after the main app)
101
- # Borrrow from Spree as documenented here: https://github.com/rails/rails/issues/11895
154
+ # Borrow from Spree as documented here: https://github.com/rails/rails/issues/11895
102
155
  config.after_initialize do
103
156
  Rails.application.routes_reloader.reload!
104
157
  end