8.2 sign up failure

chapter 8.2

 

for this section, we will do this:

 

if a signup form has invalid submission, the app will re-render the signup page, show the error details.

 

1. we will do TDD again!!!

 

resources :users

 

this line in routes.rb prepare many REST urls for us.

 

for example, a POST request to /users is handled by the create action.

 

2. the create action is to use the form submission to make a new user object using User.new, try to save this user object, and then render the signup page for resubmission.

 

so we will write test to test this work flow, then write create action to Users controller to make it pass.

 

let's see the test code first:

 

 

require 'spec_helper'

describe UsersController do
  render_views
  .
  .
  .

  describe "POST 'create'" do

    describe "failure" do

      before(:each) do
        @attr = { :name => "", :email => "", :password => "",
                  :password_confirmation => "" }
      end

      it "should not create a user" do
        lambda do
          post :create, :user => @attr
        end.should_not change(User, :count)
      end

      it "should have the right title" do
        post :create, :user => @attr
        response.should have_selector("title", :content => "Sign up")
      end

      it "should render the 'new' page" do
        post :create, :user => @attr
        response.should render_template('new')
      end
    end
  end
end

 a. response.should have_selector()

b. response.should render_template('new')

 

c. then let's learn two new tricks in the first example.

 

it "should not create a user" do
  lambda do
    post :create, :user => @attr
  end.should_not change(User, :count)
end

 this is to verify the failed create action doesn't create a user in the database.

 

--->  should_not change(User, :count)

this will compare the User.count value before and after the excution of the former part of code.

 

----> the lambda is a Ruby construct, it will take a block, wrap the codes in the block into a package.

 

 

3. next, we will implement the create function.

 

def create
    @user = User.new(params[:user])
    if @user.save
      # Handle a successful save.
    else
      @title = "Sign up"
      render 'new'
    end
  end

 when invoking the create action, our app will receive a params hash

params(:user) is

{:name => "", :email => "", .......}

params(:action)

params(:authenticity_token)

params(:controller)

 

the magic come from the name attr in the element of html form.

 

<input id="user_email" name="user[email]" size="30" type="text" />

 

note, if the submit fails, in the re-rendered page, some fields are pre-filled.

the reason is that, 

form_for auto fills in the fields with the attr of @user object.

so

 

    <input id="user_name" name="user[name]" size="30" type="text" value="Foo"/>
 

 

4. sign up error messages:

 

We want to display the error messages.

 

so we render a partial into the new.html.erb:

 

  <%= render 'shared/error_messages' %>

 

so the partial lives in views/shared/_error_messages.html.erb

 

<% if @user.errors.any? %>
	<div id="error_explanation">
		<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user rom being saved:</h2>
		<p>There were problems with the following fields:</p>
		<ul>
			<%@user.errors.full_messages.each do |msg| %>
				<li><%= msg%></li>
			<% end %>
		</ul>
	</div>
<% end %>

 from this part of code, we learned:

 

User.count---------> return the record count.

array.count  -------> return the count of the array.

array.empty?

array.any?

 

b. we learn the helper method:

 

pluralize(@user.errors.count, "error")

 

c. we used id="error_explanation", so in custom.css file, there be an entry of #error_explanation

(#... to specify a css of a id)

 

and Rails automatically wraps the fields with errors in divs with the css class "field_with_errors"

 

so you can specify your own css by define 

 

.field_with_errors 

 

in your customed css file.

 

 

5. filtering params logging.

 

before rails 3, the password will be recorded in the log file, without being filtered.

Rails 3 changed to default to filter password.

 

it is set in config/application.rb

 

 

    config.filter_parameters += [:password]
 

if you want to filter other fields, like "secret_code"

you can change this config:

 

    config.filter_parameters += [:password, :secret_code]
 

 

你可能感兴趣的:(sign)