2016-10-06 1 views
0

나는 http://railstutorial.org을 따르고 있습니다. 나는 10.2 섹션을 제외한 모든 것을 다 끝냈다. 그런 다음 어떤 종류의 문제가 발생했습니다. 내 현재 응용 프로그램 코드는 아래와 같습니다.form_for()에 yield()를 삽입하면 테스트에 의해 잡히지 않은 오류가 발생합니다.

섹션 7.3.4의 연습 2에서는 응용 프로그램에 몇 가지 코드를 추가했습니다. 결과적으로 경로를 업데이트하고 10.1.1 절 (코드 작성자는 yieldprovide 메서드를 사용하여 제안 함)에서 2를 실행하는 고유 한 솔루션을 만들어야했습니다. 그런 다음 사용자의 성공적인 편집 (10.1.3 절과 10.1.4 절)에 대한 테스트를 만들었습니다. 두 가지 테스트가 모두 통과되었지만 응용 프로그램이 예상대로 작동하지 않았습니다.

문제 설명 : 로그인하면 (인증은 10.2 섹션의 목표 임) 로그인하여 페이지/사용자/: id/edit 편집으로 이동하면 사이트가 작동합니다. '변경 사항 저장'버튼을 누르면 수정하려는 사용자에 관계없이 오류가 반환됩니다.

No route matches [PATCH] "https://stackoverflow.com/users/1/edit" 
Rails.root: /home/akazecik/workspace/sample_app 

모든 테스트가 통과합니다.

반면에 @useruser_path(@user)으로 바꾸면 edit.html.erb 파일에 오류가 사라지고 사이트가 정상적으로 작동합니다. 모든 테스트는 여전히 통과됩니다.

