Rails 5.1,删除有条件的多条记录

时间:2018-02-02 15:13:58

标签: ruby-on-rails ruby-on-rails-5 conditional-statements record destroy

我尝试根据一些条件删除数据库中的多条记录。在我谈论我的问题之前,我将解释我的应用程序是如何工作的。

用户可以创建组和链接。此用户拥有他为链接创建的组。然后,其他用户可以通过成员模型提供令牌(在创建组时自动创建)来加入此组。其中成员在DB中具有user_id和group_id。然后,一旦用户成为组的一部分,他就可以通过Grouplink模型共享他在组中创建的链接。其中grouplink有groupd_id和link_id。

我设法编写了一个事实,即如果一个组中没有成员,该组就会被销毁。但是,如果用户离开群组,如何删除用户在群组中共享的链接? (当用户被自动销毁时,所有链接都被删除,所以我认为共享应该也已经消失了,我必须尝试那样做)。当用户离开该组时,我会销毁他的会员记录,但他已经离开,但链接仍然存在。我显示共享链接,你可以踢用户(成员销毁)和组中的组成员列表显示顺便说一句。

我想到了一些事情。我写下我在控制台中所做的事情

g = Group.find(66)
u = g.users.find(1)
u.links

,它会给我组中用户的所有链接。在那旁边

g.grouplinks

会给我组中的所有共享链接。

g.grouplinks.map(&:link_id) returns [16, 17, 14, 13, 15]
u.links.map(&:id) returns [13, 15]

现在我该怎么办?我的用户正在离开小组。会员记录被销毁,我如何根据用户的链接销毁这些群组链接? 是否有一个我不知道的魔术?

感谢您的帮助。

编辑

class User < ApplicationRecord

    has_secure_password


  has_many :links, dependent: :destroy
  has_many :grouplinks, dependent: :destroy

  has_many :members, :dependent => :destroy
  has_many :groups, :through => :members
  has_one :owned_group, foreign_key: "owner_id", class_name: "Group"
end

class Member < ApplicationRecord

  belongs_to :user
  belongs_to :group

  validates :user_id, :presence => true
  validates :group_id, :presence => true
  validates :user_id, :uniqueness => {:scope => [:user_id, :group_id]}

end

class Link < ApplicationRecord

    has_many :grouplinks, :dependent => :destroy
    belongs_to :user

end

class Grouplink < ApplicationRecord

    belongs_to :group
    belongs_to :link

end

class Group < ApplicationRecord
has_secure_token :auth_token

    has_many :members, :dependent => :destroy
    has_many :users, through: :members, source: :user
    belongs_to :owner, class_name: "User"

    has_many :links, through: :grouplinks
    has_many :grouplinks, :dependent => :destroy

    def to_param
        auth_token
    end

end

我认为实际上我可以在grouplinks中添加user_id,因此我可以根据链接和groupslinks中的user_id删除all_all。不知道如何做到这一点&#39;并且不知道是否有更好的解决方案。

编辑2

我在模型中尝试了你的解决方案。实际上它很聪明,我没有想到...... 现在问题是我的grouplink的创建(共享链接)。我有这个:

  def create
    user = current_user if current_user
    group = user.groups.find_by(auth_token: params[:auth_token])
    share = group.id
    group_link = group.grouplinks.build(link_id: params[:link_id])
    gl = group.grouplinks
    if gl.where(group_id: share).where(link_id: params[:link_id]).exists?
        flash[:error] = "You shared this link in '#{group.name}' already."
        redirect_to mylinks_path
    else
        if group_link.save
          group_link.toggle!(:shared)
          flash[:success] = "You shared your link in '#{group.name}'."
          redirect_to mylinks_path
        else
          render 'new'
        end
    end
  end

这显然不再适用了,当我尝试分享链接时出现此错误:First argument in form cannot contain nil or be empty <%= form_for @grouplink do |f| %>

我试着改变它:

def create
    group = Group.find_by(auth_token: params[:auth_token])
    share = group.id
    group_link = group.grouplinks.build(link_id: params[:link_id])
    gl = group.grouplinks
    if gl.where(group_id: share).where(link_id: params[:link_id]).exists?
        flash[:error] = "You shared this link in '#{group.name}' already."
        redirect_to mylinks_path
    else
        if group_link.save
          group_link.toggle!(:shared)
          flash[:success] = "You shared your link in '#{group.name}'."
          redirect_to mylinks_path
        else
          render 'new'
        end
    end
  end

