【问题标题】:Destroy a has_many :through is not working with link_to helper销毁 has_many :through 不适用于 link_to 助手
【发布时间】:2015-08-15 20:27:07
【问题描述】:

我正在 Rails 4 中开发一个简单的项目管理工具,让我头疼的部分主要有三个模型:ProjectsUsersMemberships

用户可以有很多项目,项目也可以有很多用户。我通过以下方式在项目和用户之间实现了has_many through 成员关系:

项目:

class Project < ActiveRecord::Base
  has_many :memberships
  has_many :users, through: :memberships
end

用户:

class User < ActiveRecord::Base
   has_many :memberships
   has_many :projects, through: :memberships
end

会员:

class Membership < ActiveRecord::Base
    belongs_to :user
    belongs_to :project
end

到目前为止,我还没有在 Stack Overflow 上看到它,但我为 Memberships 创建了一个单独的控制器,只有 :create:destroy。 到目前为止,:create 似乎工作得很好。

主要问题在于会员资格的销毁功能。 我实现的destroy函数是:

def destroy
    Membership.find(:id).destroy
    redirect_to current_project || request.referer
end

rake routes 说会员路径存在,但以下尝试给了我:

我尝试使用link_to helper 删除会员资格:

<%= link_to "delete", membership, method: :delete %> 
EDIT: error: undefined local variable or method `membership' 

<%= link_to "delete", @membership, method: :delete %>
EDIT: error: Sorry something went wrong --> goes to /memberships

<%= link_to "delete, membership_path(@membership), method: :delete %>
EDIT: error No route matches {:action=>"destroy", :controller=>"memberships", :id=>nil} missing required keys: [:id]

这都给出了错误。

编辑:还应要求提供projects_controller #show 功能

def show
    @user = current_user
    @project = current_user.projects.find(params[:id])
    @members = @project.users
    @projects = @user.projects
    @membership = @project.memberships.build if logged_in?
    @memberships = @project.memberships
end 

如何确保删除具有@project.membership_ids 中关联 ID 的成员资格?我应该包含某些额外的参数吗?

【问题讨论】:

  • 他们给出什么样的错误?错误是在生成链接时发生还是在单击时发生?
  • 您能否发布控制器操作的代码,该操作显示“删除”链接到会员资格?我认为问题在于呈现该视图,而不是 MembershipController 类上的 destroy 方法。
  • 我添加了 Project#show 函数。到目前为止,当我单击链接时会引发错误,具体取决于会员路径的代码。

标签: ruby-on-rails ruby


【解决方案1】:

resources :memberships, only: [:create, :destroy]

更新

不知道我之前是怎么错过的,在你的销毁操作中你有Membership.find(:id).destroy。它应该利用参数并且更符合以下原则:

# MembershipsController
def destroy
    @membership = Membership.find(params[:id])
    if @membership.destroy
        redirect_to current_project || request.referer
    else
        #
    end
end

您的ProjectsController 的显示操作未将@membership 定义为Membership 对象。

def show
    @user = current_user
    @project = @user.projects.find(params[:id])
    @membership = Membership.find_by user: @user, project: @project

    # build is used for nested attributes, not sure why you'd have this in a show action...
    # @project.memberships.build if logged_in?

    # the following are redundant.
    @projects = @user.projects
    @members = @project.users
    @memberships = @project.memberships
end 

在视图中:&lt;%= link_to "delete", @membership, method: :delete %&gt;

如果您希望在删除父项时销毁项目或用户的所有成员资格,请对您的 UserProject 模型进行以下更改:

class Project < ActiveRecord::Base
    has_many :memberships, dependent: :destroy
    has_many :users, through: :memberships
end

class User < ActiveRecord::Base
    has_many :memberships, dependent: :destroy
    has_many :projects, through: :memberships
end

【讨论】:

  • 错误包含在上面。路由正是您建议的方式。 :)
  • 它渲染得很好,但是当点击它时,它会路由到/memberships。没有索引,所以它给出了“我们很抱歉,但出了点问题”错误。
  • 谢谢@kjmagic13。它仍然给出“找不到没有 ID 的项目”错误。但这可能是因为在路由器文件中我没有将成员资格嵌套到项目中,而是将它们视为单独的资源。这可能是一个问题吗?
  • 我发现并解决了我的问题,主要是因为您的回答!所以谢谢你:) 问题是我必须在删除请求中传递参数,否则它只是不知道删除后它必须去哪里。我用一个方法实现了一个 form_for: :delete.
【解决方案2】:

您的代码不起作用的原因是您没有指定link_to 的路径。我认为您不需要@membership,所以我将其编辑了。

<%= link_to "delete", membership_path(@membership), method: :delete %>

【讨论】:

  • 不要简单地扔掉代码,而是解释为什么应该使用它。扔代码就像给某人一条鱼。解释它是在教他们如何钓鱼。
  • 很公平。您的代码不起作用的原因是您没有指定 link_to 的路径。我不相信你需要有@membership,所以我把它编辑了。
  • membership_path 需要一个对象传递给它,否则 Rails 将不知道要删除什么。
  • 也许我应该为你澄清一下。正确的语法是membership_path(@membership)。这不是link_to 方法中的另一个参数。
  • 你是对的......现在对我来说是清晨,一个人从裂缝中溜走了!
猜你喜欢
  • 2010-11-26
  • 2015-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多