firstdraft_generators 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +637 -0
  5. data/Gemfile +14 -0
  6. data/Gemfile.lock +83 -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/firstdraft_generators.gemspec +85 -0
  12. data/lib/firstdraft_generators.rb +2 -0
  13. data/lib/generators/draft/layout/USAGE +49 -0
  14. data/lib/generators/draft/layout/layout_generator.rb +70 -0
  15. data/lib/generators/draft/layout/templates/_bootstrapcdn_assets.html.erb +9 -0
  16. data/lib/generators/draft/layout/templates/_flashes.html.erb +17 -0
  17. data/lib/generators/draft/layout/templates/_footer.html.erb +33 -0
  18. data/lib/generators/draft/layout/templates/_navbar.html.erb +61 -0
  19. data/lib/generators/draft/layout/templates/layout.html.erb +31 -0
  20. data/lib/generators/draft/model/USAGE +14 -0
  21. data/lib/generators/draft/model/model_generator.rb +33 -0
  22. data/lib/generators/draft/resource/USAGE +11 -0
  23. data/lib/generators/draft/resource/resource_generator.rb +162 -0
  24. data/lib/generators/draft/resource/templates/controllers/controller.rb +98 -0
  25. data/lib/generators/draft/resource/templates/controllers/read_only_controller.rb +9 -0
  26. data/lib/generators/draft/resource/templates/specs/crud_spec.rb +300 -0
  27. data/lib/generators/draft/resource/templates/specs/factories.rb +34 -0
  28. data/lib/generators/draft/resource/templates/views/create_row.html.erb +13 -0
  29. data/lib/generators/draft/resource/templates/views/destroy_row.html.erb +13 -0
  30. data/lib/generators/draft/resource/templates/views/edit_form.html.erb +54 -0
  31. data/lib/generators/draft/resource/templates/views/index.html.erb +62 -0
  32. data/lib/generators/draft/resource/templates/views/new_form.html.erb +54 -0
  33. data/lib/generators/draft/resource/templates/views/show.html.erb +46 -0
  34. data/lib/generators/draft/resource/templates/views/update_row.html.erb +9 -0
  35. metadata +151 -0
