在我的应用程序中,用户可以创建计划。创建计划后,用户可以定义计划的利益相关者/团队成员。每个团队成员都成为一名负责人。有许多计划,用户可以成为多个计划的利益相关者,并且在每个计划中他们都有不同的责任。
示例
管理员创建计划并将10个用户指定为利益相关者。 1是问责,2是负责,7只需要通知
我在两个模型之间建立了一个has_many关系:
class User < ActiveRecord::Base
has_many :assignments
has_many :plans, through: :assignments
end
class Plan < ActiveRecord::Base
has_many :assignments
has_many :users, through: :assignments
end
分配表如下所示:
create_table :assignments do |t|
t.belongs_to :user
t.belongs_to :plan
t.string :responsibility
end
add_index :assignments, [:user_id, :plan_id]
列责任包含4个不同值中的一个(负责,负责,知情,咨询。)
我知道如何查询已分配给该计划的所有用户(@plan.users.to_a
),但我不知道如何能够额外补充用户信息以及他们在此计划中的责任。
我需要的查询是:
通过查看分配表来选择属于计划X的用户。不要只使用赋值表来标识用户,还要从赋值表中的责任列中获取值并返回包含的数组:
答案 0 :(得分:1)
我们有这个确切的要求,并以两种方式解决它:
<强> Use an SQL Alias Column 强>
第一种方法是使用SQL Alias Column&amp;将其附加到您的has_many
关联中,如下所示:
Class User < ActiveRecord::Base
has_many :assignments
has_many :plans, -> { select("#{User.table_name}.*, #{Plan.table_name}.responsibility AS responsibility") }, through: :assignments, dependent: :destroy
end
这将允许您拨打@user.plans.first.responsibility
,如果没有记录,将会正常失败
使用ActiveRecord Association Extensions
这是最好但更复杂的方式,因为它在内存中使用proxy_association
对象(而不是执行另一个DB请求)。这个剧本花了我们两个星期的时间来创作,所以我们为此感到非常自豪!未经Rails 4.1测试:
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :assignments
has_many :plans, through: :assignments, extend: Responsibility
end
#app/models/plan.rb
Class Plan < ActiveRecord::Base
attr_accessor :responsibility
end
#app/models/concerns/Responsibility.rb
module Responsibility
#Load
def load
captions.each do |caption|
proxy_association.target << responsibility
end
end
#Private
private
#Captions
def captions
return_array = []
through_collection.each_with_index do |through,i|
associate = through.send(reflection_name)
associate.assign_attributes({responsibility: items[i]}) if items[i].present?
return_array.concat Array.new(1).fill( associate )
end
return_array
end
#######################
# Variables #
#######################
#Association
def reflection_name
proxy_association.source_reflection.name
end
#Foreign Key
def through_source_key
proxy_association.reflection.source_reflection.foreign_key
end
#Primary Key
def through_primary_key
proxy_association.reflection.through_reflection.active_record_primary_key
end
#Through Name
def through_name
proxy_association.reflection.through_reflection.name
end
#Through
def through_collection
proxy_association.owner.send through_name
end
#Responsibilities
def items
through_collection.map(&:responsibility)
end
#Target
def target_collection
#load_target
proxy_association.target
end
end
答案 1 :(得分:0)
查询约会表,直接筛选当前计划中的所有用户:
Appointement.select(:id).where(user_id: Plan.find(params[:id]).users.pluck(:user_id), plan_id: params[:id]).group(:id).having('count(*) = ?', Plan.find(params[:id]).users.count)