我跟随http://railstutorial.org。我把所有内容都排除在10.2以外。然后我遇到了某种问题。我目前的申请代码如下。
7.3.4节中的练习2让我向应用程序添加了一些额外的代码。因此,我必须更新路线并在第10.1.1节中创建我自己的解决方案练习2(作者建议使用yield
和provide
方法,我做过 - 在代码中看到)。在这之后,我创建了一个成功和不成功编辑用户的测试(第10.1.3和10.1.4节)。两个测试都通过了,但我的应用程序没有按预期工作。
问题描述:当我登录时(不是必需的,授权是10.2部分的目标)并转到编辑页面/ users /:id / edit,网站正常工作。当我按"保存更改"按钮,它返回一个错误(无论我尝试编辑哪个用户):
No route matches [PATCH] "/users/1/edit"
Rails.root: /home/akazecik/workspace/sample_app
并且所有测试都通过了。
另一方面,当我将@user
替换为user_path(@user)
文件中的edit.html.erb
时,错误消失了,网站正常工作。所有测试仍然通过。
在第三手牌上'当我在yield(:needed_link)
文件中用@user
替换_form.html.erb
时(因此省略了第一种情况下使用yield
方法)并忽略不通过测试(显而易见的事情):< / p>
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>'
我再次获得工作现场,其余的测试似乎都过去了。
所以我的问题是:
users_edit_test.rb
能够更新用户,即使我不能@user
和yield(:needed_link)
与provide(:needed_link, @user)
之间有什么区别?他们允许任何人(甚至是非登录用户)访问任一操作, 任何登录用户都可以更新任何其他用户的信息
情况并非如此,因为即使是非登录用户,我也可以更新信息。我错过了什么?登录后,我的意思是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: "foo@invalid", 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 = "foo@bar.com"
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: michael@example.com
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)
<% provide(:needed_link, @user) %>
@user
不是链接 - 它是用户实例。您可以将模型的实例传递给链接生成方法(例如,控制器中的render
或模板中的link_to
),该方法使用Rails-magic *将模型转换为链接......但它本身并不是链接,所以如果你试图在一个不是特殊(不成文)方法之一的地方使用它......它就不会工作。< / p>
这可能就是为什么:link_needed
的东西没有按照你预期的方式运作。
表单的url
可能不是其中一种方法......所以您需要使用edit_user_path(@user)
方法实际创建链接。
*幕后,一些rails方法在模型上调用url_for
将其转换为正确的链接 - 但只有一些方法。