FAIL["test_invalid_signup_information", UsersSignupTest, 0.5256564110004547] 
test_invalid_signup_information#UsersSignupTest (0.53s) 
     Expected at least 1 element matching "form[action="/signup"]", found 0.. 
     Expected 0 to be >= 1. 
     test/integration/users_signup_test.rb:6:in `block in <class:UsersSignupTest>' 

: 나는 _form.html.erb 파일에 @useryield(:needed_link) 교체 (따라서 첫 번째 경우에서 yield 방법의 사용을 생략) 및 비 통과 테스트 (명백한 일을) 무시 '제 손'에

다시 작업 사이트를 얻고 나머지 테스트는 통과하는 것 같습니다.


그래서 제 질문은 다음과 같습니다

  • 왜 내 사이트가 작동하지 불구하고도 통과하는 시험이다? 내가 할 수 없더라도 users_edit_test.rb이 사용자를 업데이트 할 수있는 이유는 무엇입니까?
  • @useryield(:needed_link)의 차이점은 무엇입니까? provide(:needed_link, @user)?
  • 오른쪽은 10.2의 시작 부분에 우리가 읽고 그 행동 수정 및 업데이트 :

그들은 수 있도록 사람 (심지어 비 로그인 한 사용자) 중 액션, 및 액세스 할 수있는 로그인 한 사용자 다른 사용자의 정보를 업데이트 할 수 있습니다

로그인하지 않은 사용자도 정보를 업데이트 할 수 있기 때문에 그렇습니다. 내가 뭘 놓치고 있니? 로그인 한 상태라면 logged_in을 의미합니까? 메서드가 app/helpers/sessions_helper.rb이면 true를 반환합니다.


/app/views/users/new.html.erb

<% provide(:title, 'Sign up') %> 
<% provide(:button_text, 'Create my account') %> 
<% provide(:needed_link, signup_path) %> 
<h1>Sign up</h1> 
<div class="row"> 
    <div class="col-md-6 col-md-offset-3"> 
    <%= render 'form' %> 
    </div> 
</div> 

/app/views/users/edit.html.ERB

<% provide(:title, 'Edit user') %> 
<% provide(:button_text, 'Save changes') %> 
<% provide(:needed_link, @user) %> 
<h1>Update your profile</h1> 
<div class="row"> 
    <div class="col-md-6 col-md-offset-3"> 
    <%= render 'form' %> 
    <div class="gravatar_edit"> 
     <%= gravatar_for @user %> 
     <a href="http://gravatar.com/emails" target="_blank">Change</a> 
    </div> 
    </div> 
</div> 

/app/views/users/_form.html.erb

<%= form_for(@user, url: yield(:needed_link)) do |f| %> 
    <%= render 'shared/error_messages', object: @user %> 

    <%= f.label :name %> 
    <%= f.text_field :name, class: 'form-control' %> 

    <%= f.label :email %> 
    <%= f.email_field :email, class: 'form-control' %> 

    <%= f.label :password %> 
    <%= f.password_field :password, class: 'form-control' %> 

    <%= f.label :password_confirmation %> 
    <%= f.password_field :password_confirmation, class: 'form-control' %> 

    <%= f.submit yield(:button_text), class: "btn btn-primary" %> 
<% end %> 

응용 프로그램/컨트롤러/users_controller.rb

class UsersController < ApplicationController 
    def show 
    @user = User.find(params[:id]) 
    end 
    def new 
    @user = User.new 
    end 
    def create 
    @user = User.new(user_params)  # Not the final implementation! 
    if @user.save 
     log_in @user 
     flash[:success] = "Welcome to the Sample App!" 
     redirect_to user_url(@user) 
    else 
     render 'new' 
    end 
    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_path(@user) 
    else 
     render 'edit' 
    end 
    end 
    private 
     def user_params 
     params.require(:user).permit(:name, :email, :password, :password_confirmation) 
    end 
end 

테스트/통합 /users_edit_test.rb

require 'test_helper' 

class UsersEditTest < ActionDispatch::IntegrationTest 
    def setup 
    @user = users(:michael) 
    end 

    test "unsuccessful edit" do 
    get edit_user_path(@user) 
    assert_template 'users/edit' 
    patch user_path(@user), params: {user: { name: "", email: "[email protected]", password: "foo", password_confirmation: "bar" } } 
    assert_template 'users/edit' 
    assert_select 'div.alert', "The form contains 4 errors." 
    end 

    test "successful edit" do 
    get edit_user_path(@user) 
    assert_template 'users/edit' 
    name = "Foo Bar" 
    email = "[email protected]" 
    patch user_path(@user), params: { user: { name: name, 
               email: email, 
               password:    "", 
               password_confirmation: "" } } 
    assert_not flash.empty? 
    assert_redirected_to @user 
    @user.reload 
    assert_equal name, @user.name 
    assert_equal email, @user.email 
    end 
end 

시험/비품/users.yml

michael: 
    name: Michael Example 
    email: [email protected] 
    password_digest: <%= User.digest('password') %> 

응용 프로그램/도우미/sessions_helper.rb

module SessionsHelper 
    # Logs in the given user. 
    def log_in(user) 
     session[:user_id] = user.id 
    end 

    # Remembers a user in a persistent session. 
    def remember(user) 
    user.remember 
    cookies.permanent.signed[:user_id] = user.id 
    cookies.permanent[:remember_token] = user.remember_token 
    end 

    # Returns the current logged-in user (if any). 
    def current_user 
     if (user_id = session[:user_id]) 
     @current_user ||= User.find_by(id: user_id) 
     elsif (user_id = cookies.signed[:user_id]) 
     user = User.find_by(id: user_id) 
     if user && user.authenticated?(cookies[:remember_token]) 
      log_in user 
      @current_user = user 
     end 
     end 
    end 

    # Returns true if the user is logged in, false otherwise. 
    def logged_in? 
     !current_user.nil? 
    end 

    # Forgets a persistent session. 
    def forget(user) 
    user.forget 
    cookies.delete(:user_id) 
    cookies.delete(:remember_token) 
    end 

    # Logs out the current user. 
    def log_out 
    forget(current_user) 
    session.delete(:user_id) 
    @current_user = nil 
    end 
end 
+0

안녕하세요. 오버플로 스택을 환영합니다. 일반적으로 각 질문이 하나만 묻는 질문을 나누기를 선호합니다. 질문 : 하지만 내 대답은 '내 사이트가 작동하지 않아도 테스트를 통과하는 이유는 무엇입니까?'라고 대답하는 것부터 시작하겠습니다. 귀하의 검사는 실제로 부러진 것을 검사하지 않습니다. –

+0

세 번째 질문에 다시 답하십시오. 인증이없는 경우 로그인 한 사용자와 로그인하지 않은 사용자의 차이를 알 수 없으므로 올바른 인증을 추가 할 때까지 모든 사용자가 아무 것도 할 수 없습니다. 지금까지 해왔 던 것과 정확히 일치하지 않습니까? 그렇지 않다면 기대했던 것과 어떻게 다른가요? –

+1

@TarynEast 다음번에 더 잘 해보고 별도의 질문을 만들거나 독백을 다시 작성하여 하나의 질문 만 말합니다;) 대답을 참고하면 테스트되지 않은 내용을 한 눈에 볼 수 있습니까? 나는 코드를 통해 꽤 많은 시간을 보냈고 이유를 찾지 못했습니다. – AkaZecik

답변

0
<% provide(:needed_link, @user) %> 

@user는 링크 아니다 - 그것은이다 사용자 인스턴스 모델의 인스턴스를 링크 생성 메소드에 전달할 수 있습니다 (예 : 컨트롤러의 render 또는 템플릿의 link_to).이 메소드는 Rails-magic *을 사용하여 모델을 링크로 바꿉니다. 그러나 그렇지 않습니다. 그 자체의 링크입니다. 따라서 특수한 (쓴 적이없는) 방법이 아닌 장소에서 사용하려고하면 작동하지 않을 것입니다.

이것은 :link_needed 항목이 예상대로 작동하지 않는 이유 일 수 있습니다.

양식의 경우 url은 아마도 이러한 메서드 중 하나가 아니므로 edit_user_path(@user) 메서드를 사용하여 실제로 링크를 만들어야합니다.

* 뒷 배경에서 일부 레일 메소드는 모델에서 url_for을 호출하여 적절한 링크로 바꾼다.

+0

음,'@ user'를'form_for'에 직접 입력하면 작업 사이트가됩니다. 이 발언과 답을 고려할 때,'provide' 및/또는'yield' 메소드는 모델 객체를 허용하지 않으며'form_for' 메소드는 할당시 모델 객체로부터 url/path를 생성 할 수 있음을 의미합니까? ': url' 키? – AkaZecik

+0

'글쎄, @user를 form_for에 직접 넣으면 결과는 작동하는 사이트가된다.'form_for는 장면 뒤에 url_for를 사용하는 마법 메서드 중 하나이기 때문에 그렇다. :) 그러나 나는 그것을 ': url' 그래서 당신이 그것을 테스트하고 그것이 작동하지 않는다면, 나는 당신의 대답이라고 생각할 것입니다. 왜냐하면': url'은 완전한 형태의 URL을 기대하기 때문입니다. 'form_for'는'url_for' (예 : 모델)로 url이 될 수있는 모든 것일 수 있습니다. –

+0

'provide '와'yield'부분은 이것과 관련이 없습니다 ... 그들은 간접적 인 계층입니다. 실제 문제와 관련이 없습니다. 가장 중요한 문제는'@ user' 변수에': url'과'form_for'를 사용할 지 여부입니다. –

관련 문제