如何设置两个用户一起聊天

时间:2017-06-29 13:31:46

标签: ruby-on-rails ruby-on-rails-5

我希望如果用户订购了一顿饭,他可以与餐食供应商交谈......反之亦然...... 用户也可以提供膳食和订餐,例如在空中bnb,您可以是客人或主人(或两者)

Exemples:

  1. 假设我们有Bob(买家)从约翰(制造商)订餐,我希望约翰和鲍勃可以一起聊天
  2. 约翰(买家)从迈克(制造商)订餐,约翰和迈克可以一起聊天。
  3. 会话/ index.html.erb

    <% @users.each do |user| %>
      <%= link_to user.full_name , conversations_path(user_id: user), remote: true, method: :post %>
     <% end %>
    

    user.rb (我对此模型有疑问......)

      has_many :meals #Meals that the user offers
      has_many :received_orders, class_name: "Order" #The user receive an order
      has_many :placed_orders, through: :meals, class_name: "Order" #The user order a meal
      has_many :prepared_orders, through: :received_orders, class_name: "Meal", source: :meal #The user has prepared the order
    
      ####maybe this way below....TODO
      # has_many :meals
      # has_many :orders_as_a_customer, class_name: "Order"# same as: has_many :orders
      # has_many :orders_as_a_seller, through: :orders_as_a_customer, class_name: "Meal", source: :meal
      # has_many :orders, through: :meals
    

    order.rb

    class Order < ApplicationRecord
      before_save :calculate_price
      belongs_to :user
      belongs_to :meal
    
      has_many :notifications, as: :topic
    
      monetize :amount_cents, as: :amount
    
      def payment
        self.payment_status = true
        self.save
      end
    
      def calculate_price
        self.amount = (self.quantity * meal.price)
      end
    end
    

    我已按照此tutorial创建了我的聊天,我打赌可以调整到我的应用程序...

    conversation.rb

    class Conversation < ApplicationRecord
      has_many :messages, dependent: :destroy
    
      belongs_to :sender, foreign_key: :sender_id, class_name: "User"
      belongs_to :recipient, foreign_key: :recipient_id, class_name: "User"
    
      validates :sender_id, uniqueness: { scope: :recipient_id }
    
      scope :between, -> (sender_id, recipient_id) do
        where(sender_id: sender_id, recipient_id: recipient_id).or(
          where(sender_id: recipient_id, recipient_id: sender_id)
        )
      end
    
      def self.get(sender_id, recipient_id)
        conversation = between(sender_id, recipient_id).first
        return conversation if conversation.present?
    
        create(sender_id: sender_id, recipient_id: recipient_id)
      end
    
      def opposed_user(user)
        user == recipient ? sender : recipient
      end
    end
    

    conversations_controller.rb

    class ConversationsController < ApplicationController
    
      def create
        @conversation = Conversation.get(current_user.id, params[:user_id])
    
        add_to_conversations unless conversated?
    
        respond_to do |format|
          format.js
        end
      end
    
      def index
        session[:conversations] ||= []
        @users = User.all.where.not(id: current_user)
        @conversations = Conversation.includes(:recipient, :messages).find(session[:conversations])
      end
    
      def close
        @conversation = Conversation.find(params[:id])
    
        session[:conversations].delete(@conversation.id)
    
        respond_to do |format|
          format.js
        end
      end
    
      private
    
      def add_to_conversations
        session[:conversations] ||= []
        session[:conversations] << @conversation.id
      end
    
      def conversated?
        session[:conversations].include?(@conversation.id)
      end
    end
    

    我的实际 schema.rb

    ActiveRecord::Schema.define(version: 20170629192651) do
    
      # These are extensions that must be enabled in order to support this database
      enable_extension "plpgsql"
    
      create_table "attachinary_files", force: :cascade do |t|
        t.string   "attachinariable_type"
        t.integer  "attachinariable_id"
        t.string   "scope"
        t.string   "public_id"
        t.string   "version"
        t.integer  "width"
        t.integer  "height"
        t.string   "format"
        t.string   "resource_type"
        t.datetime "created_at"
        t.datetime "updated_at"
        t.index ["attachinariable_type", "attachinariable_id", "scope"], name: "by_scoped_parent", using: :btree
      end
    
      create_table "categories", force: :cascade do |t|
        t.string   "name"
        t.datetime "created_at", null: false
        t.datetime "updated_at", null: false
      end
    
      create_table "conversations", force: :cascade do |t|
        t.integer  "recipient_id"
        t.integer  "sender_id"
        t.datetime "created_at",   null: false
        t.datetime "updated_at",   null: false
        t.integer  "order_id"
        t.index ["order_id"], name: "index_conversations_on_order_id", using: :btree
        t.index ["recipient_id", "sender_id"], name: "index_conversations_on_recipient_id_and_sender_id", unique: true, using: :btree
      end
    
      create_table "ingredients", force: :cascade do |t|
        t.string   "name"
        t.integer  "meal_id"
        t.datetime "created_at", null: false
        t.datetime "updated_at", null: false
        t.index ["meal_id"], name: "index_ingredients_on_meal_id", using: :btree
      end
    
      create_table "meals", force: :cascade do |t|
        t.string   "menu_name"
        t.integer  "portion"
        t.date     "availability"
        t.datetime "created_at",   null: false
        t.datetime "updated_at",   null: false
        t.integer  "user_id"
        t.integer  "category_id"
        t.string   "images"
        t.string   "location"
        t.float    "latitude"
        t.float    "longitude"
        t.integer  "price"
        t.index ["user_id"], name: "index_meals_on_user_id", using: :btree
      end
    
      create_table "messages", force: :cascade do |t|
        t.text     "body"
        t.integer  "user_id"
        t.integer  "conversation_id"
        t.datetime "created_at",      null: false
        t.datetime "updated_at",      null: false
        t.index ["conversation_id"], name: "index_messages_on_conversation_id", using: :btree
        t.index ["user_id"], name: "index_messages_on_user_id", using: :btree
      end
    
      create_table "notifications", force: :cascade do |t|
        t.boolean  "read",       default: false
        t.string   "content"
        t.integer  "user_id"
        t.string   "topic_type"
        t.integer  "topic_id"
        t.datetime "created_at",                 null: false
        t.datetime "updated_at",                 null: false
        t.integer  "order_id"
        t.index ["order_id"], name: "index_notifications_on_order_id", using: :btree
        t.index ["topic_type", "topic_id"], name: "index_notifications_on_topic_type_and_topic_id", using: :btree
        t.index ["user_id"], name: "index_notifications_on_user_id", using: :btree
      end
    
      create_table "orders", force: :cascade do |t|
        t.text     "message"
        t.boolean  "payment_status", default: false
        t.integer  "quantity"
        t.integer  "user_id"
        t.integer  "meal_id"
        t.datetime "created_at",                     null: false
        t.datetime "updated_at",                     null: false
        t.integer  "amount_cents",   default: 0,     null: false
        t.json     "payment"
        t.index ["meal_id"], name: "index_orders_on_meal_id", using: :btree
        t.index ["user_id"], name: "index_orders_on_user_id", using: :btree
      end
    
      create_table "reviews", force: :cascade do |t|
        t.integer  "rating"
        t.text     "comment"
        t.integer  "meal_id"
        t.integer  "user_id"
        t.datetime "created_at", null: false
        t.datetime "updated_at", null: false
        t.index ["meal_id"], name: "index_reviews_on_meal_id", using: :btree
        t.index ["user_id"], name: "index_reviews_on_user_id", using: :btree
      end
    
      create_table "users", force: :cascade do |t|
        t.string   "email",                  default: "", null: false
        t.string   "encrypted_password",     default: "", null: false
        t.string   "reset_password_token"
        t.datetime "reset_password_sent_at"
        t.datetime "remember_created_at"
        t.integer  "sign_in_count",          default: 0,  null: false
        t.datetime "current_sign_in_at"
        t.datetime "last_sign_in_at"
        t.inet     "current_sign_in_ip"
        t.inet     "last_sign_in_ip"
        t.datetime "created_at",                          null: false
        t.datetime "updated_at",                          null: false
        t.string   "provider"
        t.string   "uid"
        t.string   "facebook_picture_url"
        t.string   "first_name"
        t.string   "last_name"
        t.string   "token"
        t.datetime "token_expiry"
        t.string   "nickname"
        t.string   "avatar"
        t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
        t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
      end
    
      add_foreign_key "conversations", "orders"
      add_foreign_key "meals", "users"
      add_foreign_key "messages", "conversations"
      add_foreign_key "messages", "users"
      add_foreign_key "notifications", "orders"
      add_foreign_key "notifications", "users"
      add_foreign_key "orders", "meals"
      add_foreign_key "orders", "users"
      add_foreign_key "reviews", "meals"
      add_foreign_key "reviews", "users"
    end
    

1 个答案:

答案 0 :(得分:0)

从评论中得出结论,您需要拥有不同的模型。以下是对我有用的内容:

class User < ApplicationRecord
  has_many :meals
  has_many :orders
  has_many :sent_messages, :class => 'ChatMessage', :foreign_key => 'sender_id'
  has_many :received_messages, :class => 'ChatMessage', :foreign_key => 'receiver_id'
end

class Meal < ApplicationRecord
  belongs_to :user
  belongs_to :order_item
end

class Order < ApplicationRecord
  belongs_to :user
  has_many :order_items
end

class OrderItem < ApplicationRecord
  belongs_to :order
  has_one :meal
end

class ChatMessage < ApplicationRecord
  belongs_to :sender, :class => 'User'
  belongs_to :receiver, :class => 'User'
end