从 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存储过程中的另一个表中的最有效方法是啥[重复]

从一维 numpy 数组中获取这种矩阵的最有效方法是啥?

从 JavaScript 中的关联数组中获取第一项的最有效方法是啥?

检查表中是不是存在行的最有效方法是啥?