I've been struggling with this for a while now and can't figure out what is happening. I'm working my way through Michael Hartl's Rails tutorial and have come to have an issue with some of my tests. These are the failing test results:
Failures:
1) User pages signup with invalid information should not create a user
Failure/Error: expect { click_button submit }.not_to change(User, :count)
ActionController::ParameterMissing:
param not found: user
# ./app/controllers/users_controller.rb:61:in `user_params'
# ./app/controllers/users_controller.rb:21:in `create'
# ./spec/requests/user_pages_spec.rb:89:in `block (5 levels) in <top (required)>'
# ./spec/requests/user_pages_spec.rb:89:in `block (4 levels) in <top (required)>'
2) User pages signup with invalid information after submission
Failure/Error: before { click_button submit }
ActionController::ParameterMissing:
param not found: user
# ./app/controllers/users_controller.rb:61:in `user_params'
# ./app/controllers/users_controller.rb:21:in `create'
# ./spec/requests/user_pages_spec.rb:93:in `block (5 levels) in <top (required)>'
3) User pages signup with invalid information after submission
Failure/Error: before { click_button submit }
ActionController::ParameterMissing:
param not found: user
# ./app/controllers/users_controller.rb:61:in `user_params'
# ./app/controllers/users_controller.rb:21:in `create'
# ./spec/requests/user_pages_spec.rb:93:in `block (5 levels) in <top (required)>'
4) User pages signup with valid information should create a user
Failure/Error: before { valid_signup(user) }
Capybara::ElementNotFound:
Unable to find field "Name"
# ./spec/support/utilities.rb:10:in `valid_signup'
# ./spec/requests/user_pages_spec.rb:102:in `block (4 levels) in <top (required)>'
5) User pages signup with valid information after saving the user
Failure/Error: before { valid_signup(user) }
Capybara::ElementNotFound:
Unable to find field "Name"
# ./spec/support/utilities.rb:10:in `valid_signup'
# ./spec/requests/user_pages_spec.rb:102:in `block (4 levels) in <top (required)>'
6) User pages signup with valid information after saving the user
Failure/Error: before { valid_signup(user) }
Capybara::ElementNotFound:
Unable to find field "Name"
# ./spec/support/utilities.rb:10:in `valid_signup'
# ./spec/requests/user_pages_spec.rb:102:in `block (4 levels) in <top (required)>'
7) User pages signup with valid information after saving the user
Failure/Error: before { valid_signup(user) }
Capybara::ElementNotFound:
Unable to find field "Name"
# ./spec/support/utilities.rb:10:in `valid_signup'
# ./spec/requests/user_pages_spec.rb:102:in `block (4 levels) in <top (required)>'
Finished in 9.1 seconds
119 examples, 7 failures
Failed examples:
rspec ./spec/requests/user_pages_spec.rb:88 # User pages signup with invalid information should not create a user
rspec ./spec/requests/user_pages_spec.rb:95 # User pages signup with invalid information after submission
rspec ./spec/requests/user_pages_spec.rb:96 # User pages signup with invalid information after submission
rspec ./spec/requests/user_pages_spec.rb:104 # User pages signup with valid information should create a user
rspec ./spec/requests/user_pages_spec.rb:113 # User pages signup with valid information after saving the user
rspec ./spec/requests/user_pages_spec.rb:115 # User pages signup with valid information after saving the user
rspec ./spec/requests/user_pages_spec.rb:116 # User pages signup with valid information after saving the user
So Here's my user_pages_spec.rb:
require 'spec_helper'
describe "User pages" do
subject { page }
describe "index" do
let(:user) { FactoryGirl.create(:user) }
before do
sign_in user
visit users_path
end
it { should have_title('All users') }
it { should have_content('All users') }
describe "pagination" do
before(:all) { 30.times { FactoryGirl.create(:user) } }
after(:all) { User.delete_all }
it { should have_selector('div.pagination') }
it "should list each user" do
#User.all.each do |user|
User.paginate(page: 1).each do |user|
expect(page).to have_selector('li', text: user.name)
end
end
end
describe "delete links" do
it { should_not have_link('delete') }
describe "as an admin user" do
let(:admin) { FactoryGirl.create(:admin) }
before do
sign_in admin
visit users_path
end
it { should have_link('delete', href: user_path(User.first)) }
it "should be able to delete another user" do
expect do
click_link('delete', match: :first)
end.to change(User, :count).by(-1)
end
it { should_not have_link('delete', href: user_path(admin)) }
end
end
end
describe "profile page" do
let(:user) { FactoryGirl.create(:user) }
let!(:m1) { FactoryGirl.create(:micropost, user: user, content: "Foo") }
let!(:m2) { FactoryGirl.create(:micropost, user: user, content: "Bar") }
before { visit user_path(user) }
it { should have_content(user.name) }
it { should have_title(user.name) }
describe "microposts" do
it { should have_content(m1.content) }
it { should have_content(m2.content) }
it { should have_content(user.microposts.count) }
end
end
describe "signup page" do
before { visit signup_path }
it { should have_content('Sign up') }
it { should have_title(full_title('Sign up')) }
end
describe "signup" do
before { visit signup_path }
let(:submit) { "Create my account" }
describe "with invalid information" do
it "should not create a user" do
expect { click_button submit }.not_to change(User, :count)
end
describe "after submission" do
before { click_button submit }
it { should have_title('Sign up') }
it { should have_content('error') }
end
end
describe "with valid information" do
let(:user) {FactoryGirl.build(:user)}
before { valid_signup(user) }
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
describe "after saving the user" do
before { click_button submit }
#let(:user) { User.find_by(email: '[email protected]') }
it { should have_title(user.name) }
#it { should have_selector('title', text: user.name) }
it { should have_selector('div.alert.alert-success', text: 'Welcome') }
it { should have_link('Sign out') }
end
end
end
describe "edit" do
let(:user) { FactoryGirl.create(:user) }
before do
sign_in user
visit edit_user_path(user)
end
describe "page" do
it { should have_content("Update your profile") }
it { should have_title("Edit user") }
it { should have_link('Change', href: 'http://gravatar.com/emails') }
end
describe "with invalid information" do
before { click_button "Save changes" }
it { should have_content('error') }
end
describe "with valid information" do
let(:new_name) { "New Name" }
let(:new_email) { "[email protected]" }
before do
fill_in "Name", with: new_name
fill_in "Email", with: new_email
fill_in "Password", with: user.password
fill_in "Confirm Password", with: user.password
click_button "Save changes"
end
it { should have_title(new_name) }
it { should have_selector('div.alert.alert-success') }
it { should have_link('Sign out', href: signout_path) }
specify { expect(user.reload.name).to eq new_name }
specify { expect(user.reload.email).to eq new_email }
end
describe "forbidden attributes" do
let(:params) do
{ user: {admin: true, password: user.password, password_confirmation: user.password } }
end
before do
sign_in user, no_capybara: true
patch user_path(user), params
end
specify { expect(user.reload).not_to be_admin }
end
end
end
users_controller.rb:
class UsersController < ApplicationController
before_action :signed_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
before_filter :signed_in_user_filter, only: [:new, :create]
def index
@users = User.paginate(page: params[:page])
end
def show
@user = User.find(params[:id])
@microposts = @user.microposts.paginate(page: params[:page])
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
sign_in @user
flash[:success] = "Welcome to the Sample App!"
redirect_to @user
else
render 'new'
end
end
def destroy
@user = User.find(params[:id])
if current_user == @user
flash[:error] = "You must not delete yourself."
#redirect_to users_path
else
@user.destroy
flash[:success] = "User deleted."
#redirect_to users_url
end
redirect_to users_path
end
def edit
#@user = User.find(params[:id])
end
def update
#@user = User.find(params[:id])
if @user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to @user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
#Before filters
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
def signed_in_user_filter
redirect_to root_path, notice: "Already logged in" if signed_in?
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
I'm not sure what else would be releveant but here's app/views/users/new.html.erb:
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(@user) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
To be honest I'm not 100% sure where to look for this problem. It just happened with these latest changes I've made in this chapter. I try to do all the exercises so sometimes there's variation in what I'm supposed to edit so I don't know if I've messed something up or perhaps just done something dumb. When I visit the app from a browser, and click the "Sign me up" link to register a new user I get the red rails error page that says ActionController::ParameterMissing in UsersController#create but I don't know exactly what that means. I didn't really think I changed any code that would affect that, but I've tinkered around with some stuff to try to complete previous exercises so perhaps that's whats happening.
Thanks for any help! This is my first SO post so hopefully I didn't make a huge mistake in etiquette/formatting. I searched for someone with similar problems, as usual, but couldn't find anything.
Edit: I wanted to add that I've been working off the previous version of this tutorial as I wasn't done when the new edition came out. You can find it here: http://rails-4-0.railstutorial.org/book/user_microposts
I think the answer is pretty simple. It looks like you deleted all of the fields out of your form when he only wanted you to add in the error rendering component. Your sign-up form should be something like:
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(@user) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>