draft_generators 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +6 -0
  3. data/.document +5 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +637 -0
  6. data/Gemfile +16 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.markdown +24 -0
  9. data/Rakefile +51 -0
  10. data/VERSION +1 -0
  11. data/draft_generators.gemspec +120 -0
  12. data/lib/devise_customization_service.rb +95 -0
  13. data/lib/draft_generators.rb +8 -0
  14. data/lib/generators/draft/devise/devise_generator.rb +92 -0
  15. data/lib/generators/draft/devise/views/templates/confirmations/new.html.erb +49 -0
  16. data/lib/generators/draft/devise/views/templates/mailer/confirmation_instructions.html.erb +5 -0
  17. data/lib/generators/draft/devise/views/templates/mailer/email_changed.html.erb +7 -0
  18. data/lib/generators/draft/devise/views/templates/mailer/password_change.html.erb +3 -0
  19. data/lib/generators/draft/devise/views/templates/mailer/reset_password_instructions.html.erb +8 -0
  20. data/lib/generators/draft/devise/views/templates/mailer/unlock_instructions.html.erb +7 -0
  21. data/lib/generators/draft/devise/views/templates/passwords/edit.html.erb +83 -0
  22. data/lib/generators/draft/devise/views/templates/passwords/new.html.erb +49 -0
  23. data/lib/generators/draft/devise/views/templates/registrations/edit.html.erb +159 -0
  24. data/lib/generators/draft/devise/views/templates/registrations/new.html.erb +113 -0
  25. data/lib/generators/draft/devise/views/templates/registrations_with_sentinels/edit.html.erb +160 -0
  26. data/lib/generators/draft/devise/views/templates/registrations_with_sentinels/new.html.erb +102 -0
  27. data/lib/generators/draft/devise/views/templates/sessions/new.html.erb +51 -0
  28. data/lib/generators/draft/devise/views/templates/shared/_links.html.erb +25 -0
  29. data/lib/generators/draft/devise/views/templates/unlocks/new.html.erb +49 -0
  30. data/lib/generators/draft/devise/views/views_generator.rb +41 -0
  31. data/lib/generators/draft/layout/USAGE +49 -0
  32. data/lib/generators/draft/layout/layout_generator.rb +66 -0
  33. data/lib/generators/draft/layout/templates/_bootstrapcdn_assets.html.erb +10 -0
  34. data/lib/generators/draft/layout/templates/_flashes.html.erb +23 -0
  35. data/lib/generators/draft/layout/templates/_navbar.html.erb +75 -0
  36. data/lib/generators/draft/layout/templates/layout.html.erb +40 -0
  37. data/lib/generators/draft/model/USAGE +14 -0
  38. data/lib/generators/draft/model/model_generator.rb +42 -0
  39. data/lib/generators/draft/resource/USAGE +11 -0
  40. data/lib/generators/draft/resource/resource_generator.rb +172 -0
  41. data/lib/generators/draft/resource/templates/controllers/controller.rb +97 -0
  42. data/lib/generators/draft/resource/templates/controllers/read_only_controller.rb +13 -0
  43. data/lib/generators/draft/resource/templates/specs/crud_spec.rb +300 -0
  44. data/lib/generators/draft/resource/templates/specs/factories.rb +32 -0
  45. data/lib/generators/draft/resource/templates/views/association_new_form.html.erb +67 -0
  46. data/lib/generators/draft/resource/templates/views/create_row.html.erb +13 -0
  47. data/lib/generators/draft/resource/templates/views/destroy_row.html.erb +13 -0
  48. data/lib/generators/draft/resource/templates/views/edit_form.html.erb +72 -0
  49. data/lib/generators/draft/resource/templates/views/edit_form_with_errors.html.erb +85 -0
  50. data/lib/generators/draft/resource/templates/views/index.html.erb +102 -0
  51. data/lib/generators/draft/resource/templates/views/new_form.html.erb +73 -0
  52. data/lib/generators/draft/resource/templates/views/new_form_with_errors.html.erb +86 -0
  53. data/lib/generators/draft/resource/templates/views/show.html.erb +90 -0
  54. data/lib/generators/draft/resource/templates/views/update_row.html.erb +9 -0
  55. data/lib/generators/draft/scaffold/scaffold_controller_generator.rb +16 -0
  56. data/lib/generators/draft/scaffold/scaffold_erb_generator.rb +25 -0
  57. data/lib/generators/draft/scaffold/scaffold_generator.rb +15 -0
  58. data/lib/generators/draft/scaffold/templates/_card.html.erb +37 -0
  59. data/lib/generators/draft/scaffold/templates/_form.html.erb +44 -0
  60. data/lib/generators/draft/scaffold/templates/_list_item.html.erb +13 -0
  61. data/lib/generators/draft/scaffold/templates/_table_row.html.erb +23 -0
  62. data/lib/generators/draft/scaffold/templates/edit.html.erb +17 -0
  63. data/lib/generators/draft/scaffold/templates/index.html.erb +71 -0
  64. data/lib/generators/draft/scaffold/templates/new.html.erb +17 -0
  65. data/lib/generators/draft/scaffold/templates/show.html.erb +5 -0
  66. data/lib/rails_tag_service.rb +47 -0
  67. metadata +197 -0
