This project is archived and is in readonly mode.
Iterate over :has_many array with the join (:through) model
-
Michael Koziarski
- State changed from new to invalid
This should really just be:
user.memberships.each do |membership|
puts membership.status, membership.group.name
end
So I can't the need for this feature.
-
Daniel Lunde
What about the cases where you are sorting by groups
class User < ActiveRecord::Base has_many :memberships has_many :groups, :through => :memberships, :order => "groups.name" end user.groups.each_with_join do |group, membership| puts "#{group.name}, #{membership.status}" endBy only doing user.memberships, there's no knowledge of the groups to order it correctly.
There's other instances where it makes sense to iterate over the groups rather then the memberships.
-
Pratik
Why can't you just do the following ?
user = User.find(:first, :include => { :groups => :membership }) user.groups.each do |group| puts "#{group.name}, #{group.membership.status}" end -
Daniel Lunde
Pratik:
It seems like the obvious thing to do, but there's a problem with it. Let me give a more complete example.
>> pp frank.groups [#<Group id: 2, name: "Swim Team">] >> pp frank.memberships [#<Membership id: 4, user_id: 2, group_id: 2, status: "Starter">] >> pp john.groups [#<Group id: 2, name: "Swim Team">] >> pp john.memberships [#<Membership id: 6, user_id: 3, group_id: 2, status: "Finisher">] # Note, I'm using memberships instead of membership since the Group class declares "has_many :memberships" >> frank = User.find(2, :include => { :groups => :memberships }) >> frank.groups.each do |group| ?> pp group >> pp group.memberships >> end #<Group id: 2, name: "Swim Team"> [#<Membership id: 4, user_id: 2, group_id: 2, status: "Starter">, #<Membership id: 6, user_id: 3, group_id: 2, status: "Finisher">]So when iterating over frank's groups, it returned not only frank's membership, but all memberships from that group. Which is incorrect.
With my patch, you only get the correct membership record that matches both the user and the group, plus you get it as a record that's not wrapped in an array.
And in those instances where someone might have multiple memberships to a single group, it does give it back as an array of just those memberships.
-
Daniel Lunde
Here's a real world example where I've needed to use each_with_join:
class Feature < ActiveRecord::Base has_many :featured_items, :dependent => :destroy, :order => 'featured_items.position' has_many :featured_users, :source => :featureable, :through => :featured_items, :source_type => 'User', :order => 'featured_items.position' has_many :featured_media, :source => :featureable, :through => :featured_items, :source_type => 'Medium', :order => 'featured_items.position' end # in view <% feature = Feature.find_by_group("users", :include => :featured_users, :order => 'featured_items.position') %> <% feature.featured_users.each_with_join do |user, featured_item| %> <%= image_tag(featured_item.photo.public_filename) %><br/> <%= user.name %> <% end %>In this case I couldn't do:
feature.featured_items do |featured_item| featured_item.featured_user.name # featured_user is not a valid method endWouldn't you say that using each_with_join in this example would be easier then alternative methods?
-
Michael Koziarski
I certainly can see cases where this is required, but I'm just not convinced that it justifies a new method for us to have to maintain on an ongoing basis.
If there's a join model, it should be exposed.
