10.1 updating users.

1. git checkout -b updating-users

 

2. in this chapter, we will make you can update user profile.

a. we will use a "edit" action to render a view to edit user.

b. we will use "update" action and a "PUT" request to update user profile

c. we need to make sure only current user can update their information. this need a "before_filter"

 

3. edit form, we will start from TDD again!!

 

describe UserController do
	describe "get 'edit'" do
		before(:each) do
			@user = Factory(:user)
			test_sign_in(@user)
		end

		it "should be success" do
			get :edit, :id => @user
			response.should be_success
		end
		it "should have the right title" do
			get :edit, :id => @user
			response.should have_selector("title", :content => "Edit user")
		end
		it "should have the link to gravatar" do
			get :edit, :id => @user
			gravatar_url = "http://gravatar.com/emails"
			response.should have_selector("a", :href => gravatar_url, :content => "change")
		end
	end
end

 4. now it is time to write the view code:

 

<h1>Edit User</h1>

<%= form_for @user do |f| %>
	<%= render "shared/error_messages", :object => f.object %>
	<div class="field">
		<%= f.label :name %>								<br />
		<%= f.text_field :name %>							<br />
		<%= f.label :email %>								<br />
		<%= f.text_field :email %>							<br />
		<%= f.label :password %>							<br />
		<%= f.password_field :password %>					<br />
		<%= f.label :password_confirmation, "Confirmation" %><br />
		<%= f.password_field :password_confirmation %>		<br />
	</div>
	<div class="action">
		<%= f.submit "Update"%>
	</div>
<% end %>

<div>
	<%= gravatar_for @user %>
	<a href="http://gravatar.com/emails">Change</a>
</div>

you can find we passed a object param when rendering partial .

this is common because a real partial should not rely on the fact that there is a @user object.

this is especially useful when composing a form, 

<%= render 'shared/error_messages', :object => f.object %>

 

 this create a var called object in the partial, 

 

now we need to re-write the _error_messages partial:

 

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

 we can learn two helper method here:

 

"ActiveRecord".underscore ======> active_record  (lower case and add _ )


"active_record".humanize =======> Active record  (capitalize, and replace _ with space.)

 

5. next, let's look at the html gened by the form:

 

 

<form action="/users/1" class="edit_user" id="edit_user_1" method="post">
  <input name="_method" type="hidden" value="put" />
  . . . </form>

 

note this hidden line:

 

since web browser can't natively send "PUT" request, rails fake it with a post request, and a hidden input field.

 

6. there is another magic that you may wondering,

 

we use the same code for edit form and new form, but why the html generated are different?

for new action, rails use a post method, and for edit action, rails use a put method.

 

the answer is simple and trikey, rails will run

 

@user.new_record?

 

to judge if this record is a new one, or already exist in database.

 

so rails will know to use a put request or post request, clever?? cool!

 

7. next is the test for update success and update failure.

  describe "PUT 'update'" do
    before(:each) do
      @user = Factory(:user)
      test_sign_in(@user)
    end
    describe "update failure" do
      before(:each) do
        @attr = {:name => "", :email => "", :password => "", :password_confirmation => "" }
      end
      it "should render the edit page" do
        put :update, :id => @user, :user => @attr
        response.should render_template('edit')
      end
      it "should have the right title" do
        put :update, :id => @user, :user => @attr
        response.should have_selector("title", :content => "Edit user")
      end
    end

    describe "update success" do
      before(:each) do
        @attr = { :name => "New Name", :email => "user@example.org",
                          :password => "barbaz", :password_confirmation => "barbaz" }
      end
      it "should redirect to user show page" do
        put :update, :id => @user, :user => @attr
        response.should redirect_to user_path(@user)
      end
      it "should change user's attrs" do
        put :update, :id => @user, :user => @attr
        @user.reload
        @user.name.should == @attr[:name]
        @user.email.should == @attr[:email]
      end
      it "should have a flash message" do
        put :update, :id => @user, :user => @attr
        flash[:success].should =~ /updated/i
      end
    end
  end

 one thing to note:

 

@user.reload  ========> this will reload the @user content from database.

 

8. next, we will implement the update method in the controller:

 

  def update
    @user = User.find_by_id(params[:id])
    if @user.update_attributes(params[:user])
      flash[:success] = "Profile updated"
      redirect_to @user
    else
      @title = "Edit user"
      render 'edit'
    end
  end
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值