无法从特定表中删除特定行

时间:2013-10-31 17:55:56

标签: ruby-on-rails ruby ruby-on-rails-4

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

edit2:通过将(@relationship)添加到视图中的form_tag来解决取消关注部分。现在关系控制器'redirect_to user_path params [:id]'中的重定向正在寻找用户控制器中的索引方法,当我想要它寻找show方法时所以我现在想要找出那个部分

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

我有用户可以创建帖子(ribbits)。用户可以关注其他用户。我试图让unfollow功能工作。有一个关系表,其中包含字段id,follower_id,followed_id和timestamps。

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

  

RelationshipsController中的ActiveRecord :: RecordNotFound#destroy   无法找到与id = 2的关系

它指向relations_controller :: destroy方法

中此代码的行
        @relationship = Relationship.find(params[:id])

我不确定params [:id]来自何处或为何使用它。从我可以告诉跟随的人用户ID被传递给destroy方法而不是实际的关系id

这是代码的其余部分

relationshipsController

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

show.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>

2 个答案:

答案 0 :(得分: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) %>

答案 1 :(得分:0)

问题实际上在于这一行:

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

我怀疑你在show方法中查找的@relationship应该在url helper中提供:

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

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

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

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

我的第二个音乐家47的建议是,这应该是链接而不是表格。

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

风格会更容易。