ruby-on-rails - 在 Rails 上创建用户组
问题描述
我正在创建一个 Rails 应用程序,用户可以在其中创建组、添加联系人、将联系人添加到该组,然后将信息广播给用户到他们创建的组。
我正处于第三阶段,现在我正在尝试允许登录用户将联系人添加到组中。
对于多对多关系,我有三个模型:
class UserGroups < ApplicationRecord
belongs_to :user
belongs_to :group
end
class Group < ApplicationRecord
belongs_to :user
has_many: :user_groups
has_many: :users, through: :user_groups
validates :title, presence: true
end
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_one_attached :avatar
has_many :groups, dependent: :destroy
has_many :posts, dependent: :destroy
has_many :user_groups
has_many :users, through: :user_groups
before_create :set_circleid
has_many :contactships, dependent: :destroy
has_many :contacts, -> { where contactships: { status: :accepted }}, through: :contactships
has_many :requested_contacts, -> { where contactships: { status: :requested }}, through: :contactships, source: :contact
has_many :pending_contacts, -> { where contactships: { status: :pending }}, through: :contactships, source: :contact
has_many :blocked_contacts, -> { where contactships: { status: :blocked }}, through: :contactships, source: :contact
has_many :contactships_inverse, class_name: 'Contactship', foreign_key: :contact_id
has_many :contacts_inverse, through: :contactships_inverse, source: :user
def all_contacts
contacts + contacts_inverse
end
def has_contactship?(contact)
#return true if the user is a contact
return true if self == contact
contactships.map(&:contact_id).include?(contact.id)
end
def requested_contacts_with?(contact)
return false if self == contact
#we are going to map requested contacts with list of users to see if they include contact_id
requested_contacts.map(&:id).include?(contact.id)
end
def pending_contacts_with?(contact)
return false if self == contact
pending_contacts.map(&:id).include?(contact.id)
end
def contacts_with?(contact)
return false if self == contact
contacts.map(&:id).include?(contact.id)
end
def contact_request(contact)
#unless the contact is not equal to self and contactship does not already exist
unless self == contact || Contactship.where(user: self, contact: contact).exists?
#transaction means that if one fails they both are rolled back
transaction do
#for user to another user (sent request)
Contactship.create(user: self, contact: contact, status: :pending)
#from another user to user (recieve request)
Contactship.create(user: contact, contact: self, status: :requested)
end
end
def accept_request(contact)
transaction do
Contactship.find_by(user: self, contact: contact, status: [:requested])&.accepted!
Contactship.find_by(user: contact, contact: self, status: [:pending])&.accepted!
end
end
def reject_request(contact)
transaction do
Contactship.find_by(user: self, contact: contact)&.destroy!
Contactship.find_by(user: contact, contact: self)&.destroy!
end
end
end
还有我的组控制器中的一个方法(不知道在这里做什么):
#for adding a user to a group?
def add_user
#search for the group?
@group = Group.find(params[:id])
#add a user to that group via user_groups? How?
end
架构.rb:
ActiveRecord::Schema.define(version: 2020_06_22_142356) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "blob_id", null: false
t.datetime "created_at", null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end
create_table "active_storage_blobs", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
t.text "metadata"
t.bigint "byte_size", null: false
t.string "checksum", null: false
t.datetime "created_at", null: false
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end
create_table "groups", force: :cascade do |t|
t.string "title"
t.bigint "user_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["user_id"], name: "index_groups_on_user_id"
end
create_table "contactships", force: :cascade do |t|
t.bigint "user_id"
t.bigint "contact_id"
t.integer "status", limit: 2, default: 0
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["contact_id"], name: "index_contactships_on_contact_id"
t.index ["user_id"], name: "index_contactships_on_user_id"
end
create_table "posts", force: :cascade do |t|
t.string "description"
t.integer "user_id"
t.string "thought"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "user_groups", force: :cascade do |t|
t.bigint "user_id", null: false
t.bigint "group_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["group_id"], name: "index_user_groups_on_group_id"
t.index ["user_id"], name: "index_user_groups_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "first_name"
t.string "last_name"
t.string "groupid"
t.text "bio"
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", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "groups", "users"
add_foreign_key "comments", "users"
add_foreign_key "user_groups", "groups"
add_foreign_key "user_groups", "users"
end
我将如何开发该方法以便可以成功地将联系人添加到控制台中的组?我对实现这一点的方法特别感到困惑,特别是因为联系人不是他们自己的模型,而是用户模型的一部分。
谢谢!
解决方案
你可以做
group = Group.find(params[:id])
contact = User.find(params[:user_id])
UserGroups.create(user: contact, group: group)
命名
您已经在问题中提到了该术语contacts
,也许可以考虑这样命名您的协会。class_name
如果模型类的名称与关联名称不匹配,您可以指定一个属性让 Rails 知道它的名称。
belongs_to :owner, class_name: "User"
has_many: :user_groups
has_many: :contacts, through: :user_groups, class_name: "User"
validates :title, presence: true
https://guides.rubyonrails.org/association_basics.html#options-for-belongs-to
has_many 通过 vs. has_and_belongs_to
您还应该考虑是否真的需要UserGroups
模型或使用has_and_belongs_to
关联,请参阅 Rails 指南
最简单的经验法则是,如果您需要将关系模型作为独立实体使用,则应该设置一个 has_many :through 关系。如果您不需要对关系模型做任何事情,那么设置 has_and_belongs_to_many 关系可能会更简单(尽管您需要记住在数据库中创建连接表)。
推荐阅读
- docker - 在 Docker 安装和卸载后让 Vagrant Homstead 恢复生机
- alarmmanager - 公共类 AlarmManager 时间间隔执行少于 15 分钟(例如 2 分钟、5 分钟、7 分钟或 10 分钟)
- mysql - 根据数据组合两个具有不同日期值的表
- apache-flink - 得到“pyflink.util.exceptions.TableException:findAndCreateTableSource 失败。” 运行 PyFlink 示例时
- javascript - 如何修复“TypeError:req.next 不是函数”错误?
- profiling - Datadog 是否有能力从分析中排除某些网站?
- laravel - Laravel 通知上的 Laravel 5.5 批量分配异常错误 ID
- javascript - Javascript - 为 DOM 创建的元素创建切换功能
- php - Laravel 表单链接到错误的控制器功能
- javascript - 在 Chartjs 中动态更新数据