现在,我有一个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
这样做有更好的方法吗?
答案 0 :(得分:0)
您需要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