← Back to Upcase

Help modifying the model relationships in my Rails application


(Jon Castillo) #1

What I’d like to be able to do is obtain the posts for a given Group. But I only want to be able to obtain the last post (most recent) for each user in that group.

For example, I want to be able to do something like: Group.find(6).recent_posts
and have it return an array that would equal

posts = [ ]
Group.find(6).users.each do |user| 
posts << user.posts.last 
end

Posted are the models in my app

class Group < ActiveRecord::Base
  attr_accessible :name, :share_link
  has_many :memberships
  has_many :users, :through => :memberships
  
  validates :name, presence: :true
end


class Membership < ActiveRecord::Base
  belongs_to :user
  belongs_to :group
  attr_accessible :group_id, :user_id, :admin
end


class Post < ActiveRecord::Base
  belongs_to :user
  attr_accessible :title, :url, :user_id
  
  validates :title, presence: :true
end


class User < ActiveRecord::Base
  attr_accessible :name, :provider, :uid
  has_many :memberships
  has_many :groups, :through => :memberships
  has_many :posts
end

(Jon Castillo) #2

I just realized that I don’t need to modify the relationships of my models. I just simply needed to add a method to the Group model.

class Group < ActiveRecord::Base
  attr_accessible :name, :share_link
  has_many :memberships
  has_many :users, :through => :memberships
  
  validates :name, presence: :true
  
  def recent_posts
    posts = []
    self.users.each do |user|
      if !user.posts.last.nil?
        posts << user.posts.last
      end
    end
  end
end

(Ben Orenstein) #3

Glad to see you figured out your issue. One thought: I might refactor the recent_posts method as so:

def recent_posts
  users.inject([]) do |posts, user|
    if user.posts.last
      posts << user.posts.last
    end
    posts
  end
end

My code is somewhat more dense than yours, but I think it’s slightly more idiomatic.

Even if you don’t like the inject, I’d definitely drop the unneeded self, and change if !foo.nil? to if foo every time.