Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Scoped Views/Mailers/I18n per model inside app/views/devise #5627

Open
jamesst20 opened this issue Sep 10, 2023 · 0 comments

Comments

@jamesst20
Copy link

jamesst20 commented Sep 10, 2023

Environment

  • Ruby 3.2.2
  • Rails 7.0.8
  • Devise 4.9.2

Current behavior

config/initializers/devise.rb

config.scoped_views = true

Exemple

/users/sign_in 
Paths: 
app/views/users/sessions/new
app/views/devise/sessions/new

/administrators/sign_in
Paths:
app/views/administrators/sessions/new
app/views/devise/sessions/new

Feature request behavior

/users/sign_in 
Paths: 
app/views/users/sessions/new
app/views/devise/users/sessions/new <--- This one
app/views/devise/sessions/new

/administrators/sign_in
Paths:
app/views/administrators/sessions/new
app/views/devise/administrators/sessions/new <--- This one
app/views/devise/sessions/new

Cons: This is likely going to require changes to I18n lookup path to add default path as a default fallback

Before:  devise.sessions.new
After: devise.users.sessions.new

With proper fallback:

1. devise.users.sessions.new
2. devise.sessions.new (fallback to add)

Temporary workaround to get this working using a single initializer

##
# Allow overwriting devise views from app/views/devise/<scope name>
# It will fallback to the default directory
module DeviseScopedViews
  def _prefixes
    prefixes = super.dup

    return prefixes unless devise_controller?

    devise_prefix = prefixes.index { |dir| dir.include?("devise/") }

    return prefixes if devise_prefix.nil?

    prefixes.insert(devise_prefix, prefixes[devise_prefix].sub("devise/", "devise/#{scope_name.to_s.pluralize}/"))
  end
end

##
# Allow devise i18n to fallback to the default translation path if no specific ones are given per scope.
module DeviseScopedI18n
  def t(key, **options)
    return super(key, **options) unless try(:devise_controller?)

    key = send(:scope_key_by_partial, key)

    translate key, **options.merge(default: [key.sub("#{scope_name.to_s.pluralize}.", "").to_sym])
  end
end

##
# Allow overwriting devise mailer views from app/views/devise/<scope name>
# It will fallback to the default directory
# Add missing methods to have working DeviseScopedI18n
module DeviseMailersScopedViews
  extend ActiveSupport::Concern

  included do
    helper_method :devise_controller?, :scope_name

    def template_paths
      paths = super.dup

      index = paths.index { |dir| dir.include?("devise/mailer") }

      return paths if index.nil?

      paths.insert(index, "devise/#{scope_name.to_s.pluralize}/mailer")
    end

    def devise_controller?
      true
    end
  end
end

Devise::Mailers::Helpers.prepend DeviseMailersScopedViews

ActiveSupport.on_load(:action_controller) { prepend DeviseScopedViews }
ActiveSupport.on_load(:action_view) { prepend DeviseScopedI18n }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant