make_resourceful_rails2 1.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.
- data/Rakefile +31 -0
- data/VERSION +1 -0
- data/lib/make_resourceful.rb +2 -0
- data/lib/resourceful/base.rb +63 -0
- data/lib/resourceful/builder.rb +405 -0
- data/lib/resourceful/default/accessors.rb +418 -0
- data/lib/resourceful/default/actions.rb +101 -0
- data/lib/resourceful/default/callbacks.rb +51 -0
- data/lib/resourceful/default/responses.rb +118 -0
- data/lib/resourceful/default/urls.rb +136 -0
- data/lib/resourceful/generators/resourceful_scaffold/resourceful_scaffold_generator.rb +87 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/controller.rb +5 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/fixtures.yml +10 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/functional_test.rb +50 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/helper.rb +2 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/migration.rb +13 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/model.rb +2 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/unit_test.rb +7 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/view__form.haml +5 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/view_edit.haml +11 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/view_index.haml +5 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/view_new.haml +9 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/view_partial.haml +12 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/view_show.haml +14 -0
- data/lib/resourceful/maker.rb +92 -0
- data/lib/resourceful/response.rb +33 -0
- data/lib/resourceful/serialize.rb +185 -0
- data/spec/accessors_spec.rb +474 -0
- data/spec/actions_spec.rb +310 -0
- data/spec/base_spec.rb +12 -0
- data/spec/builder_spec.rb +332 -0
- data/spec/callbacks_spec.rb +71 -0
- data/spec/integration_spec.rb +394 -0
- data/spec/maker_spec.rb +91 -0
- data/spec/response_spec.rb +37 -0
- data/spec/responses_spec.rb +314 -0
- data/spec/serialize_spec.rb +133 -0
- data/spec/urls_spec.rb +282 -0
- metadata +114 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'resourceful/builder'
|
2
|
+
|
3
|
+
module Resourceful
|
4
|
+
module Default
|
5
|
+
# This module is mostly meant to be used by the make_resourceful default actions.
|
6
|
+
# It provides various methods that declare where callbacks set in the +make_resourceful+ block,
|
7
|
+
# like Builder#before and Builder#response_for,
|
8
|
+
# should be called.
|
9
|
+
module Callbacks
|
10
|
+
# Calls any +before+ callbacks set in the +make_resourceful+ block for the given event.
|
11
|
+
def before(event)
|
12
|
+
resourceful_fire(:before, event.to_sym)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Calls any +after+ callbacks set in the +make_resourceful+ block for the given event.
|
16
|
+
def after(event)
|
17
|
+
resourceful_fire(:after, event.to_sym)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Calls any +response_for+ callbacks set in the +make_resourceful+ block for the given event.
|
21
|
+
# Note that these aren't called directly,
|
22
|
+
# but instead passed along to Rails' respond_to method.
|
23
|
+
def response_for(event)
|
24
|
+
if responses = self.class.resourceful_responses[event.to_sym]
|
25
|
+
respond_to do |format|
|
26
|
+
responses.each do |key, value|
|
27
|
+
format.send(key, &scope(value))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns a block identical to the given block,
|
34
|
+
# but in the context of the current controller.
|
35
|
+
# The returned block accepts no arguments,
|
36
|
+
# even if the given block accepted them.
|
37
|
+
def scope(block)
|
38
|
+
proc do
|
39
|
+
instance_eval(&(block || proc {}))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def resourceful_fire(type, name)
|
46
|
+
callbacks = self.class.resourceful_callbacks[type][name] || []
|
47
|
+
callbacks.each { |callback| scope(callback).call }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Resourceful
|
2
|
+
module Default
|
3
|
+
module Responses
|
4
|
+
# Sets the default flash message.
|
5
|
+
# This message can be overridden by passing in
|
6
|
+
# an HTTP parameter of the form "_flash[type]" via POST or GET.
|
7
|
+
#
|
8
|
+
# You can use this to easily have multiple forms
|
9
|
+
# post to the same create/edit/destroy actions
|
10
|
+
# but display different flash notices -
|
11
|
+
# without modifying the controller code at all.
|
12
|
+
#
|
13
|
+
# By default, the flash types are +notice+ when the database operation completes successfully
|
14
|
+
# and +error+ when it fails.
|
15
|
+
#
|
16
|
+
#--
|
17
|
+
# TODO: Move this out of here
|
18
|
+
#++
|
19
|
+
def set_default_flash(type, message)
|
20
|
+
flash[type] ||= (params[:_flash] && params[:_flash][type]) || message
|
21
|
+
end
|
22
|
+
|
23
|
+
# Sets the default redirect
|
24
|
+
# (the argument passed to +redirect_to+).
|
25
|
+
# This message can be overridden by passing in
|
26
|
+
# an HTTP parameter of the form "_redirect_on[status]" via POST or GET.
|
27
|
+
#
|
28
|
+
# You can use this to easily have multiple forms
|
29
|
+
# post to the same create/edit/destroy actions
|
30
|
+
# but redirect to different URLs -
|
31
|
+
# without modifying the controller code at all.
|
32
|
+
#
|
33
|
+
# By default, the redirect statuses are +success+ when the database operation completes successfully
|
34
|
+
# and +failure+ when it fails.
|
35
|
+
# Use the <tt>:status</tt> option to specify which status to run the redirect for.
|
36
|
+
# For example:
|
37
|
+
#
|
38
|
+
# set_default_redirect "/posts", :status => :failure
|
39
|
+
#
|
40
|
+
# This will run <tt>redirect_to params[:_redirect_on][:failure]</tt> if the parameter exists,
|
41
|
+
# or <tt>redirect_to "/posts"</tt> otherwise.
|
42
|
+
#
|
43
|
+
#--
|
44
|
+
# TODO: Move this out of here
|
45
|
+
#++
|
46
|
+
def set_default_redirect(to, options = {})
|
47
|
+
status = options[:status] || :success
|
48
|
+
redirect_to (params[:_redirect_on] && params[:_redirect_on][status]) || to
|
49
|
+
end
|
50
|
+
|
51
|
+
# This method is automatically run when this module is included in Resourceful::Base.
|
52
|
+
# It sets up the default responses for the default actions.
|
53
|
+
def self.included(base)
|
54
|
+
base.made_resourceful do
|
55
|
+
response_for(:show, :index, :edit, :new) do |format|
|
56
|
+
format.html
|
57
|
+
format.js
|
58
|
+
end
|
59
|
+
|
60
|
+
response_for(:show_fails) do |format|
|
61
|
+
not_found = Proc.new { render :text => I18n.t('make_resourceful.show.fails', :default => "No item found"), :status => 404 }
|
62
|
+
format.html ¬_found
|
63
|
+
format.js ¬_found
|
64
|
+
format.xml ¬_found
|
65
|
+
end
|
66
|
+
|
67
|
+
response_for(:create) do |format|
|
68
|
+
format.html do
|
69
|
+
set_default_flash :notice, I18n.t('make_resourceful.create.success', :default => "Create successful!")
|
70
|
+
set_default_redirect object_path
|
71
|
+
end
|
72
|
+
format.js
|
73
|
+
end
|
74
|
+
|
75
|
+
response_for(:create_fails) do |format|
|
76
|
+
format.html do
|
77
|
+
set_default_flash :error, I18n.t('make_resourceful.create.fails', :default => "There was a problem!")
|
78
|
+
render :action => :new, :status => 422
|
79
|
+
end
|
80
|
+
format.js
|
81
|
+
end
|
82
|
+
|
83
|
+
response_for(:update) do |format|
|
84
|
+
format.html do
|
85
|
+
set_default_flash :notice, I18n.t('make_resourceful.update.success', :default => "Save successful!")
|
86
|
+
set_default_redirect object_path
|
87
|
+
end
|
88
|
+
format.js
|
89
|
+
end
|
90
|
+
|
91
|
+
response_for(:update_fails) do |format|
|
92
|
+
format.html do
|
93
|
+
set_default_flash :error, I18n.t('make_resourceful.update.fails', :default => "There was a problem saving!")
|
94
|
+
render :action => :edit, :status => 422
|
95
|
+
end
|
96
|
+
format.js
|
97
|
+
end
|
98
|
+
|
99
|
+
response_for(:destroy) do |format|
|
100
|
+
format.html do
|
101
|
+
set_default_flash :notice, I18n.t('make_resourceful.destroy.success', :default => "Record deleted!")
|
102
|
+
set_default_redirect objects_path
|
103
|
+
end
|
104
|
+
format.js
|
105
|
+
end
|
106
|
+
|
107
|
+
response_for(:destroy_fails) do |format|
|
108
|
+
format.html do
|
109
|
+
set_default_flash :error, I18n.t('make_resourceful.destroy.fails', :default => "There was a problem deleting!")
|
110
|
+
set_default_redirect :back, :status => :failure
|
111
|
+
end
|
112
|
+
format.js
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module Resourceful
|
2
|
+
module Default
|
3
|
+
# This file contains various methods to make URL helpers less painful.
|
4
|
+
# They provide methods analogous to the standard foo_url and foo_path helpers.
|
5
|
+
# However, they use make_resourceful's knowledge of the structure of the controller
|
6
|
+
# to allow you to avoid figuring out which method to call and which parent objects it should be passed.
|
7
|
+
module URLs
|
8
|
+
# This returns the path for the given object,
|
9
|
+
# by default current_object[link:classes/Resourceful/Default/Accessors.html#M000012].
|
10
|
+
# For example, in HatsController the following are equivalent:
|
11
|
+
#
|
12
|
+
# object_path #=> "/hats/12"
|
13
|
+
# hat_path(@hat) #=> "/hats/12"
|
14
|
+
#
|
15
|
+
def object_path(object = current_object); object_route(object, 'path'); end
|
16
|
+
# Same as object_path, but with the protocol and hostname.
|
17
|
+
def object_url (object = current_object); object_route(object, 'url'); end
|
18
|
+
|
19
|
+
# This is the same as object_path,
|
20
|
+
# unless a parent exists.
|
21
|
+
# Then it returns the nested path for the object.
|
22
|
+
# For example, in HatsController where Person has_many :hats and <tt>params[:person_id] == 42</tt>,
|
23
|
+
# the following are equivalent:
|
24
|
+
#
|
25
|
+
# nested_object_path #=> "/person/42/hats/12"
|
26
|
+
# person_hat_path(@person, @hat) #=> "/person/42/hats/12"
|
27
|
+
#
|
28
|
+
def nested_object_path(object = current_object); nested_object_route(object, 'path'); end
|
29
|
+
# Same as nested_object_path, but with the protocol and hostname.
|
30
|
+
def nested_object_url (object = current_object); nested_object_route(object, 'url'); end
|
31
|
+
|
32
|
+
# This returns the path for the edit action for the given object,
|
33
|
+
# by default current_object[link:classes/Resourceful/Default/Accessors.html#M000012].
|
34
|
+
# For example, in HatsController the following are equivalent:
|
35
|
+
#
|
36
|
+
# edit_object_path #=> "/hats/12/edit"
|
37
|
+
# edit_person_hat_path(@person, @hat) #=> "/hats/12/edit"
|
38
|
+
#
|
39
|
+
def edit_object_path(object = current_object); edit_object_route(object, 'path'); end
|
40
|
+
# Same as edit_object_path, but with the protocol and hostname.
|
41
|
+
def edit_object_url (object = current_object); edit_object_route(object, 'url'); end
|
42
|
+
|
43
|
+
# This returns the path for the collection of the current controller.
|
44
|
+
# For example, in HatsController where Person has_many :hats and <tt>params[:person_id] == 42</tt>,
|
45
|
+
# the following are equivalent:
|
46
|
+
#
|
47
|
+
# objects_path #=> "/people/42/hats"
|
48
|
+
# person_hats_path(@person) #=> "/people/42/hats"
|
49
|
+
#
|
50
|
+
def objects_path; objects_route('path'); end
|
51
|
+
# Same as objects_path, but with the protocol and hostname.
|
52
|
+
def objects_url ; objects_route('url'); end
|
53
|
+
|
54
|
+
# This returns the path for the new action for the current controller.
|
55
|
+
# For example, in HatsController where Person has_many :hats and <tt>params[:person_id] == 42</tt>,
|
56
|
+
# the following are equivalent:
|
57
|
+
#
|
58
|
+
# new_object_path #=> "/people/42/hats/new"
|
59
|
+
# new_person_hat_path(@person) #=> "/people/42/hats/new"
|
60
|
+
#
|
61
|
+
def new_object_path; new_object_route('path'); end
|
62
|
+
# Same as new_object_path, but with the protocol and hostname.
|
63
|
+
def new_object_url ; new_object_route('url'); end
|
64
|
+
|
65
|
+
# This returns the path for the parent object.
|
66
|
+
#
|
67
|
+
def parent_path(object = parent_object)
|
68
|
+
instance_route(parent_class_name.underscore, object, 'path')
|
69
|
+
end
|
70
|
+
# Same as parent_path, but with the protocol and hostname.
|
71
|
+
def parent_url(object = parent_object)
|
72
|
+
instance_route(parent_class_name.underscore, object, 'url')
|
73
|
+
end
|
74
|
+
|
75
|
+
# This prefix is added to the Rails URL helper names
|
76
|
+
# before they're called.
|
77
|
+
# By default, it's the underscored list of namespaces of the current controller,
|
78
|
+
# or nil if there are no namespaces defined.
|
79
|
+
# However, it can be overridden if another prefix is needed.
|
80
|
+
# Note that if this is overridden,
|
81
|
+
# the new method should return a string ending in an underscore.
|
82
|
+
#
|
83
|
+
# For example, in Admin::Content::PagesController:
|
84
|
+
#
|
85
|
+
# url_helper_prefix #=> "admin_content_"
|
86
|
+
#
|
87
|
+
# Then object_path is the same as <tt>admin_content_page_path(current_object)</tt>.
|
88
|
+
def url_helper_prefix
|
89
|
+
namespaces.empty? ? nil : "#{namespaces.join('_')}_"
|
90
|
+
end
|
91
|
+
|
92
|
+
# This prefix is added to the Rails URL helper names
|
93
|
+
# for the make_resourceful collection URL helpers,
|
94
|
+
# objects_path and new_object_path.
|
95
|
+
# By default, it's the parent name followed by an underscore if a parent
|
96
|
+
# is given, and the empty string otherwise.
|
97
|
+
#
|
98
|
+
# See also url_helper_prefix.
|
99
|
+
def collection_url_prefix
|
100
|
+
parent? ? "#{parent_class_name.underscore}_" : ''
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def object_route(object, type)
|
106
|
+
instance_route(current_model_name.underscore, object, type)
|
107
|
+
end
|
108
|
+
|
109
|
+
def nested_object_route(object, type)
|
110
|
+
return object_route(object, type) unless parent?
|
111
|
+
send("#{url_helper_prefix}#{parent_class_name.underscore}_#{current_model_name.underscore}_#{type}", parent_object, object)
|
112
|
+
end
|
113
|
+
|
114
|
+
def edit_object_route(object, type)
|
115
|
+
instance_route(current_model_name.underscore, object, type, "edit")
|
116
|
+
end
|
117
|
+
|
118
|
+
def objects_route(type)
|
119
|
+
collection_route(current_model_name.pluralize.underscore, type)
|
120
|
+
end
|
121
|
+
|
122
|
+
def new_object_route(type)
|
123
|
+
collection_route(current_model_name.underscore, type, "new")
|
124
|
+
end
|
125
|
+
|
126
|
+
def instance_route(name, object, type, action = nil)
|
127
|
+
send("#{action ? action + '_' : ''}#{url_helper_prefix}#{collection_url_prefix unless shallow?}#{name}_#{type}", *(parent? && !shallow? ? [parent_object, object] : [object]))
|
128
|
+
end
|
129
|
+
|
130
|
+
def collection_route(name, type, action = nil)
|
131
|
+
send("#{action ? action + '_' : ''}#{url_helper_prefix}#{collection_url_prefix}#{name}_#{type}",
|
132
|
+
*(parent? ? [parent_object] : []))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
class ResourcefulScaffoldGenerator < Rails::Generators::Base
|
2
|
+
attr_reader :controller_class_path,
|
3
|
+
:controller_file_path,
|
4
|
+
:controller_class_nesting,
|
5
|
+
:controller_class_nesting_depth,
|
6
|
+
:controller_class_name,
|
7
|
+
:controller_underscore_name,
|
8
|
+
:controller_plural_name
|
9
|
+
alias_method :controller_file_name, :controller_underscore_name
|
10
|
+
alias_method :controller_table_name, :controller_plural_name
|
11
|
+
|
12
|
+
def initialize(runtime_args, runtime_options = {})
|
13
|
+
super
|
14
|
+
|
15
|
+
base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@name.pluralize)
|
16
|
+
@controller_class_name_without_nesting, @controller_underscore_name, @controller_plural_name = inflect_names(base_name)
|
17
|
+
|
18
|
+
if @controller_class_nesting.empty?
|
19
|
+
@controller_class_name = @controller_class_name_without_nesting
|
20
|
+
else
|
21
|
+
@controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def manifest
|
26
|
+
record do |m|
|
27
|
+
# Check for class naming collisions.
|
28
|
+
m.class_collisions(controller_class_path, "#{controller_class_name}Controller", "#{controller_class_name}Helper")
|
29
|
+
m.class_collisions(class_path, "#{class_name}")
|
30
|
+
|
31
|
+
# Controller, helper, views, and test directories.
|
32
|
+
m.directory(File.join('app/models', class_path))
|
33
|
+
m.directory(File.join('app/controllers', controller_class_path))
|
34
|
+
m.directory(File.join('app/helpers', controller_class_path))
|
35
|
+
m.directory(File.join('app/views', controller_class_path, controller_file_name))
|
36
|
+
m.directory(File.join('test/functional', controller_class_path))
|
37
|
+
m.directory(File.join('test/unit', class_path))
|
38
|
+
m.directory(File.join('test/fixtures', class_path))
|
39
|
+
|
40
|
+
# Views
|
41
|
+
for action in scaffold_views
|
42
|
+
m.template("view_#{action}.haml", File.join('app/views', controller_class_path, controller_file_name, "#{action}.html.haml"))
|
43
|
+
end
|
44
|
+
m.template('view_partial.haml', File.join('app/views', controller_class_path, controller_file_name, "_#{singular_name}.html.haml"))
|
45
|
+
|
46
|
+
# Helper
|
47
|
+
m.template('helper.rb', File.join('app/helpers', controller_class_path, "#{controller_file_name}_helper.rb"))
|
48
|
+
|
49
|
+
# Model
|
50
|
+
m.template('model.rb', File.join('app/models', class_path, "#{file_name}.rb"))
|
51
|
+
|
52
|
+
unless options[:skip_migration]
|
53
|
+
m.migration_template('migration.rb', 'db/migrate',
|
54
|
+
:assigns => {
|
55
|
+
:migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}",
|
56
|
+
:attributes => attributes
|
57
|
+
},
|
58
|
+
:migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}")
|
59
|
+
end
|
60
|
+
|
61
|
+
# Controller
|
62
|
+
m.template('controller.rb', File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb"))
|
63
|
+
|
64
|
+
# Tests
|
65
|
+
m.template('functional_test.rb', File.join('test/functional', controller_class_path, "#{controller_file_name}_controller_test.rb"))
|
66
|
+
m.template('unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb"))
|
67
|
+
m.template('fixtures.yml', File.join('test/fixtures', "#{table_name}.yml"))
|
68
|
+
|
69
|
+
# Route
|
70
|
+
m.route_resources controller_file_name
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
protected
|
75
|
+
|
76
|
+
def banner
|
77
|
+
"Usage: #{$0} resourcefulscaffold ModelName [field:type, field:type]"
|
78
|
+
end
|
79
|
+
|
80
|
+
def scaffold_views
|
81
|
+
%w[ index show new edit _form ]
|
82
|
+
end
|
83
|
+
|
84
|
+
def model_name
|
85
|
+
class_name.demodulize
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.dirname(__FILE__) + '<%= '/..' * controller_class_nesting_depth %>/../test_helper'
|
2
|
+
require '<%= controller_file_path %>_controller'
|
3
|
+
|
4
|
+
# Re-raise errors caught by the controller.
|
5
|
+
class <%= controller_class_name %>Controller; def rescue_action(e) raise e end; end
|
6
|
+
|
7
|
+
class <%= controller_class_name %>ControllerTest < ActionController::TestCase
|
8
|
+
|
9
|
+
def test_should_get_index
|
10
|
+
get :index
|
11
|
+
assert_response :success
|
12
|
+
assert assigns(:<%= table_name %>)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_should_get_new
|
16
|
+
get :new
|
17
|
+
assert_response :success
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_create_<%= file_name %>
|
21
|
+
old_count = <%= class_name %>.count
|
22
|
+
post :create, :<%= file_name %> => { }
|
23
|
+
assert_equal old_count + 1, <%= class_name %>.count
|
24
|
+
|
25
|
+
assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>))
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_should_show_<%= file_name %>
|
29
|
+
get :show, :id => 1
|
30
|
+
assert_response :success
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_should_get_edit
|
34
|
+
get :edit, :id => 1
|
35
|
+
assert_response :success
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_should_update_<%= file_name %>
|
39
|
+
put :update, :id => 1, :<%= file_name %> => { }
|
40
|
+
assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>))
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_should_destroy_<%= file_name %>
|
44
|
+
old_count = <%= class_name %>.count
|
45
|
+
delete :destroy, :id => 1
|
46
|
+
assert_equal old_count-1, <%= class_name %>.count
|
47
|
+
|
48
|
+
assert_redirected_to <%= table_name %>_path
|
49
|
+
end
|
50
|
+
end
|