@@ -0,0 +1,66 @@
1
+ module Draft
2
+ class LayoutGenerator < Rails::Generators::Base
3
+ source_root File.expand_path('../templates', __FILE__)
4
+
5
+ class_option :theme, type: :string, default: "none", desc: "Bootstrap theme"
6
+ class_option :layout_file, type: :string, default: "application", desc: "Layout filename"
7
+ class_option :skip_cdn, type: :boolean, default: false, desc: "Skip connecting CDN assets"
8
+
9
+ def generate_layout
10
+ if bootswatch?
11
+ log :insert, "Adding #{theme_name.capitalize} Bootswatch"
12
+ else
13
+ log :insert, "Adding Bootstrap"
14
+ end
15
+
16
+ log :insert, "Adding Font Awesome"
17
+ log :insert, "Adding navbar"
18
+ log :insert, "Adding alerts"
19
+ log :insert, "Adding sticky footer; you may need to add
20
+
21
+ padding-bottom: 70px
22
+
23
+ to the body of the document."
24
+
25
+ template "layout.html.erb", "app/views/layouts/#{options["layout_file"]}.html.erb"
26
+
27
+ template "_navbar.html.erb", "app/views/shared/_navbar.html.erb"
28
+
29
+ template "_flashes.html.erb", "app/views/shared/_flashes.html.erb"
30
+
31
+ unless skip_cdn?
32
+ template "_bootstrapcdn_assets.html.erb", "app/views/shared/_bootstrapcdn_assets.html.erb"
33
+ end
34
+ end
35
+
36
+ protected
37
+
38
+ def bootswatch?
39
+ if theme_name.present?
40
+ theme_name != "none"
41
+ end
42
+ end
43
+
44
+ def theme_name
45
+ options["theme"].downcase
46
+ end
47
+
48
+ def skip_cdn?
49
+ options["skip_cdn"]
50
+ end
51
+
52
+ def app_resources
53
+ route_names.reject { |name| /^rails_info.*/.match(name) || /^rails_mailers.*/.match(name) || name.pluralize != name }
54
+ end
55
+
56
+ def devise_routes
57
+ route_names.map do |name|
58
+ /new_(.*)_registration/.match(name)
59
+ end.compact
60
+ end
61
+
62
+ def route_names
63
+ @route_names ||= Rails.application.routes.routes.map(&:name).uniq.compact
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,10 @@
1
+ <% if bootswatch? -%>
2
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/4.0.0-beta.3/<%= theme_name %>/bootstrap.min.css">
3
+ <% else -%>
4
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
5
+ <% end -%>
6
+ <link rel="stylesheet"href="https://use.fontawesome.com/releases/v5.0.6/css/all.css" >
7
+
8
+ <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
9
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
10
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
@@ -0,0 +1,23 @@
1
+ <div class="row">
2
+ <div class="col-md-12">
3
+ <%% if notice.present? %>
4
+ <div class="alert alert-success alert-dismissable" role="alert">
5
+ <%%= notice %>
6
+
7
+ <button type="button" class="close" data-dismiss="alert" aria-label="Close">
8
+ <span aria-hidden="true">&times;</span>
9
+ </button>
10
+ </div>
11
+ <%% end %>
12
+
13
+ <%% if alert.present? %>
14
+ <div class="alert alert-warning alert-dismissable" role="alert">
15
+ <%%= alert %>
16
+
17
+ <button type="button" class="close" data-dismiss="alert" aria-label="Close">
18
+ <span aria-hidden="true">&times;</span>
19
+ </button>
20
+ </div>
21
+ <%% end %>
22
+ </div>
23
+ </div>
@@ -0,0 +1,75 @@
1
+ <nav class="navbar navbar-expand-lg navbar-light bg-light mb-4">
2
+ <div class="container">
3
+ <a class="navbar-brand" href="/">
4
+ <%= Rails.application.class.parent_name %>
5
+ </a>
6
+
7
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsible-nav-links" aria-controls="collapsible-nav-links" aria-expanded="false" aria-label="Toggle navigation">
8
+ <span class="navbar-toggler-icon"></span>
9
+ </button>
10
+
11
+ <div class="collapse navbar-collapse" id="collapsible-nav-links">
12
+ <ul class="navbar-nav mr-auto">
13
+ <li class="nav-item dropdown">
14
+ <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
15
+ Resources
16
+ </a>
17
+ <div class="dropdown-menu" aria-labelledby="navbarDropdown">
18
+ <% app_resources.each do |resource| -%>
19
+ <a href="/<%= resource %>" class="dropdown-item">
20
+ <%= resource.humanize.titleize %>
21
+ </a>
22
+ <% end -%>
23
+ </div>
24
+ </li>
25
+ </ul>
26
+ <% if devise_routes.any? -%>
27
+ <% devise_routes.each do |devise_route| -%>
28
+ <ul class="navbar-nav">
29
+ <%% if current_<%= devise_route[1]%>.blank? %>
30
+ <li class="nav-item">
31
+ <a href="/<%= devise_route[1].pluralize %>/sign_in" class="nav-link">
32
+ <% if devise_routes.size > 1 -%>
33
+ <%= devise_route[1].classify %> sign in
34
+ <% else -%>
35
+ Sign in
36
+ <% end -%>
37
+ </a>
38
+ </li>
39
+
40
+ <li class="nav-item">
41
+ <a href="/<%= devise_route[1].pluralize %>/sign_up" class="nav-link">
42
+ <% if devise_routes.size > 1 -%>
43
+ <%= devise_route[1].classify %> sign up
44
+ <% else -%>
45
+ Sign up
46
+ <% end -%>
47
+ </a>
48
+ </li>
49
+ <%% else %>
50
+ <li class="nav-item">
51
+ <a href="/<%= devise_route[1].pluralize %>/edit" class="nav-link">
52
+ <% if devise_routes.size > 1 -%>
53
+ <%= devise_route[1].classify %> edit profile
54
+ <% else -%>
55
+ Edit profile
56
+ <% end -%>
57
+ </a>
58
+ </li>
59
+
60
+ <li class="nav-item">
61
+ <a href="/<%= devise_route[1].pluralize %>/sign_out" data-method="delete" class="nav-link">
62
+ <% if devise_routes.size > 1 -%>
63
+ <%= devise_route[1].classify %> sign out
64
+ <% else -%>
65
+ Sign out
66
+ <% end -%>
67
+ </a>
68
+ </li>
69
+ <%% end %>
70
+ </ul>
71
+ <% end -%>
72
+ <% end -%>
73
+ </div> <!-- .navbar-collapse -->
74
+ </div> <!-- .container -->
75
+ </nav>
@@ -0,0 +1,40 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>
5
+ <%= Rails.application.class.parent_name %>
6
+ </title>
7
+
8
+ <% unless skip_cdn? -%>
9
+ <%%= render "shared/bootstrapcdn_assets" %>
10
+
11
+ <% end -%>
12
+ <%%= csrf_meta_tags %>
13
+
14
+ <%%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
15
+ <%%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
16
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tempusdominus-bootstrap-4/5.0.0-alpha14/css/tempusdominus-bootstrap-4.min.css" />
17
+ <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/tempusdominus-bootstrap-4/5.0.0-alpha14/js/tempusdominus-bootstrap-4.min.js"></script>
18
+ <script src="//maps.google.com/maps/api/js?v=3.24&key=AIzaSyCOTPWiuvyyo6sKoIBzKA4-1ol-vTOIOlM"></script>
19
+ <script src="//cdn.rawgit.com/mahnunchik/markerclustererplus/master/dist/markerclusterer.min.js"></script>
20
+
21
+
22
+ <meta name="viewport" content="width=device-width, initial-scale=1">
23
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
24
+ <meta charset="utf-8">
25
+ <style>
26
+ body { padding-bottom: 70px }
27
+ </style>
28
+ </head>
29
+
30
+ <body>
31
+ <%%= render "shared/navbar" %>
32
+
33
+ <div class="container">
34
+ <%%= render "shared/flashes" %>
35
+
36
+ <%%= yield %>
37
+ </div>
38
+
39
+ </body>
40
+ </html>
@@ -0,0 +1,14 @@
1
+ Description:
2
+
3
+ Generates the files you need to get started saving information to a
4
+ database table:
5
+
6
+ - A Ruby script that will create the database table (called a "migration")
7
+ - A Ruby class that will serve as a translator for talking to the table
8
+ (called a "model")
9
+ - A file that will make it easy to manage the table using the Active Admin
10
+ gem
11
+
12
+ Examples:
13
+
14
+ rails generate draft:model photo source:string caption:text
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/named_base"
4
+
5
+ module Draft
6
+ class ModelGenerator < Rails::Generators::NamedBase
7
+ argument :attributes, type: :array, default: [],
8
+ banner: "field[:type][:index] field[:type][:index]"
9
+ def generate_model
10
+ invoke "model"
11
+ end
12
+
13
+ def generate_active_admin
14
+ if Gem.loaded_specs.has_key? "activeadmin"
15
+ invoke "active_admin:resource", [singular_table_name]
16
+
17
+ permit_active_admin_params
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def permit_active_admin_params
24
+ if File.exist?("app/admin/#{singular_table_name}.rb")
25
+ insert_code(singular_table_name)
26
+ elsif File.exist?("app/admin/#{plural_table_name}.rb")
27
+ insert_code(plural_table_name)
28
+ end
29
+ end
30
+
31
+ def insert_code(file_name)
32
+ sentinel = /.*ActiveAdmin.register.*do.*/
33
+ inside "app" do
34
+ inside "admin" do
35
+ insert_into_file "#{file_name}.rb", after: sentinel do
36
+ "\n permit_params #{attributes_names.map { |name| ":#{name}" }.join(', ')}\n"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,11 @@
1
+ Description:
2
+
3
+ Generates an entire database-backed CRUD resource with a web interface:
4
+
5
+ - the database table (migration to create it)
6
+ - the model to interact with it
7
+ - routes, controller, and views for users to CRUD
8
+
9
+ Examples:
10
+
11
+ rails generate draft:resource post title body:text published:boolean
@@ -0,0 +1,172 @@
1
+ module Draft
2
+ class ResourceGenerator < Rails::Generators::NamedBase
3
+ source_root File.expand_path("../templates", __FILE__)
4
+
5
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
6
+ class_option :skip_model, type: :boolean, default: false, desc: "Skip model, migration, and specs"
7
+ class_option :skip_controller, type: :boolean, default: false, desc: "Skip controller and routes"
8
+ class_option :read_only, type: :boolean, default: false, desc: "Only generates the index and show actions"
9
+ class_option :skip_validation_alerts, type: :boolean, default: false, desc: "Skip validation failure alerts"
10
+ class_option :skip_post, type: :boolean, default: false, desc: "Skip HTTP POST verb"
11
+ class_option :skip_redirect, type: :boolean, default: false, desc: "Skip redirecting after create, update, and destroy"
12
+ class_option :only_new_form, type: :boolean, default: false, desc: "Generate association new form"
13
+ class_option :new_form_name, type: :string, default: "", desc: "Partial name"
14
+ class_option :associated_table_name, type: :string, default: "", desc: "Associatiated table name"
15
+ class_option :with_sentinels, type: :boolean, default: false, desc: "Skip adding comments to generated files"
16
+
17
+ def generate_controller
18
+ return if skip_controller?
19
+
20
+ if read_only?
21
+ template "controllers/read_only_controller.rb", "app/controllers/#{plural_table_name.underscore}_controller.rb"
22
+ else
23
+ template "controllers/controller.rb", "app/controllers/#{plural_table_name.underscore}_controller.rb"
24
+ end
25
+ end
26
+
27
+ def generate_model
28
+ return if skip_model?
29
+ invoke "draft:model"
30
+ end
31
+
32
+ def create_root_folder
33
+ empty_directory File.join("app/views", "#{singular_table_name}_templates")
34
+ end
35
+
36
+ def generate_view_files
37
+ available_views.each do |view|
38
+ filename = view_filename_with_extensions(view)
39
+ template filename, File.join("app/views", "#{singular_table_name}_templates", File.basename(options[:new_form_name].presence || filename))
40
+ end
41
+ end
42
+
43
+ def generate_routes
44
+ return if skip_controller?
45
+
46
+ if read_only?
47
+ read_only_routes
48
+ else
49
+ golden_seven_routes
50
+ end
51
+ end
52
+
53
+ def generate_specs
54
+ # Hotfix to prevent specs during MSM Associations
55
+ return
56
+ # return if read_only? || skip_controller? || skip_model?
57
+
58
+ template "specs/crud_spec.rb", "spec/features/crud_#{plural_table_name.underscore}_spec.rb"
59
+ template "specs/factories.rb", "spec/factories/#{plural_table_name.underscore}.rb"
60
+ end
61
+
62
+ private
63
+
64
+ def golden_seven_routes
65
+ log :route, "RESTful routes"
66
+
67
+ route <<-RUBY.gsub(/^ /, "")
68
+
69
+ # Routes for the #{singular_table_name.humanize} resource:
70
+
71
+ # CREATE
72
+ get("/#{plural_table_name}/new", { :controller => "#{plural_table_name}", :action => "new_form" })
73
+ #{skip_post? ? "get" : "post"}("/create_#{singular_table_name}", { :controller => "#{plural_table_name}", :action => "create_row" })
74
+
75
+ # READ
76
+ get("/#{plural_table_name}", { :controller => "#{plural_table_name}", :action => "index" })
77
+ get("/#{plural_table_name}/:id_to_display", { :controller => "#{plural_table_name}", :action => "show" })
78
+
79
+ # UPDATE
80
+ get("/#{plural_table_name}/:prefill_with_id/edit", { :controller => "#{plural_table_name}", :action => "edit_form" })
81
+ #{skip_post? ? "get" : "post"}("/update_#{singular_table_name}/:id_to_modify", { :controller => "#{plural_table_name}", :action => "update_row" })
82
+
83
+ # DELETE
84
+ get("/delete_#{singular_table_name}/:id_to_remove", { :controller => "#{plural_table_name}", :action => "destroy_row" })
85
+
86
+ #------------------------------
87
+ RUBY
88
+ end
89
+
90
+ def read_only_routes
91
+ log :route, "Index and show routes"
92
+
93
+ route <<-RUBY.gsub(/^ /, "")
94
+
95
+ # Routes for the #{singular_table_name.humanize} resource:
96
+
97
+ # READ
98
+ get("/#{plural_table_name}", { :controller => "#{plural_table_name}", :action => "index" })
99
+ get("/#{plural_table_name}/:id_to_display", { :controller => "#{plural_table_name}", :action => "show" })
100
+
101
+ #------------------------------
102
+ RUBY
103
+ end
104
+
105
+ def skip_controller?
106
+ options[:skip_controller] || options[:only_new_form]
107
+ end
108
+
109
+ def skip_model?
110
+ options[:skip_model] || options[:only_new_form]
111
+ end
112
+
113
+ def read_only?
114
+ options[:read_only]
115
+ end
116
+
117
+ def skip_validation_alerts?
118
+ options[:skip_validation_alerts]
119
+ end
120
+
121
+ def skip_post?
122
+ options[:skip_post]
123
+ end
124
+
125
+ def skip_redirect?
126
+ options[:skip_redirect]
127
+ end
128
+
129
+ def only_new_form?
130
+ options[:only_new_form]
131
+ end
132
+
133
+ def with_sentinels?
134
+ options[:with_sentinels]
135
+ end
136
+
137
+ def new_form_hidden_variable
138
+ "@#{options[:associated_table_name].singularize}.id"
139
+ end
140
+
141
+ def new_form_create_path
142
+ "create_#{singular_table_name}_from_#{options[:associated_table_name].singularize}"
143
+ end
144
+
145
+ def route(routing_code)
146
+ sentinel = /\.routes\.draw do(?:\s*\|map\|)?\s*$/
147
+
148
+ inside "config" do
149
+ insert_into_file "routes.rb", routing_code, after: sentinel
150
+ end
151
+ end
152
+
153
+ def available_views
154
+ if read_only?
155
+ %w(index show)
156
+ elsif skip_redirect?
157
+ %w(index show new_form create_row edit_form update_row destroy_row)
158
+ elsif only_new_form?
159
+ %w(association_new_form)
160
+ else
161
+ %w(index new_form new_form_with_errors edit_form edit_form_with_errors show)
162
+ end
163
+ end
164
+
165
+ def view_filename_with_extensions(name)
166
+ filename = [name, :html, :erb].compact.join(".")
167
+ folders = ["views"]
168
+ filename = File.join(folders, filename) if folders.any?
169
+ filename
170
+ end
171
+ end
172
+ end