-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdevise_generator.rb
157 lines (133 loc) · 6.26 KB
/
devise_generator.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
require_relative '../../../bundler_helpers'
module Rolemodel
module Saas
class DeviseGenerator < Rails::Generators::Base
include Rolemodel::BundlerHelpers
source_root File.expand_path('templates', __dir__)
def add_organization
generate :model, 'organization name:string' unless File.exist?(Rails.root.join('app/models/organization.rb'))
inject_into_file 'app/models/organization.rb', " has_many :users, inverse_of: :organization\n", after: "ApplicationRecord\n"
end
def install_devise
# Devise tries to install bcrypt, but it fails because the bundle command
# is run using the wrong platform causing the native extension to fail.
# Using clean env fixes this.
Bundler.with_clean_env do
run 'bundle add devise'
end
generate 'devise:install'
generate :devise, 'user first_name:string last_name:string'
generate :migration, 'add_organization_and_role_to_users organization_id:bigint:index role:string super_admin:boolean'
file_name = Dir.glob(Rails.root.join('db/migrate', '*_add_organization_and_role_to_users.rb', )).last
gsub_file file_name, /:role, :string$/, ":role, :string, default: 'user', null: false"
gsub_file file_name, /:super_admin, :boolean$/, ':super_admin, :boolean, default: false, null: false'
end
def add_invitable
@add_invitations = yes?('Would you like to add user invitations?')
if @add_invitations
run 'bundle add devise_invitable'
generate 'devise_invitable:install'
generate :devise_invitable, 'user'
end
end
def add_routes
route_info = ", controllers: {\n"
route_info += " invitations: 'users/invitations',\n" if @add_invitations
route_info += " registrations: 'users/registrations',\n"
route_info += " }"
inject_into_file 'config/routes.rb', route_info, after: /devise_for :users$/
route_info = "namespace :admin do\n"
if @add_invitations
route_info += " resources :users do\n"
route_info += " post :reinvite, on: :member\n"
route_info += " end\n"
else
route_info += " resources :users\n"
end
route_info += "end"
route route_info
route 'root to: "admin/users#index"' unless File.readlines("config/routes.rb").grep(/root\sto/).any?
end
def add_modified_files
copy_file 'app/controllers/application_controller.rb'
if @add_invitations
copy_file 'app/controllers/users/invitations_controller.rb'
directory 'app/views/devise/invitations'
copy_file 'app/views/devise/mailer/invitation_instructions.html.slim'
copy_file 'app/views/devise/mailer/invitation_instructions.text.slim'
copy_file 'config/locales/devise_invitable.en.yml'
end
template 'app/controllers/admin/users_controller.rb'
copy_file 'app/controllers/users/registrations_controller.rb'
directory 'app/views/admin'
directory 'app/views/devise', exclude_pattern: /invitation/
copy_file 'config/locales/devise.en.yml'
copy_file 'spec/support/devise.rb'
copy_file 'spec/system/users_spec.rb'
copy_file 'spec/factories/organizations.rb'
copy_file 'spec/factories/users.rb'
end
def modify_existing_files
unless File.exist?(Rails.root.join('config/initializers/premailer_rails.rb'))
inject_into_file 'config/environments/development.rb', after: "config.action_mailer.perform_caching = false\n" do
optimize_indentation <<~'RUBY', 2
# Default mailing host suggested by Devise installation instructions
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
RUBY
end
end
inject_into_file 'config/environments/production.rb', after: "config.action_mailer.perform_caching = false\n" do
optimize_indentation <<~'RUBY', 2
# Tell Devise about your host, so it can send password reset emails
if ENV['REVIEW_APP'] == 'true' && ENV['HEROKU_APP_NAME'].present?
config.action_mailer.default_url_options = { host: "https://#{ENV['HEROKU_APP_NAME']}.herokuapp.com" }
else
config.action_mailer.default_url_options = { host: ENV['PRODUCTION_HOST'] }
end
RUBY
end
# Update Devise email_regexp to something more useful
gsub_file 'config/initializers/devise.rb', '/\A[^@\s]+@[^@\s]+\z/', '/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i'
# Turn Devise validate_on_invite on by default
if @add_invitations
gsub_file 'config/initializers/devise.rb', '# config.validate_on_invite = true', 'config.validate_on_invite = true'
end
inject_into_file 'app/models/user.rb', after: /devise\s+:.*\n.*\n/ do
optimize_indentation <<~'RUBY', 2
enum role: { user: 'user', admin: 'admin' }
belongs_to :organization, inverse_of: :users
accepts_nested_attributes_for :organization
validates :first_name, :last_name, :role, presence: true
delegate :name, to: :organization, prefix: true
RUBY
end
inject_into_file 'db/seeds.rb', after: "Examples:\n" do
<<~'RUBY'
if Rails.env.development?
puts 'Creating the default user environment...'
organization = Organization.create!(
name: 'RoleModel Software'
)
User.create!(
first_name: 'Support',
last_name: 'Admin',
organization: organization,
super_admin: true,
role: User.roles[:admin],
email: '[email protected]',
password: 'password',
password_confirmation: 'password'
)
end
RUBY
end
end
def define_devise_mailer_layout
gsub_file 'config/initializers/devise.rb', "# config.parent_mailer = 'ActionMailer::Base'", "config.parent_mailer = 'ApplicationMailer'"
end
def add_devise_mailer_preview
copy_file 'spec/mailers/previews/devise_mailer_preview.rb'
end
end
end
end