但它不起作用

4 个答案:

答案 0 :(得分:2)

怎么样:

class Member < ApplicationRecord

  belongs_to :user
  belongs_to :group
  has_many :group_links, dependent: :destroy

  validates :user_id, :presence => true
  validates :group_id, :presence => true
  validates :user_id, :uniqueness => {:scope => [:user_id, :group_id]}

end

class Grouplink < ApplicationRecord

  belongs_to :link
  belongs_to :member

end

现在,当Member记录被销毁时(即,user被踢出或离开group),任何links与{{1}共享(即,group)也被销毁。但是,如果group_links在另一个user中共享了link,则group将继续与其他link共享。

正如@Pablo在评论中所提到的,你可能也想这样做:

groups

允许您这样做:

class Group < ApplicationRecord
  has_secure_token :auth_token

  has_many :members, :dependent => :destroy
  has_many :grouplinks, through: :members
  has_many :users, through: :members, source: :user
  belongs_to :owner, class_name: "User"

  has_many :links, through: :grouplinks

  def to_param
      auth_token
  end

end

我也同意@ amr-el-bakry group.grouplinks 有点令人困惑。我建议使用Member,因为它很清楚它是GroupUserGroup之间的关联。

另外,我认为说User而不是GroupLink可能更常规一些。或者,如果您想坚持基于关联类的命名,可能Grouplink。如果您将MemberLink更改为Member,那么可能会GroupUser

我认为您的GroupUserLink代码应该类似于:

create

可能能够将其写成:

  def create
    if group
      if member
        if link
          unless group_link
            @group_link = member.group_links.build(link: link)
            if group_link.save
              group_link.toggle!(:shared)
              flash[:success] = "You shared your link in '#{group.name}'."
              redirect_to mylinks_path
            else
              render :new
            end
          else
            flash[:error] = "You shared this link in '#{group.name}' already."
        else
          flash[:error] = "That link does not exist."
          redirect_to somewhere #fix this
        end
      else
        flash[:error] = "You must be a member of this group to add a link."
        redirect_to somewhere #fix this
      end
    else
      flash[:error] = "There is no group with that token."
      redirect_to somewhere #fix this
    end
  end

private

  def group
    @group ||= Group.find_by(auth_token: params[:auth_token])
  end

  def member 
    @member ||= current_user.members.where(group: group)
  end

  def link
    @link ||= Link.find_by(id: params[:link_id])
  end

  def group_link
    @group_link ||= member.group_links.where(link: link)
  end

但是我不记得那些重定向会让你心痛。

答案 1 :(得分:1)

您正在寻找的是Group

在您的has_many :links, dependent :delete_all 模型中,您希望自己应该有一行:

SortedCollection = inputCollection.stream()
    .map(e -> {
        return new Element(e.id, e.color);
    }).collect(Collectors.toList());

这就是说,该组有许多链接,如果您销毁该组,则销毁所有相关链接。

答案 2 :(得分:1)

在您的Member模型中,您可以使用after_destroy回调在销毁会员记录后销毁该组中的所有用户链接:

class Member < ApplicationRecord
  after_destroy do |record|
    record.user.links.each { |link| link.grouplinks.where(group_id: record.group.id).destroy_all }
  end

  belongs_to :user
  belongs_to :group

  ...

end

此外,我建议您将Member更改为Membership以便更清楚。

答案 3 :(得分:0)

我认为最好的想法是group_links属于成员和链接(而不是组和链接)。并且成员(不是用户)具有许多group_links。当你破坏成员时,它会破坏group_links。

修改

这就是jvillian在我的回答中提出的,就在我做之前。所以我相信他的答案是正确的(我在评论中提出了一些小的改进,jvillian肯定会接受并补充: - )。

<强> EDIT2

关于在应用jvillian建议后遇到的问题,在创建新的grouplink时,必须从成员(不是组)完成。因此,在创建操作中,您必须搜索成员(通过user_id和group_id)并将grouplink创建为member.grouplinks.build