如何简化我的活动记录代码(我想使用连接表列过滤has_many)?



这是我的schema

create_table "duties", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.boolean "is_general", default: false
t.boolean "write_all", default: true
end
create_table "duties_users", force: :cascade do |t|
t.bigint "duty_id"
t.bigint "user_id"
t.boolean "has_write_access", default: true
t.index ["duty_id"], name: "index_duties_users_on_duty_id"
t.index ["user_id"], name: "index_duties_users_on_user_id"
end

create_table "users", force: :cascade do |t|
t.string "mail"
t.text "password_digest"
t.datetime "birth_date"
t.boolean "is_admin", default: false
t.integer "rating", default: 0
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "name", default: ""
t.string "surname", default: ""
t.string "patronymic", default: ""
t.datetime "restore_date", default: "2021-02-11 09:57:14"
t.boolean "is_boss", default: false
end

我的连接模型

class DutyUser < ApplicationRecord
self.table_name = "duties_users"
belongs_to :user
belongs_to :duty
end

用户模型
class User < ApplicationRecord     
has_secure_password   
has_many :duties_users, class_name: "DutyUser"
has_many :duties, through: :duties_users, class_name: "Duty"
end

和责任模型

class Duty < ApplicationRecord
has_many :duties_users, class_name: "DutyUser"
has_many :users, through: :duties_users, class_name: "User"
end

我想找到所有对特定任务有写权限的用户。为了实现它,我需要使用这样的东西:

Duty.first.duties_users.find_all{|m| m.has_write_access}.map{|m| m.user}

如何简化这行代码?

这里的要点是:

  • Dutyhas_manyusers。所以如果你有duty,你也可以做duty.users这样你就能得到所谓的" ActiveRecord relationship "
  • 中的用户
  • ActiveRecord Relations的行为很像数组,除了它们只允许您访问一个模型的实例(在本例中是duty)。users将返回一个充满User实例的关系),它允许您运行进一步的查询,以及User上的任何类方法。请注意,与数组不同,关系实际上不包含任何内容。它悄悄地构建一些SQL,只有当你强迫它(例如通过迭代它与.each,或要求.count)发送SQL到数据库
  • 查询可以使用where方法完成-例如.where(has_write_access: true)-这是在数据库中完成的,所以它非常快。

最新更新