fantgeass
fantgeass

Reputation: 35

Several associations as one

How can I get the same result, but like posts method is a simple association?
I want to do this: "user.posts.active". Is the best solution to define :finder_sql ?

class User < ActiveRecord::Base
    has_many :created_posts, class_name: Post.name, foreign_key: :creator_id
    has_many :updated_posts, class_name: Post.name, foreign_key: :updater_id

    def posts
        (created_posts + updated_posts).flatten.uniq
    end
end

Upvotes: 1

Views: 63

Answers (1)

jefflunt
jefflunt

Reputation: 33954

Rather than load both sets of posts and then uniqing them in Ruby, you can make that a little more efficient by having SQL only give you the unique list.

class User < ActiveRecord::Base
  def posts
    Post.where(["creator_id = ? OR updater_id = ?", self.id, self.id])
  end

  ...
end

The reason this is more efficient is because it issues a single DB query with a single set of response rows, the duplicates are never returned to begin with, and ActiveRecord then only instantiates Ruby objects for that set of rows.

By way of comparison, the approach in your original question issues two DB queries, each of which creates an array of User objects, then combines those two arrays, then removes duplicates. The extra object initialization, then the combining of arrays, then the iterations over the combined array needed to remove duplicates - all combined together - is where the bulk of the overhead takes place.

As with all optimization of this sort, if you're dealing with a very small dataset the difference in performance is probably negligible, however the single query, single set of responses approach is just plain smart in this case.

On a side note...

With the relationships as defined, if two users update the same post, one after the other, won't only the most recent user have their id assigned to the updater_id? Is that what you intend?

Depending on the design of your app it may be better to record updates on their own, so that all users who have edited a given post will have that post in their list of updated_posts.

Upvotes: 3

Related Questions