Ruby on rails - Postgres schema for Users & Approvaling Users for a Dating style app



用户查看其他用户的个人资料,并标记approvereject、ala Tinder或类似的约会应用程序。

我正在用ActiveRecord&后端的PostgreSQL。

我正在考虑有一个User模型,然后是一个有user_idapproved_idApproval模型。

批准:

  create_table "approvals", force: :cascade do |t|
    t.integer  "user_id"
    t.integer  "approved_id"
    t.datetime "created_at",         null: false
    t.datetime "updated_at",         null: false
    t.datetime "user1_approval"
    t.datetime "user2_approval"
    t.datetime "denied_at"
  end

class User
  has_many :approvals
  has_many :approved, through: :approvals
  has_many :inverse_users, class_name: "Approval", foreign_key: "approved_id"
  has_many :inverse_approvals, through: :inverse_users, source: :user
class Approval
    def self.user_approval(user1, user2)
        sorted = [user1, user2].sort_by { |u| u.name}
        Approval.find_or_create_by(user: sorted[0], approved: sorted[1])
    end

这样做的优点是限制了Approval对象的数量——每对User对象只有1个。然而,我不确定如何使用此模式有效地进行查询。

例如,当查找approvereject动作时,我必须手动检查提交的user_id是否与user_idapproved_id匹配,以适当地设置user1_approvaluser2_approval

我正在考虑通过一个简单的过滤器(年龄范围在10年内(查找User

因此在User中我有:

def self.eligible(user) 
    users = User.where('age >= ? AND age <= ? AND id != ?', user.lowest_eligible_age,user.maximum_eligible_age, user.id).limit(20)
    approvals = []
    users.each do |u|
      approvals.push(Approval.user_approval(user, u ))
    end
    approvals.reject! { |a| a.denied_at}
    approvals
  end

这对于获得合格用户的入围名单非常有用。它还具有允许CCD_ 18&/approvals/:id/reject

我想知道使用像/users/:id/approve这样的API,然后让该操作相应地生成Approval是否更有意义。每个Approval对象将具有user_idrelated_approval_id,因此它可以链接到相互的Approval(其中目标用户与链接的批准的user_id相同(。

  create_table "approvals", force: :cascade do |t|
    t.integer  "user_id"
    t.integer  "approved_id"
    t.integer  "related_approval_id"

这样做会在数据库中产生更多的行。

我希望这是有道理的。我正在寻找一个好的架构解决方案,以用户批准&相互拒绝,这允许我进行良好的查询,比如只显示CCD_ 28尚未批准和尚未拒绝current_user的CCD_。

因为用户可以被Tinder"批准"或"拒绝",所以将此模型称为Decision更有意义。以下是我对这件事的看法。

用户模型

create_table "users", force: :cascade do |t|
  t.integer  "id"
  t.datetime "created_at",         null: false
  t.datetime "updated_at",         null: false
  t.integer  "age"
  ...etc...
end  

用户模型代表应用程序的任何用户,他们将对另一个用户做出决定或另一用户将对其做出决定。

决策模型

create_table "decision", force: :cascade do |t|
  t.integer  "id"
  t.datetime "created_at",         null: false
  t.datetime "updated_at",         null: false
  t.integer  "decision_maker_id"
  t.integer  "decision_receiver_id"
  t.boolean  "approved"  
  t.boolean  "active"
  ...etc...
end  

决策表示用户之间的任何交互。向右滑动用户是一个决定。另一个决定是对方用户向右滑动。这不是作为一个整体对象来表示的,而是作为两个独立的"决策"交互来表示的。

让我解释一下Decision中的字段是什么意思:

  • decision_maker_id-进行刷单的用户的id
  • decision_rereceiver_id-接收刷单的用户的id
  • approved-一个布尔值,如果向右滑动则为true,如果向左滑动则为false
  • active-一个布尔值,用于确定此决策是否已做出回复决策

Decision模型中,您需要一个before_save回调来检查正在保存的决策是否已经有对应的回复决策。如果是这样,那么你会想让这个决定不再有效,这样它就不会再出现在提要上了。然后,你可以在应用程序中通知用户他们同意/不同意,或者你想做的任何事情。

before_save: check_for_existing_reply
def check_for_existing_reply
  # if there is a decision object with this decision_maker_id and this 
  # decision_receiver_id but in opposite fields then you know there is a reply 
  # and you can take some action here
end  

用户模型中,您可以编写方法来查找所有存在的活动批准/拒绝。

scope :decisions, -> (id, approval_type) { where('decision_receiver_id = ? AND approved = ? AND active = true', approval_type) }  

通过使用User.decisions(user_id, true)调用该作用域,您可以获得用户的所有批准。通过用user.decisions(user_id, false)调用该作用域,您可以获得用户的所有拒绝。

您也可以将其分解为两个独立的范围,一个用于批准,另一个用于拒绝。

scope :approvals, -> (id) { where('decision_receiver_id = ? AND approved = ? AND active = true', true) } 
scope :rejections, -> (id) { where('decision_receiver_id = ? AND approved = ? AND active = true', false) }  

最后,您可以将其作为在User实例上调用的方法,这样您就不必传入id参数。

# where decision = true would mean approvals and decision = false would mean rejections  
def get_decisions(decision)  
   return User.where('decision_receiver_id = self.id AND approved = decision AND active = true') }  
end

您可以在像user.get_decisions(true)这样的User实例上调用它。

最新更新