Rails:破坏多个用户到用户的关联

时间:2014-03-15 02:50:17

标签: ruby-on-rails ruby callback associations

我有一个名为Block的模型,其中包含blocker_id(user_id)和blocked_user_id字段(也是user_id)。 Block模型允许一个用户阻止另一个用户。当一个用户阻止另一个用户时,我希望它使用Relationship类的before_save方法销毁它们之间的BlockRelationship表格包含follower_idfollowed_id

这是事情变得棘手的地方。我知道我可以通过使用多个return if Relationship.xyz.nil?语句然后使用多个Relationship.find_by(follower_id: , followed_id: ).destroy语句来实现此目标,但这会变得复杂,因为每个blockerblocked_user都可以followerfollowed id,两者都有,或者两者都没有。有没有更简单的方法呢?

这是我的模型供参考:( Block课程也有一个blocked_post字段,我没有遇到任何问题)

class Block < ActiveRecord::Base

validates :blocker_id, presence: true
validates :blocked_user_id, uniqueness: {scope: :blocker_id}, allow_nil: true
validates :blocked_post_id, uniqueness: {scope: :blocker_id}, allow_nil: true 
validate  :blocked_user_or_post
after_validation :validate_block
before_save :destroy_blocked_relationships


belongs_to(
    :blocker,
    class_name: "User"
    )

has_one(
    :blocked_user,
    class_name: "User"
    )

has_one(
    :blocked_post,
    class_name: "Post"
    )

private

def blocked_user_or_post
  blocked_user_id.blank? ^ blocked_post_id.blank?
end


def validate_block
  if blocked_user_id.present?
    !(blocker_id == blocked_user_id)
  elsif blocked_post_id.present?
    blocked_post = Post.find_by(id: self.blocked_post_id).user_id
    !(blocker_id == blocked_post)
  else
    false
  end
end

def destroy_blocked_relationships
  #my over-complex code was here
end

end

relationship.rb:

class Relationship < ActiveRecord::Base


validates :follower_id, :followed_id, presence: {message: 'Need an eligible follower and followee id'}
validates :followed_id, uniqueness: { scope: :follower_id}


belongs_to(
   :follower, 
   class_name: "User"
   )

belongs_to(
   :followed, 
   class_name: "User"
   )
end

如果有任何方法可以做到这一点并不需要大量的代码,我真的很想知道。提前谢谢。

2 个答案:

答案 0 :(得分:0)

我不确定您的确切用例,但我对人们可以互相关注的系统的看法,似乎阻止者始终是被关注的人。如果是这种情况,那么这是一个实现:

def destroy_blocked_relationships
  Relationship.where(follower_id:blocked_user_id, followed_id:blocker_id).destroy_all
  true
end

如果阻止某人被人关注是有道理的,你可以加上:

Relationship.where(follower_id:blocker_id, followed_id:blocked_user_id).destory_all

这里一共都是,如果没有关系,就停止保存Block:

before_save :destroy_blocked_relationships

def destroy_blocked_relationships
  relationships = Relationship.where("(follower_id = ? AND followed_id = ?) OR (followed_id = ? AND follower_id = ? )", blocked_user_id, blocker_id, blocked_user_id, blocker_id)
  relationships.destroy_all
  relationships.present?  # Omit this line if the save should continue regardless
end

答案 1 :(得分:0)

这是我的理解:

  • a Block是两个用户之间的关系,或者是User和Post之间的关系
  • 当在用户A和帖子X之间创建一个块时,在用户A和用户B之间也会创建一个隐式块,其中用户B是帖子X的作者

考虑制作两个模型,BlockedPost和BlockedUser。然后,制作两个#make方法。这使得所有相关逻辑更容易推理。

# class BlockedPost
def make(user, post)
  transaction do
    create!(user: user, post: post)
    BlockedUser.make(user, post.author)
  end
end

# class BlockedUser
def make(user, blocked_user)
  transaction do
    create!(user: user, blocked_user: blocked_user)
    Relationship.where(follower: user, following: blocked_user).destroy_all
    Relationship.where(follower: blocked_user, following: user).destroy_all
  end
end