@@ -0,0 +1,61 @@
1
+ <nav class="navbar navbar-default" role="navigation">
2
+ <div class="container">
3
+ <!-- Brand and toggle get grouped for better mobile display -->
4
+ <div class="navbar-header">
5
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#collapsible-nav-links">
6
+ <span class="sr-only">Toggle navigation</span>
7
+ <span class="icon-bar"></span>
8
+ <span class="icon-bar"></span>
9
+ <span class="icon-bar"></span>
10
+ </button>
11
+
12
+ <a href="/" class="navbar-brand">
13
+ <%= Rails.application.class.parent_name %>
14
+ </a>
15
+ </div>
16
+
17
+ <!-- Collect the nav links, forms, and other content for toggling -->
18
+ <div class="collapse navbar-collapse" id="collapsible-nav-links">
19
+ <ul class="nav navbar-nav">
20
+ <% app_resources.each do |resource| -%>
21
+ <li>
22
+ <a href="/<%= resource %>">
23
+ <%= resource.humanize.titleize %>
24
+ </a>
25
+ </li>
26
+ <% end -%>
27
+ </ul>
28
+ <% if devise_routes.any? -%>
29
+ <% devise_routes.each do |devise_route| -%>
30
+ <ul class="nav navbar-nav navbar-right">
31
+ <%% if current_<%= devise_route[1]%>.blank? %>
32
+ <li>
33
+ <a href="/<%= devise_route[1].pluralize %>/sign_in">
34
+ Sign in
35
+ </a>
36
+ </li>
37
+
38
+ <li>
39
+ <a href="/<%= devise_route[1].pluralize %>/sign_up">
40
+ Sign up
41
+ </a>
42
+ </li>
43
+ <%% else %>
44
+ <li>
45
+ <a href="/<%= devise_route[1].pluralize %>/edit">
46
+ Edit profile
47
+ </a>
48
+ </li>
49
+
50
+ <li>
51
+ <a href="/<%= devise_route[1].pluralize %>/sign_out" data-method="delete">
52
+ Sign out
53
+ </a>
54
+ </li>
55
+ <%% end %>
56
+ </ul>
57
+ <% end -%>
58
+ <% end -%>
59
+ </div><!-- /.navbar-collapse -->
60
+ </div>
61
+ </nav>
@@ -0,0 +1,31 @@
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
+ <%%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
14
+ <%%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
15
+
16
+ <meta name="viewport" content="width=device-width, initial-scale=1">
17
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
18
+ </head>
19
+
20
+ <body>
21
+ <%%= render "shared/navbar" %>
22
+
23
+ <div class="container">
24
+ <%%= render "shared/flashes" %>
25
+
26
+ <%%= yield %>
27
+ </div>
28
+
29
+ <%%= render "shared/footer" %>
30
+ </body>
31
+ </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,33 @@
1
+ module Draft
2
+ class ModelGenerator < Rails::Generators::NamedBase
3
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
4
+
5
+ def generate_model
6
+ invoke "active_record:model", ARGV
7
+ end
8
+
9
+ def generate_active_admin
10
+ if Gem.loaded_specs.has_key? "activeadmin"
11
+ invoke "active_admin:resource", [singular_table_name]
12
+
13
+ permit_active_admin_params
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def permit_active_admin_params
20
+ sentinel = /.*ActiveAdmin.register.*do.*/
21
+
22
+ if File.exist?("app/admin/#{singular_table_name}.rb")
23
+ inside "app" do
24
+ inside "admin" do
25
+ insert_into_file "#{singular_table_name}.rb", after: sentinel do
26
+ "\n permit_params #{attributes_names.map { |name| ":#{name}" }.join(", ")}\n"
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ 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,162 @@
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
+
13
+ def generate_controller
14
+ return if skip_controller?
15
+
16
+ if read_only?
17
+ template "controllers/read_only_controller.rb", "app/controllers/#{plural_table_name.underscore}_controller.rb"
18
+ else
19
+ template "controllers/controller.rb", "app/controllers/#{plural_table_name.underscore}_controller.rb"
20
+ end
21
+ end
22
+
23
+ def generate_model
24
+ return if skip_model?
25
+
26
+ invoke "draft:model", ARGV
27
+
28
+ if Gem.loaded_specs.has_key? "activeadmin"
29
+ invoke "active_admin:resource", [singular_table_name]
30
+
31
+ permit_active_admin_params
32
+ end
33
+ end
34
+
35
+ def generate_view_files
36
+ available_views.each do |view|
37
+ filename = view_filename_with_extensions(view)
38
+ template filename, File.join("app/views", "#{plural_table_name}_templates", File.basename(filename))
39
+ end
40
+ end
41
+
42
+ def generate_routes
43
+ return if skip_controller?
44
+
45
+ if read_only?
46
+ read_only_routes
47
+ else
48
+ golden_seven_routes
49
+ end
50
+ end
51
+
52
+ def generate_specs
53
+ return if read_only? || skip_controller? || skip_model?
54
+
55
+ template "specs/crud_spec.rb", "spec/features/crud_#{plural_table_name.underscore}_spec.rb"
56
+ template "specs/factories.rb", "spec/factories/#{plural_table_name.underscore}.rb"
57
+ end
58
+
59
+ private
60
+
61
+ def golden_seven_routes
62
+ log :route, "RESTful routes"
63
+
64
+ route <<-RUBY.gsub(/^ /, "")
65
+
66
+ # Routes for the #{singular_table_name.humanize} resource:
67
+
68
+ # CREATE
69
+ get("/#{plural_table_name}/new", { :controller => "#{plural_table_name}", :action => "new_form" })
70
+ #{skip_post? ? "get" : "post"}("/create_#{singular_table_name}", { :controller => "#{plural_table_name}", :action => "create_row" })
71
+
72
+ # READ
73
+ get("/#{plural_table_name}", { :controller => "#{plural_table_name}", :action => "index" })
74
+ get("/#{plural_table_name}/:id_to_display", { :controller => "#{plural_table_name}", :action => "show" })
75
+
76
+ # UPDATE
77
+ get("/#{plural_table_name}/:prefill_with_id/edit", { :controller => "#{plural_table_name}", :action => "edit_form" })
78
+ #{skip_post? ? "get" : "post"}("/update_#{singular_table_name}/:id_to_modify", { :controller => "#{plural_table_name}", :action => "update_row" })
79
+
80
+ # DELETE
81
+ get("/delete_#{singular_table_name}/:id_to_remove", { :controller => "#{plural_table_name}", :action => "destroy_row" })
82
+
83
+ #------------------------------
84
+ RUBY
85
+ end
86
+
87
+ def read_only_routes
88
+ log :route, "Index and show routes"
89
+
90
+ route <<-RUBY.gsub(/^ /, "")
91
+ # Routes for the #{singular_table_name.humanize} resource:
92
+
93
+ # READ
94
+ get("/#{plural_table_name}", { :controller => "#{plural_table_name}", :action => "index" })
95
+ get("/#{plural_table_name}/:id_to_display", { :controller => "#{plural_table_name}", :action => "show" })
96
+
97
+ #------------------------------
98
+ RUBY
99
+ end
100
+
101
+ def skip_controller?
102
+ options[:skip_controller]
103
+ end
104
+
105
+ def skip_model?
106
+ options[:skip_model]
107
+ end
108
+
109
+ def read_only?
110
+ options[:read_only]
111
+ end
112
+
113
+ def skip_validation_alerts?
114
+ options[:skip_validation_alerts]
115
+ end
116
+
117
+ def skip_post?
118
+ options[:skip_post]
119
+ end
120
+
121
+ def skip_redirect?
122
+ options[:skip_redirect]
123
+ end
124
+
125
+ def route(routing_code)
126
+ sentinel = /\.routes\.draw do(?:\s*\|map\|)?\s*$/
127
+
128
+ inside "config" do
129
+ insert_into_file "routes.rb", routing_code, after: sentinel
130
+ end
131
+ end
132
+
133
+ def permit_active_admin_params
134
+ sentinel = /.*ActiveAdmin.register.*do.*/
135
+
136
+ inside "app" do
137
+ inside "admin" do
138
+ insert_into_file "#{singular_table_name}.rb", after: sentinel do
139
+ "\n permit_params #{attributes_names.map { |name| ":#{name}" }.join(", ")}\n"
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ def available_views
146
+ if read_only?
147
+ %w(index show)
148
+ elsif skip_redirect?
149
+ %w(index show new_form create_row edit_form update_row destroy_row)
150
+ else
151
+ %w(index new_form edit_form show)
152
+ end
153
+ end
154
+
155
+ def view_filename_with_extensions(name)
156
+ filename = [name, :html, :erb].compact.join(".")
157
+ folders = ["views"]
158
+ filename = File.join(folders, filename) if folders.any?
159
+ filename
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,98 @@
1
+ class <%= plural_table_name.camelize %>Controller < ApplicationController
2
+ def index
3
+ @<%= plural_table_name.underscore %> = <%= class_name %>.all
4
+
5
+ render("<%= plural_table_name.underscore %>_templates/index.html.erb")
6
+ end
7
+
8
+ def show
9
+ @<%= singular_table_name.underscore %> = <%= class_name %>.find(params[:id_to_display])
10
+
11
+ render("<%= plural_table_name.underscore %>_templates/show.html.erb")
12
+ end
13
+
14
+ def new_form
15
+ <% unless skip_validation_alerts? -%>
16
+ @<%= singular_table_name.underscore %> = <%= class_name %>.new
17
+ <% end -%>
18
+ render("<%= plural_table_name.underscore %>_templates/new_form.html.erb")
19
+ end
20
+
21
+ def create_row
22
+ @<%= singular_table_name.underscore %> = <%= class_name %>.new
23
+
24
+ <% attributes.each do |attribute| -%>
25
+ @<%= singular_table_name.underscore %>.<%= attribute.column_name %> = params[:<%= attribute.column_name %>]
26
+ <% end -%>
27
+
28
+ <% unless skip_validation_alerts? -%>
29
+ save_status = @<%= singular_table_name.underscore %>.save
30
+
31
+ if save_status == true
32
+ redirect_to("/<%= @plural_table_name.underscore %>", :notice => "<%= singular_table_name.humanize %> created successfully.")
33
+ else
34
+ render("<%= plural_table_name.underscore %>_templates/new_form.html.erb")
35
+ end
36
+ <% else -%>
37
+ @<%= singular_table_name.underscore %>.save
38
+
39
+ <% unless skip_redirect? -%>
40
+ redirect_to("/<%= @plural_table_name.underscore %>")
41
+ <% else -%>
42
+ @current_count = <%= class_name %>.count
43
+
44
+ render("<%= plural_table_name.underscore %>_templates/create_row.html.erb")
45
+ <% end -%>
46
+ <% end -%>
47
+ end
48
+
49
+ def edit_form
50
+ @<%= singular_table_name.underscore %> = <%= class_name %>.find(params[:prefill_with_id])
51
+
52
+ render("<%= plural_table_name.underscore %>_templates/edit_form.html.erb")
53
+ end
54
+
55
+ def update_row
56
+ @<%= singular_table_name.underscore %> = <%= class_name %>.find(params[:id_to_modify])
57
+
58
+ <% attributes.each do |attribute| -%>
59
+ @<%= singular_table_name.underscore %>.<%= attribute.column_name %> = params[:<%= attribute.column_name %>]
60
+ <% end -%>
61
+
62
+ <% unless skip_validation_alerts? -%>
63
+ save_status = @<%= singular_table_name.underscore %>.save
64
+
65
+ if save_status == true
66
+ redirect_to("/<%= @plural_table_name.underscore %>/#{@<%= singular_table_name.underscore %>.id}", :notice => "<%= singular_table_name.humanize %> updated successfully.")
67
+ else
68
+ render("<%= plural_table_name.underscore %>_templates/edit_form.html.erb")
69
+ end
70
+ <% else -%>
71
+ @<%= singular_table_name.underscore %>.save
72
+
73
+ <% unless skip_redirect? -%>
74
+ redirect_to("/<%= @plural_table_name.underscore %>/#{@<%= singular_table_name.underscore %>.id}")
75
+ <% else -%>
76
+ render("<%= plural_table_name.underscore %>_templates/update_row.html.erb")
77
+ <% end -%>
78
+ <% end -%>
79
+ end
80
+
81
+ def destroy_row
82
+ @<%= singular_table_name.underscore %> = <%= class_name %>.find(params[:id_to_remove])
83
+
84
+ @<%= singular_table_name.underscore %>.destroy
85
+
86
+ <% unless skip_validation_alerts? -%>
87
+ redirect_to("/<%= @plural_table_name.underscore %>", :notice => "<%= singular_table_name.humanize %> deleted successfully.")
88
+ <% else -%>
89
+ <% unless skip_redirect? -%>
90
+ redirect_to("/<%= @plural_table_name.underscore %>")
91
+ <% else -%>
92
+ @remaining_count = <%= class_name %>.count
93
+
94
+ render("<%= plural_table_name.underscore %>_templates/destroy_row.html.erb")
95
+ <% end -%>
96
+ <% end -%>
97
+ end
98
+ end
@@ -0,0 +1,9 @@
1
+ class <%= plural_table_name.camelize %>Controller < ApplicationController
2
+ def index
3
+ @<%= plural_table_name.underscore %> = <%= class_name %>.all
4
+ end
5
+
6
+ def show
7
+ @<%= singular_table_name.underscore %> = <%= class_name %>.find(params[:id])
8
+ end
9
+ end
@@ -0,0 +1,300 @@
1
+ require "rails_helper"
2
+
3
+ feature "<%= plural_table_name.humanize.upcase %>" do
4
+ <% attributes.each do |attribute| -%>
5
+ context "index" do
6
+ it "has the <%= attribute.human_name.downcase %> of every row", points: 5 do
7
+ test_<%= plural_table_name %> = create_list(:<%= singular_table_name %>, 5)
8
+
9
+ visit "/<%= plural_table_name %>"
10
+
11
+ test_<%= plural_table_name %>.each do |current_<%= singular_table_name %>|
12
+ expect(page).to have_content(current_<%= singular_table_name %>.<%= attribute.column_name %>)
13
+ end
14
+ end
15
+ end
16
+
17
+ <% end -%>
18
+ context "index" do
19
+ it "has a link to the details page of every row", points: 5 do
20
+ test_<%= plural_table_name %> = create_list(:<%= singular_table_name %>, 5)
21
+
22
+ visit "/<%= plural_table_name %>"
23
+
24
+ test_<%= plural_table_name %>.each do |current_<%= singular_table_name %>|
25
+ expect(page).to have_css("a[href*='#{current_<%= singular_table_name %>.id}']", text: "Show details")
26
+ end
27
+ end
28
+ end
29
+
30
+ <% attributes.each do |attribute| -%>
31
+ context "details page" do
32
+ it "has the correct <%= attribute.human_name.downcase %>", points: 3 do
33
+ <%= singular_table_name %>_to_show = create(:<%= singular_table_name %>)
34
+
35
+ visit "/<%= plural_table_name %>"
36
+ find("a[href*='#{<%= singular_table_name %>_to_show.id}']", text: "Show details").click
37
+
38
+ expect(page).to have_content(<%= singular_table_name %>_to_show.<%= attribute.column_name %>)
39
+ end
40
+ end
41
+
42
+ <% end -%>
43
+ context "index" do
44
+ it "has a link to the new <%= singular_table_name.humanize.downcase %> page", points: 2 do
45
+ visit "/<%= plural_table_name %>"
46
+
47
+ expect(page).to have_css("a", text: "Add a new <%= singular_table_name.humanize.downcase %>")
48
+ end
49
+ end
50
+
51
+ <% attributes.each do |attribute| -%>
52
+ context "new form" do
53
+ it "saves the <%= attribute.human_name.downcase %> when submitted", points: 2, hint: h("label_for_input") do
54
+ visit "/<%= plural_table_name %>"
55
+ click_on "Add a new <%= singular_table_name.humanize.downcase %>"
56
+
57
+ <% case attribute.type -%>
58
+ <% when :belongs_to, :references -%>
59
+ test_<%= attribute.name %> = create(:<%= attribute.name %>)
60
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.name %>.id
61
+ <% when :boolean -%>
62
+ test_<%= attribute.column_name %> = <%= !attribute.default %>
63
+ check "<%= attribute.human_name %>"
64
+ <% when :date -%>
65
+ test_<%= attribute.column_name %> = 2.weeks.from_now.to_date
66
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
67
+ <% when :datetime -%>
68
+ test_<%= attribute.column_name %> = 2.days.from_now.to_datetime.beginning_of_minute
69
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
70
+ <% when :decimal -%>
71
+ test_<%= attribute.column_name %> = rand.round(4) * 100
72
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
73
+ <% when :integer, :primary_key -%>
74
+ test_<%= attribute.column_name %> = rand(1000)
75
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
76
+ <% when :string, :text -%>
77
+ test_<%= attribute.column_name %> = "A fake <%= attribute.human_name.downcase %> I'm typing at #{Time.now}"
78
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
79
+ <% when :time -%>
80
+ test_<%= attribute.column_name %> = 2.hours.from_now.to_time.round.change(year: 2000, month: 1, day: 1)
81
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
82
+ <% when :timestamp -%>
83
+ test_<%= attribute.column_name %> = 2.days.from_now.to_datetime.beginning_of_minute
84
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
85
+ <% else -%>
86
+ test_<%= attribute.column_name %> = "A fake <%= attribute.human_name.downcase %> I'm typing at #{Time.now}"
87
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
88
+ <% end -%>
89
+
90
+ click_on "Create <%= singular_table_name.humanize.downcase %>"
91
+
92
+ last_<%= singular_table_name %> = <%= singular_table_name.camelize %>.order(created_at: :asc).last
93
+ <% case attribute.type -%>
94
+ <% when :belongs_to, :references -%>
95
+ expect(last_<%= singular_table_name %>.<%= attribute.name %>).to eq(test_<%= attribute.name %>)
96
+ <% else -%>
97
+ expect(last_<%= singular_table_name %>.<%= attribute.column_name %>).to eq(test_<%= attribute.column_name %>)
98
+ <% end -%>
99
+ end
100
+ end
101
+
102
+ <% end -%>
103
+ <% unless skip_redirect? -%>
104
+ context "new form" do
105
+ it "redirects to the index when submitted", points: 2, hint: h("redirect_vs_render") do
106
+ visit "/<%= plural_table_name %>"
107
+ click_on "Add a new <%= singular_table_name.humanize.downcase %>"
108
+
109
+ click_on "Create <%= singular_table_name.humanize.downcase %>"
110
+
111
+ expect(page).to have_current_path("/<%= plural_table_name %>")
112
+ end
113
+ end
114
+
115
+ context "edit form" do
116
+ it "redirects to the details page with a notice", points: 3, hint: h("copy_must_match") do
117
+ visit "/<%= plural_table_name %>"
118
+
119
+ expect(page).to_not have_content("<%= singular_table_name.humanize %> created successfully.")
120
+
121
+ click_on "Add a new <%= singular_table_name.humanize.downcase %>"
122
+ click_on "Create <%= singular_table_name.humanize.downcase %>"
123
+
124
+ expect(page).to have_content("<%= singular_table_name.humanize %> created successfully.")
125
+ end
126
+ end
127
+
128
+ <% end -%>
129
+ context "details page" do
130
+ it "has a 'Delete <%= singular_table_name.humanize.downcase %>' link", points: 2 do
131
+ <%= singular_table_name %>_to_delete = create(:<%= singular_table_name %>)
132
+
133
+ visit "/<%= plural_table_name %>"
134
+ find("a[href*='#{<%= singular_table_name %>_to_delete.id}']", text: "Show details").click
135
+
136
+ expect(page).to have_css("a", text: "Delete")
137
+ end
138
+ end
139
+
140
+ context "delete link" do
141
+ it "removes a row from the table", points: 5 do
142
+ <%= singular_table_name %>_to_delete = create(:<%= singular_table_name %>)
143
+
144
+ visit "/<%= plural_table_name %>"
145
+ find("a[href*='#{<%= singular_table_name %>_to_delete.id}']", text: "Show details").click
146
+ click_on "Delete <%= singular_table_name.humanize.downcase %>"
147
+
148
+ expect(<%= singular_table_name.camelize %>.exists?(<%= singular_table_name %>_to_delete.id)).to be(false)
149
+ end
150
+ end
151
+
152
+ <% unless skip_redirect? -%>
153
+ context "delete link" do
154
+ it "redirects to the index", points: 3, hint: h("redirect_vs_render") do
155
+ <%= singular_table_name %>_to_delete = create(:<%= singular_table_name %>)
156
+
157
+ visit "/<%= plural_table_name %>"
158
+ find("a[href*='#{<%= singular_table_name %>_to_delete.id}']", text: "Show details").click
159
+ click_on "Delete <%= singular_table_name.humanize.downcase %>"
160
+
161
+ expect(page).to have_current_path("/<%= plural_table_name %>")
162
+ end
163
+ end
164
+
165
+ context "delete link" do
166
+ it "redirects to the index with a notice", points: 3, hint: h("copy_must_match") do
167
+ <%= singular_table_name %>_to_delete = create(:<%= singular_table_name %>)
168
+
169
+ visit "/<%= plural_table_name %>"
170
+ find("a[href*='#{<%= singular_table_name %>_to_delete.id}']", text: "Show details").click
171
+
172
+ expect(page).to_not have_content("<%= singular_table_name.humanize %> deleted successfully.")
173
+
174
+ click_on "Delete <%= singular_table_name.humanize.downcase %>"
175
+
176
+ expect(page).to have_content("<%= singular_table_name.humanize %> deleted successfully.")
177
+ end
178
+ end
179
+
180
+ <% end -%>
181
+ context "details page" do
182
+ it "has an 'Edit <%= singular_table_name.humanize.downcase %>' link", points: 5 do
183
+ <%= singular_table_name %>_to_edit = create(:<%= singular_table_name %>)
184
+
185
+ visit "/<%= plural_table_name %>"
186
+ find("a[href*='#{<%= singular_table_name %>_to_edit.id}']", text: "Show details").click
187
+
188
+ expect(page).to have_css("a", text: "Edit <%= singular_table_name.humanize.downcase %>")
189
+ end
190
+ end
191
+
192
+ <% attributes.each do |attribute| -%>
193
+ context "edit form" do
194
+ it "has <%= attribute.human_name.downcase %> pre-populated", points: 3, hint: h("value_attribute") do
195
+ <%= singular_table_name %>_to_edit = create(:<%= singular_table_name %>)
196
+
197
+ visit "/<%= plural_table_name %>"
198
+ find("a[href*='#{<%= singular_table_name %>_to_edit.id}']", text: "Show details").click
199
+ click_on "Edit <%= singular_table_name.humanize.downcase %>"
200
+
201
+ <% case attribute.field_type -%>
202
+ <% when :check_box -%>
203
+ <% when :text_area -%>
204
+ expect(page).to have_content(<%= singular_table_name %>_to_edit.<%= attribute.column_name %>)
205
+ <% else -%>
206
+ expect(page).to have_css("input[value='#{<%= singular_table_name %>_to_edit.<%= attribute.column_name %>}']")
207
+ <% end -%>
208
+ end
209
+ end
210
+
211
+ <% end -%>
212
+ <% attributes.each do |attribute| -%>
213
+ context "edit form" do
214
+ it "updates <%= attribute.human_name.downcase %> when submitted", points: 5, hint: h("label_for_input button_type") do
215
+ <%= singular_table_name %>_to_edit = create(:<%= singular_table_name %>, <%= attribute.column_name %>: "Boring old <%= attribute.human_name.downcase %>")
216
+
217
+ visit "/<%= plural_table_name %>"
218
+ find("a[href*='#{<%= singular_table_name %>_to_edit.id}']", text: "Show details").click
219
+ click_on "Edit <%= singular_table_name.humanize.downcase %>"
220
+
221
+ <% case attribute.type -%>
222
+ <% when :belongs_to, :references -%>
223
+ test_<%= attribute.name %> = create(:<%= attribute.name %>)
224
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.name %>.id
225
+ <% when :boolean -%>
226
+ test_<%= attribute.column_name %> = true
227
+ check "<%= attribute.human_name %>"
228
+ <% when :date -%>
229
+ test_<%= attribute.column_name %> = 2.weeks.from_now.to_date
230
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
231
+ <% when :datetime -%>
232
+ test_<%= attribute.column_name %> = 2.days.from_now.to_datetime.beginning_of_minute
233
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
234
+ <% when :decimal -%>
235
+ test_<%= attribute.column_name %> = rand.round(4) * 100
236
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
237
+ <% when :integer, :primary_key -%>
238
+ test_<%= attribute.column_name %> = rand(1000)
239
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
240
+ <% when :string, :text -%>
241
+ test_<%= attribute.column_name %> = "Exciting new <%= attribute.human_name.downcase %> at #{Time.now}"
242
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
243
+ <% when :time -%>
244
+ test_<%= attribute.column_name %> = 2.hours.from_now.to_time.round.change(year: 2000, month: 1, day: 1)
245
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
246
+ <% when :timestamp -%>
247
+ test_<%= attribute.column_name %> = 2.days.from_now.to_datetime.beginning_of_minute
248
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
249
+ <% else -%>
250
+ test_<%= attribute.column_name %> = "Exciting new <%= attribute.human_name.downcase %> at #{Time.now}"
251
+ fill_in "<%= attribute.human_name %>", with: test_<%= attribute.column_name %>
252
+ <% end -%>
253
+
254
+ click_on "Update <%= singular_table_name.humanize.downcase %>"
255
+
256
+ <%= singular_table_name %>_as_revised = <%= singular_table_name.camelize %>.find(<%= singular_table_name %>_to_edit.id)
257
+
258
+ <% case attribute.type -%>
259
+ <% when :belongs_to, :references -%>
260
+ expect(<%= singular_table_name %>_as_revised.<%= attribute.name %>).to eq(test_<%= attribute.name %>)
261
+ <% else -%>
262
+ expect(<%= singular_table_name %>_as_revised.<%= attribute.column_name %>).to eq(test_<%= attribute.column_name %>)
263
+ <% end -%>
264
+ end
265
+ end
266
+
267
+ <% end -%>
268
+ <% unless skip_redirect? -%>
269
+ context "edit form" do
270
+ it "redirects to the details page", points: 3, hint: h("embed_vs_interpolate redirect_vs_render") do
271
+ <%= singular_table_name %>_to_edit = create(:<%= singular_table_name %>)
272
+
273
+ visit "/<%= plural_table_name %>"
274
+ find("a[href*='#{<%= singular_table_name %>_to_edit.id}']", text: "Show details").click
275
+ details_page_path = page.current_path
276
+
277
+ click_on "Edit <%= singular_table_name.humanize.downcase %>"
278
+ click_on "Update <%= singular_table_name.humanize.downcase %>"
279
+
280
+ expect(page).to have_current_path(details_page_path, only_path: true)
281
+ end
282
+ end
283
+
284
+ context "edit form" do
285
+ it "redirects to the details page with a notice", points: 3, hint: h("copy_must_match") do
286
+ <%= singular_table_name %>_to_edit = create(:<%= singular_table_name %>)
287
+
288
+ visit "/<%= plural_table_name %>"
289
+ find("a[href*='#{<%= singular_table_name %>_to_edit.id}']", text: "Show details").click
290
+
291
+ expect(page).to_not have_content("<%= singular_table_name.humanize %> updated successfully.")
292
+
293
+ click_on "Edit <%= singular_table_name.humanize.downcase %>"
294
+ click_on "Update <%= singular_table_name.humanize.downcase %>"
295
+
296
+ expect(page).to have_content("<%= singular_table_name.humanize %> updated successfully.")
297
+ end
298
+ end
299
+ <% end -%>
300
+ end