Skip to content
This repository has been archived by the owner on Jan 30, 2024. It is now read-only.

Added a views generator #200

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,31 @@ for `:secure_validatable` you need to add
gem 'rails_email_validator'
```


### Configuring views
The view generator in Devise Security extensions works the same way as the view generator in [Devise](https://github.com/plataformatec/devise) does.

If you would like to change the default views, you just need to invoke the following generator, and it will copy all views to your application:

```console
$ rails g devise_security_extension:views
```

If you have more than one Devise model in your application (such as `User` and `Admin`), you will notice that Devise uses the same views for all models. Fortunately, Devise offers an easy way to customize views. All you need to do is set `config.scoped_views = true` inside the `config/initializers/devise.rb` file.

After doing so, you will be able to have views based on the role like `users/sessions/new` and `admins/sessions/new`. If no view is found within the scope, Devise will use the default view at `devise/sessions/new`. You can also use the generator to generate scoped views:

```console
$ rails generate devise_security_extension:views users
```

If you would like to generate only a few sets of views, like the ones for the `registerable` and `confirmable` module,
you can pass a list of modules to the generator with the `-v` flag.

```console
$ rails generate devise_security_extension:views -v paranoid_verification_code password_expired
```

## Configuration

```ruby
Expand Down
2 changes: 1 addition & 1 deletion devise_security_extension.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Gem::Specification.new do |s|
s.require_paths = ['lib']
s.required_ruby_version = '>= 2.1.0'

s.add_runtime_dependency 'railties', '>= 3.2.6', '< 5.0'
s.add_runtime_dependency 'railties', '>= 3.2.6', '< 5.1'
s.add_runtime_dependency 'devise', '>= 3.0.0', '< 5.0'
s.add_development_dependency 'bundler', '>= 1.3.0', '< 2.0'
s.add_development_dependency 'sqlite3', '~> 1.3.10'
Expand Down
71 changes: 71 additions & 0 deletions lib/generators/devise_security_extension/views_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
require 'rails/generators/base'

module DeviseSecurityExtension
module Generators
# Include this module in your generator to generate Devise views.
# `copy_views` is the main method and by default copies all views
# with forms.
module ViewPathTemplates #:nodoc:
extend ActiveSupport::Concern

included do
argument :scope, required: false, default: nil,
desc: "The scope to copy views to"

class_option :views, aliases: "-v", type: :array, desc: "Generate views"

public_task :copy_views
end

# TODO: Add this to Rails itself
module ClassMethods
def hide!
Rails::Generators.hide_namespace self.namespace
end
end

def copy_views
if options[:views]
options[:views].each do |directory|
view_directory directory.to_sym
end
else
view_directory :paranoid_verification_code
view_directory :password_expired
end
end

protected

def view_directory(name, _target_path = nil)
directory name.to_s, _target_path || "#{target_path}/#{name}" do |content|
content
end
end

def target_path
@target_path ||= "app/views/#{plural_scope || :devise}"
end

def plural_scope
@plural_scope ||= scope.presence && scope.underscore.pluralize
end
end

class SharedViewsGenerator < Rails::Generators::Base #:nodoc:
include ViewPathTemplates
source_root File.expand_path("../../../../app/views/devise", __FILE__)
desc "Copies shared Devise views to your application."
hide!
end

class ViewsGenerator < Rails::Generators::Base
desc "Copies Devise views to your application."

argument :scope, required: false, default: nil,
desc: "The scope to copy views to"

invoke SharedViewsGenerator
end
end
end
39 changes: 39 additions & 0 deletions test/generators/views_generator_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require "test_helper"

class ViewsGeneratorTest < Rails::Generators::TestCase
tests Devise::Generators::ViewsGenerator
destination File.expand_path("../../tmp", __FILE__)
setup :prepare_destination

test "Assert all views are properly created with no params" do
run_generator
assert_files
end

test "Assert all views are properly created with scope param" do
run_generator %w(users)
assert_files "users"

run_generator %w(admins)
assert_files "admins"
end

test "Assert only views within specified directories" do
run_generator %w(-v paranoid_verification_code password_expired)
assert_file "app/views/devise/paranoid_verification_code/show.html.erb"
assert_file "app/views/devise/password_expired/show.html.erb"
end

test "Assert specified directories with scope" do
run_generator %w(users -v password_expired)
assert_file "app/views/users/password_expired/show.html.erb"
assert_no_file "app/views/users/paranoid_verification_code/show.html.erb"
end

def assert_files(scope = nil)
scope = "devise" if scope.nil?

assert_file "app/views/#{scope}/paranoid_verification_code/show.html.erb"
assert_file "app/views/#{scope}/password_expired/show.html.erb"
end
end