Rails 4关系状态方法,这是最优的吗?

时间:2021-03-22 05:05:13

I'm building a social site in Rails 4. Users can request to follow another user.

我正在Rails 4中创建一个社交站点。用户可以请求跟踪另一个用户。

In my user model I have the following method. It works but I'm wondering if it is the best way to do determine the relationship status. Will this scale okay?

在我的用户模型中,我有以下方法。它是有效的,但我想知道这是否是确定关系状态的最好方法。这个规模会更大?

Thanks.

谢谢。

def relationship_status(user_2)
  relationship = Relationship.where(follower_id: self.id, followed_id: user_2.id)
  unless relationship.any?
    relationship = Relationship.where(followed_id: self.id, follower_id: user_2.id)
    unless relationship.any?
      return "not_friends"
    else
      if relationship.first.status == "pending"
        return "pending_recieved"
      elsif  relationship.first.status == "ignored"
        return "you_ignored"
      elsif relationship.first.status == "active"
        return "your_followed"
      end
    end
  else
    if relationship.first.status == "pending"
      return "pending_sent"
    elsif relationship.first.status == "ignored"
      return "your_ignored"
    elsif relationship.first.status == "active"
      return "you_are_following"
    end
  end
end

2 个解决方案

#1


0  

I don't believe this will scale very well as you will have to check each relationship for each operation. The better approach would be to fan them out and scope them for faster queries

我不相信这将会很好,因为你将不得不检查每一个关系的每一个操作。更好的方法是将它们扇出,并使它们适用于更快的查询。

class User < ActiveRecord::Base
  has_many :user_relationships, dependent:destroy, inverse_of :user
  has_many :users, through: user_relationships
  has_many :affected_user_relationships, class_name: UserRelatonship, dependent:destroy, foreign_key :affected_id
  has_many :affected_users, through: user_relationships, source: :affected_user

  has_many :ignored_relationships, dependent:destroy, inverse_of :user
  has_many :ignored_users, through: ignored_relationships

  # etc... 
end

class UserRelationship
  belongs_to :user
  belongs_to :affected_user, class_name: User

  validates_presence_of :user, :affected_user
end

class IgnoredRelationship < UserRelationship
end

class FollowedRelationship < UserRelationship
end

Then you could do faster queries.

然后您可以执行更快的查询。

def ignored?(u)
  self.ignored_users.include?(u)
end

#2


0  

There's nothing glaringly bad here that will prevent you from scaling with respect to performance. The bigger scaling issue is your code's clarity, and how much you'll hate yourself when you need to make a change here 4 months from now, but can't remember what the hell you were trying to do here.

这里没有什么可怕的东西可以阻止你对性能的扩展。更大的问题是你的代码的清晰性,当你需要在4个月后做出改变的时候,你会多么憎恨自己,但却不记得你在这里到底想做什么。

First, you should probably extract the logic that determine the nature of relationship into methods on your Relationship class:

首先,你应该从关系类的方法中提取确定关系性质的逻辑:

class Relationship
  def following_status
    case status
    when 'pending'
     'pending_sent'
    when 'ignored'
     'your_ignored'
    when 'active'
     'you_are_following'
    end
  end

  def followed_status
    case status
    when 'pending_received'
     'pending_sent'
    when 'you_ignored'
     'your_ignored'
    when 'active'
     'you_followed'
    end
  end
end

Then we can clean up the relationship status method using more meaningful variable names:

然后我们可以使用更有意义的变量名来清理关系状态方法:

def relationship_status(other_user)
  if following = Relationship.where(follower_id: self.id, followed_id: other_user.id).first
   return following.following_status
  end
  if followed = Relationship.where(followed_id: self.id, follower_id: other_user.id).first
    return followed.followed_status
  end
  'not_friends'
end

Aside: Don't use unless and else together. That form reads rather poorly, and gets very dizzying, especially in nested statements.

旁白:除非和其他一起使用,否则不要使用。这个表单读起来相当糟糕,而且非常令人头晕,尤其是在嵌套语句中。

#1


0  

I don't believe this will scale very well as you will have to check each relationship for each operation. The better approach would be to fan them out and scope them for faster queries

我不相信这将会很好,因为你将不得不检查每一个关系的每一个操作。更好的方法是将它们扇出,并使它们适用于更快的查询。

class User < ActiveRecord::Base
  has_many :user_relationships, dependent:destroy, inverse_of :user
  has_many :users, through: user_relationships
  has_many :affected_user_relationships, class_name: UserRelatonship, dependent:destroy, foreign_key :affected_id
  has_many :affected_users, through: user_relationships, source: :affected_user

  has_many :ignored_relationships, dependent:destroy, inverse_of :user
  has_many :ignored_users, through: ignored_relationships

  # etc... 
end

class UserRelationship
  belongs_to :user
  belongs_to :affected_user, class_name: User

  validates_presence_of :user, :affected_user
end

class IgnoredRelationship < UserRelationship
end

class FollowedRelationship < UserRelationship
end

Then you could do faster queries.

然后您可以执行更快的查询。

def ignored?(u)
  self.ignored_users.include?(u)
end

#2


0  

There's nothing glaringly bad here that will prevent you from scaling with respect to performance. The bigger scaling issue is your code's clarity, and how much you'll hate yourself when you need to make a change here 4 months from now, but can't remember what the hell you were trying to do here.

这里没有什么可怕的东西可以阻止你对性能的扩展。更大的问题是你的代码的清晰性,当你需要在4个月后做出改变的时候,你会多么憎恨自己,但却不记得你在这里到底想做什么。

First, you should probably extract the logic that determine the nature of relationship into methods on your Relationship class:

首先,你应该从关系类的方法中提取确定关系性质的逻辑:

class Relationship
  def following_status
    case status
    when 'pending'
     'pending_sent'
    when 'ignored'
     'your_ignored'
    when 'active'
     'you_are_following'
    end
  end

  def followed_status
    case status
    when 'pending_received'
     'pending_sent'
    when 'you_ignored'
     'your_ignored'
    when 'active'
     'you_followed'
    end
  end
end

Then we can clean up the relationship status method using more meaningful variable names:

然后我们可以使用更有意义的变量名来清理关系状态方法:

def relationship_status(other_user)
  if following = Relationship.where(follower_id: self.id, followed_id: other_user.id).first
   return following.following_status
  end
  if followed = Relationship.where(followed_id: self.id, follower_id: other_user.id).first
    return followed.followed_status
  end
  'not_friends'
end

Aside: Don't use unless and else together. That form reads rather poorly, and gets very dizzying, especially in nested statements.

旁白:除非和其他一起使用,否则不要使用。这个表单读起来相当糟糕,而且非常令人头晕,尤其是在嵌套语句中。