Postgres schema for users and approved users for a dating style app

Users see profiles of other users and tag approve

or reject

, ala Tinder or similar dating apps.

I am creating a Rails server with ActiveRecord and PostgreSQL on the server.

I look at a model User

, then a model Approval

that has user_id

and approved_id

.

statement:

  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

      

This has the advantage of limiting the number of objects Approval

- there User

will be only 1 for each pair of s. However, I'm not sure how to efficiently query this schema.

When looking for actions approve

or reject

, for example, I need to manually check if the submitter matches user_id

user_id

or approved_id

user1_approval

or user2_approval

.

I am considering searching User

with a simple filter (age range for 10 years)

so in User

me:

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

      

Which is great for getting a list of your favorites. It also has the advantage of allowing api /approvals/:id/approve

and /approvals/:id/reject

.

I am wondering if it makes sense to use an API for example /users/:id/approve

and then this action generates Approval

accordingly. Each object Approval

has user_id

as well related_approval_id

, so it can refer to a reciprocal Approval

(where the target user matches the associated assertion user_id

).

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

      

This makes a lot more rows in the database.

Hope this makes sense. I am looking for a good architectural solution for users who approve and reject each other, which allows me to make good requests, for example, only show User

which have current_user

not been approved and which have not been rejected by current_user.

+3


source to share


1 answer


Since a user can be “approved” or “rejected” by ala Tinder, it makes sense to call this model “Solution”. This is how I see it going.

User model

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  

      

The user model represents any user of the application who decides that another user or another user will make a decision.

Decision making model

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  

      

A solution is any interaction between users. One click of the right mouse button on the user. Another solution is to retaliate directly in front of another user. It is not presented as one coherent entity, but as two separate interaction "solutions".

Let me explain what the fields in the Solution mean:

  • decision_maker_id - ID of the user who is scrolling
  • decision_receiver_id - ID of the user who receives the swip
  • approved - a boolean value that would be true if the napkin was valid and false if the napkin was abandoned.
  • active - a boolean value that determines if this decision was still making the answer

In the Decision Model, you will need a before_save callback that will check if the decision to be saved has an already made decision for the responder. If this happens, you want the solution to stop being active so that it no longer appears in the feed. You can then notify users with whom they agree / disagree, or what you want to do at this point in your application.



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  

      

In the user model, you can write methods that will find all active permissions / denials that exist.

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

      

By calling this area with User.decisions(user_id, true)

, you can get all the approvals for the user. By calling this area with user.decisions(user_id, false)

, you can get all the deviations for the user.

You can also break this down into two separate areas, one for assertions and one for rejections.

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) }  

      

Finally, you can do this with a method that is called on the User instance, so you don't need to pass the id parameter.

# 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

      

And you can call this on a user instance for example user.get_decisions(true)

.

+3


source







All Articles