Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Scaffolded controller specs are compatible with Rails 4

* Rails 4 introduces
  [strong_parameters](https://github.com/rails/strong_parameters).
* If a model is scaffolded with attributes (e.g., `rails generate
  scaffold foo bar:string`), Rails will generate a controller that only
  accepts `bar`. This means that the controller spec must be aware of
  the specific parameters when sending PUT (update) requests.
* Furthermore if a model is scaffolded with attributes, Rails generates
  a controller that *requires* the #presence of attributes. This means
  we cannot send in an empty Hash, as the Rails framework will return a
  400 Bad Request.
  • Loading branch information...
commit 86b07996a990f19fc2769c182080894691d2fa79 1 parent be689da
alindeman alindeman authored
4 features/model_specs/errors_on.feature
View
@@ -8,7 +8,9 @@ Feature: errors_on
class ValidatingWidget < ActiveRecord::Base
self.table_name = :widgets
validates_presence_of :name
- attr_accessible :name
+
+ # In Rails 4, mass assignment protection is implemented on controllers
+ attr_accessible :name if Rails.version < '4'
validates_length_of :name, :minimum => 10, :on => :publication
end
38 lib/generators/rspec/scaffold/scaffold_generator.rb
View
@@ -57,8 +57,42 @@ def copy_view(view)
File.join("spec/views", controller_file_path, "#{view}.html.#{options[:template_engine]}_spec.rb")
end
- def params
- "{'these' => 'params'}"
+ def example_valid_attributes
+ # Only take the first attribute so this hash does not become unweildy and large in the
+ # generated controller spec. It is the responsibility of the user to keep the the valid
+ # attributes method up-to-date as they add validations.
+ @example_valid_attributes ||=
+ if attributes.any?
+ { attributes.first.name => attributes.first.default.to_s }
+ else
+ { }
+ end
+ end
+
+ def example_invalid_attributes
+ @example_invalid_attributes ||=
+ if attributes.any?
+ { attributes.first.name => "invalid value" }
+ else
+ { }
+ end
+ end
+
+ def example_params_for_update
+ @example_params_for_update ||=
+ if example_valid_attributes.any?
+ example_valid_attributes
+ else
+ { "these" => "params" }
+ end
+ end
+
+ def formatted_hash(hash)
+ formatted = hash.inspect
+ formatted.gsub!("{", "{ ")
+ formatted.gsub!("}", " }")
+ formatted.gsub!("=>", " => ")
+ formatted
end
# support for namespaced-resources
14 lib/generators/rspec/scaffold/templates/controller_spec.rb
View
@@ -24,7 +24,7 @@
# <%= class_name %>. As you add validations to <%= class_name %>, be sure to
# update the return value of this method accordingly.
def valid_attributes
- {}
+ <%= formatted_hash(example_valid_attributes) %>
end
# This should return the minimal set of values that should be in the session
@@ -91,14 +91,14 @@ def valid_session
it "assigns a newly created but unsaved <%= ns_file_name %> as @<%= ns_file_name %>" do
# Trigger the behavior that occurs when invalid params are submitted
<%= class_name %>.any_instance.stub(:save).and_return(false)
- post :create, {:<%= ns_file_name %> => {}}, valid_session
+ post :create, {:<%= ns_file_name %> => <%= formatted_hash(example_invalid_attributes) %>}, valid_session
assigns(:<%= ns_file_name %>).should be_a_new(<%= class_name %>)
end
it "re-renders the 'new' template" do
# Trigger the behavior that occurs when invalid params are submitted
<%= class_name %>.any_instance.stub(:save).and_return(false)
- post :create, {:<%= ns_file_name %> => {}}, valid_session
+ post :create, {:<%= ns_file_name %> => <%= formatted_hash(example_invalid_attributes) %>}, valid_session
response.should render_template("new")
end
end
@@ -112,8 +112,8 @@ def valid_session
# specifies that the <%= class_name %> created on the previous line
# receives the :update_attributes message with whatever params are
# submitted in the request.
- <%= class_name %>.any_instance.should_receive(:update_attributes).with(<%= params %>)
- put :update, {:id => <%= file_name %>.to_param, :<%= ns_file_name %> => <%= params %>}, valid_session
+ <%= class_name %>.any_instance.should_receive(:update_attributes).with(<%= formatted_hash(example_params_for_update) %>)
+ put :update, {:id => <%= file_name %>.to_param, :<%= ns_file_name %> => <%= formatted_hash(example_params_for_update) %>}, valid_session
end
it "assigns the requested <%= ns_file_name %> as @<%= ns_file_name %>" do
@@ -134,7 +134,7 @@ def valid_session
<%= file_name %> = <%= class_name %>.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
<%= class_name %>.any_instance.stub(:save).and_return(false)
- put :update, {:id => <%= file_name %>.to_param, :<%= ns_file_name %> => {}}, valid_session
+ put :update, {:id => <%= file_name %>.to_param, :<%= ns_file_name %> => <%= formatted_hash(example_invalid_attributes) %>}, valid_session
assigns(:<%= ns_file_name %>).should eq(<%= file_name %>)
end
@@ -142,7 +142,7 @@ def valid_session
<%= file_name %> = <%= class_name %>.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
<%= class_name %>.any_instance.stub(:save).and_return(false)
- put :update, {:id => <%= file_name %>.to_param, :<%= ns_file_name %> => {}}, valid_session
+ put :update, {:id => <%= file_name %>.to_param, :<%= ns_file_name %> => <%= formatted_hash(example_invalid_attributes) %>}, valid_session
response.should render_template("edit")
end
end
8 spec/generators/rspec/scaffold/scaffold_generator_spec.rb
View
@@ -14,6 +14,7 @@
before { run_generator %w(posts) }
it { should contain(/require 'spec_helper'/) }
it { should contain(/describe PostsController/) }
+ it { should contain(%({ "these" => "params" })) }
end
describe 'with --no-controller_specs' do
@@ -22,6 +23,13 @@
end
end
+ describe 'controller spec with attributes specified' do
+ subject { file('spec/controllers/posts_controller_spec.rb') }
+ before { run_generator %w(posts title:string) }
+
+ it { should contain(%({ "title" => "MyString" })) }
+ end
+
describe 'namespaced controller spec' do
subject { file('spec/controllers/admin/posts_controller_spec.rb') }
before { run_generator %w(admin/posts) }
Please sign in to comment.
Something went wrong with that request. Please try again.