0

编辑1:当我检查取消关注提交按钮的元素并将url末尾的变量更改为我知道的关系行ID时,它会删除正确的行,但然后告诉我找不到具有该ID的用户重定向我也是。所以我认为它将用户 id 发送到 destroy 方法,如果不存在具有该 id 的行,则会引发错误,或者如果确实退出,则会删除错误的关系。然后它使用相同的变量将您重新路由回您正在查看的用户配置文件。

edit2:取消关注部分已通过将(@relationship)添加到视图中的 form_tag 来解决。现在关系控制器“redirect_to user_path params[:id]”中的重定向正在寻找用户控制器中的索引方法,当我想我希望它寻找显示方法时,所以我现在正试图弄清楚这部分

我正在关注 Rails 教程并遇到了问题。从评论中,教程代码是错误的,所以我想知道这里是否有人可以指出我的解决方案,以便我可以继续教程的其余部分

我有可以创建帖子(ribbits)的用户。一个用户可以关注其他用户。我正在尝试使取消关注功能起作用。有一个包含字段 id、follower_id、followed_id 和时间戳的关系表。

关系创建方法工作正常,所有字段都正确填充。当我单击取消关注时,我收到以下错误

关系控制器中的 ActiveRecord::RecordNotFound#destroy 找不到 id=2 的关系

它从关系控制器::destroy 方法指向这段代码的行

        @relationship = Relationship.find(params[:id])

我不确定 params[:id] 来自或为什么被使用。据我所知,被关注的人的用户 ID 被传递给了 destroy 方法,而不是实际的关系 ID

这是其余的代码

关系控制器

class RelationshipsController < ApplicationController

    def create
        @relationship = Relationship.new
        @relationship.followed_id = params[:followed_id]
        @relationship.follower_id = current_user.id

        if @relationship.save
            redirect_to User.find params[:followed_id]
        else
            flash[:error] = "Couldn't Follow"
            redirect_to root_url
        end
    end

    def destroy
        @relationship = Relationship.find(params[:id])
        @relationship.destroy
        redirect_to user_path params[:id]
    end
end

用户模型

class User < ActiveRecord::Base

    before_save :create_avatar_url


    has_secure_password

    has_many :ribbits

    has_many :follower_relationships, class_name: "Relationship", foreign_key: "followed_id"
    has_many :followed_relationships, class_name: "Relationship", foreign_key: "follower_id"

    has_many :followers, through: :follower_relationships
    has_many :followeds, through: :followed_relationships


    validates :name, presence: true

    validates :username, uniqueness: true, presence: true

    validates :email, uniqueness: true, presence: true, format: { with: /\A[\w.+-]+@([\w]+.)+\w+\z/ }

    before_validation :prep_email

    def create_avatar_url
        self.avatar_url = "http://www.gravatar.com/avatar/#{Digest::MD5.hexdigest(self.email)}?s=50"
    end

    def following? user
        self.followeds.include? user
    end

    def follow user
        Relationship.create follower_id: self.id, followed_id: user.id
    end

    private

    def prep_email
        self.email = self.email.strip.downcase if self.email
    end
end

用户控制器

class UsersController < ApplicationController

    def new
        @user = User.new
    end

    def create
        @user = User.new(user_params)

        if @user.save
            session[:user_id] = @user.id
            redirect_to @user, notice: "Thank you for signing up for Ribbit!"
        else
            render 'new'
        end
    end

    def show
        @user = User.find(params[:id])
        @ribbit = Ribbit.new

        @relationship = Relationship.where(
            follower_id: current_user.id,
            followed_id: @user.id
            ).first_or_initialize if current_user
    end

    private

    def user_params
        params.require(:user)
                .permit(:avatar_url, :email, :name, :password, :password_confirmation, :username)
    end
end

显示.html.erb

<% if current_user %>
<div id="createRibbit" class="panel right">
    <h1>Create a Ribbit</h1>
    <p>
    <%= form_for @ribbit do |f| %>
        <%= f.text_area :content, class: 'ribbitText' %>
        <%= f.submit "Ribbit!" %>
    <% end %>
    </p>
</div>
<% end %>
<div id="ribbits" class="panel left">
    <h1>Your Ribbit Profile</h1>
    <div class="ribbitWrapper">
        <img class="avatar" src="<%= @user.avatar_url %>">
        <span class="name"><%= @user.name %></span> @<%= @user.username %>
        <p>
        <%= @user.ribbits.size %> Ribbits
        <span class="spacing"><%= @user.followers.count %> Followers</span>
        <span class="spacing"><%= @user.followeds.count %> Following</span>
        </p>
        <% if current_user and @user != current_user %>
            <% if current_user.following? @user %>
                <%= form_tag relationship_path, method: :delete do %>
                    <%= submit_tag "Unfollow" %>
                <% end %>
            <% else %>
                <%= form_for @relationship do %>
                    <%= hidden_field_tag :followed_id, @user.id %>
                    <%= submit_tag "Follow" %>
                <% end %>
            <% end %>
        <% end %>
    </div>
</div>
<div class="panel left">
    <h1>Your Ribbits</h1>
    <% @user.ribbits.each do |ribbit| %>
        <div class="ribbitWrapper">
            <img class="avatar" src="<%= @user.avatar_url %>">
            <span class="name"><%= @user.name %></span> 
            @<%= @user.username %> 
            <span class="time"><%= time_ago_in_words(ribbit.created_at) %></span>
            <p> <%= ribbit.content %> </p>
        </div>
    <% end %>
</div>
4

2 回答 2

0

问题确实出在这一行:

<%= form_tag relationship_path, method: :delete do %>

我怀疑您在 show 方法中查找的 @relationship 应该在 url 帮助程序中提供:

<%= form_tag relationship_path(@relationship), method: :delete do %>

在当前版本的 Rails 中,您甚至可以将其缩短为:

<%= form_tag @relationship, method: :delete do %>

假设您的模型 (Relationship) 并具有相应的控制器 (RelationshipsController),那么 Rails 将正确地从您的实例变量中推断出 url。

我会第二次 musicnerd47 的建议,即这应该是一个链接而不是一个表单。

<%= link_to 'Unfollow', @relationship, method: :delete %>

这将更容易设计风格。

于 2013-10-31T18:37:18.183 回答
0

params 哈希是传递给控制器​​动作的任何东西。调试它的一个好方法是raise params.to_yaml用作控制器操作的第一行。它可以让你看到正在传递的内容。目前,看起来你并没有传递你应该破坏的关系。为什么不尝试使用:

<%= form_tag relationship_path(@user.followed_relationships.where(follower: current_user)), method: :delete do %>

或者,我绝对不会为您的取消关注方法使用完整的表格。为什么不直接使用链接?您可以尝试以下方法,而不是表单:

<%= link_to('Unfollow', relationship_path(@user.followed_relationships.where(follower: current_user)), method: :delete) %>
于 2013-10-31T18:11:24.520 回答