Rails, How to determine if a Nested Record Set Exists
I have the following two models:
Project, has_many ProjectParticipants
ProjectParticipants, belongs_to Project
How can I request to determine given these 5 ProjectParticipants, do they belong to a Project?
Also, it should be strictly t开发者_如何学Chose 5, not more or less.
Any thoughts on how to elegantly solve for this type of count?
Assuming participants
contain the 5 participants you want to check.
participants.all? {|o| o.project }
This will return true of all participants have a project, otherwise false.
To return the project that was found you can do:
And to see if all participants have the same project:
first_participant = participants.shift
participants.all? {|o| o.project == first_participant.project} unless first_participant.nil?
The good thing about this method is that it short circuits if one of the participant's doesn't have the same project(more efficient).
Edit:
To return the project that they all share, you can do:
first_participant = participants.shift
project_shared = participants.all? {|o| o.project == first_participant.project} and first_particpant.project unless first_participant.nil?
project_shared will be set to the project that they are all share, otherwise it will be to nil/false.
So you can then do:
if project_shared
# do work
else
# they dont share a project!
end
You can compare the properties of the ProjectParticipant records in a group:
participants.length == 5 and participants.all? { |p| p.project_id == project.id }
This validates that your array of participants contains five entries and that all of them have the same project_id assigned. Comparing p.project == project
will have the side-effect of loading the same Project five times.
To check if they simply belong to a project, you can do this:
participants.length == 5 and participants.all? { |p| p.project_id? }
That project may be deleted and the reference could be invalid, so you may need to resort to actually fetching it:
participants.length == 5 and participants.all? { |p| p.project }
You can also use the group_by
method to see if there's only one project involved:
grouped = participants.group_by(&:project)
!grouped[nil] and grouped.length == 1 and grouped.first[1].length == 5
The group_by
method will organize the given array into a hash where the key is specified as a parameter and the value is a list of objects matching. It can be handy for situations like this.
精彩评论