从 HMT 连接表中获取属性的最有效方法是啥?
Posted
技术标签:
【中文标题】从 HMT 连接表中获取属性的最有效方法是啥?【英文标题】:What's the most efficient way to get an attribute from a HMT join table?从 HMT 连接表中获取属性的最有效方法是什么? 【发布时间】:2015-12-17 01:54:23 【问题描述】:现在我有一个Artist
模型设置作为自加入,其中艺术家可以属于group
和一个组,members
(即艺术家)。我还有一个建立这些成员资格的连接表。在连接表中有一个枚举属性status
,用于确定艺术家是否是活跃成员。
在 Rails 控制台中进行试验时,我设法通过以下操作检索了艺术家的会员状态:
Artist.first.memberships.find_by(group: 3).status
=> "active"
我想把它作为艺术家的实例方法引入我的项目,但我觉得这个查找链可以改进。
class Artist < ActiveRecord::Base
has_many :group_memberships, class_name: "Membership", foreign_key: :group_id
has_many :members, through: :group_memberships
has_many :memberships, foreign_key: :artist_id
has_many :groups, through: :memberships
end
class Membership < ActiveRecord::Base
enum status: [:active, :inactive]
belongs_to :member, class_name: "Artist", foreign_key: :artist_id
belongs_to :group, class_name: "Artist"
end
我在想我的观点是列举每个小组成员并显示他们的状态:
<% @artist.members.each do |member| %>
<%= member.group_status(@artist) %>
<% end %>
这就是实例方法的编写方式:
def group_status(group)
memberships.find_by(group: group).status
end
还有更好的方法吗?
【问题讨论】:
您有什么理由没有为Group
提供单独的模型吗?试图想象艺术家如何与实际上与艺术家占据同一张桌子的所谓“组”建立多对多关系,这让我的大脑融化!
将这些放在一起时,我发现艺术家和团体具有几乎完全相同的属性。考虑到这一点,我得出结论,对于我希望使用的每个视图,拥有两个单独的控制器或枚举两个实例变量会很麻烦。你有什么建议吗?
每个属性是什么?
不仅是属性(名称、来源等),还有其他关联(专辑、流派、标签)。
【参考方案1】:
你需要ActiveRecord Association Extensions:
#app/models/artist.rb
class Artist < ActiveRecord::Base
has_many :memberships do
def status_by_group group
select(:status).find_by(group_id: group)
end
end
has_many :groups, through: :memberships
end
这样,你就可以做到:
@artist = Artist.find params[:id]
@artist.memberships.status_by_group(2) #-> should return object with status of Membership
有更好的方法。
如果您想将 status
属性附加到您的 group
对象:
@artist.groups.find(1).status
...您可以使用 ActiveRecord 关联扩展功能,但这次是使用 proxy_association
对象。
我之前做过并创建了以下代码:
#app/models/artist.rb
has_many :memberships
has_many :groups, through: :memberships, extend: GroupStatus
#app/models/concerns/group_status.rb
module GroupStatus
#Load
def load
statuses.each do |status|
proxy_association.target << status
end
end
private
#Status
def statuses
return_array = []
through_collection.each_with_index do |through,i|
associate = through.send(reflection_name)
associate.assign_attributes(status: items[i])
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
#Statuses
def items
through_collection.map(&:status)
end
#Target
def target_collection
proxy_association.target
end
end
【讨论】:
以上是关于从 HMT 连接表中获取属性的最有效方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
使用 AnyDAC (FireDAC) 从 SQLite 表中读取切片数据 (MBTiles) 的最有效方法是啥?
从sql列中拆分数据并将其保存在sql存储过程中的另一个表中的最有效方法是啥[重复]