Skip to content

User.feed enhancement suggestion (Chapter 14) #63

Description

@slawagn

The User model has a feed method that is currently implemented the following way:

# Listing 14.47: The final implementation of the feed
  def feed
    following_ids = "SELECT followed_id FROM relationships
                     WHERE  follower_id = :user_id"
    Micropost.where("user_id IN (#{following_ids})
                     OR user_id = :user_id", user_id: id)
  end

# Listing 14.50: Using a join to make the feed.
  def feed
    part_of_feed = "relationships.follower_id = :id or microposts.user_id = :id"
    Micropost.joins(user: :followers).where(part_of_feed, { id: id })
  end

I think a slightly more elegant solution may be proposed here, for instance:

# User.rb
  def feed
    Micropost.appearing_in_feed_of(self)
  end

# Micropost.rb
  scope :appearing_in_feed_of, ->(user) do 
    where(    user_id: user.following.select(:id))
    .or(where user_id: user.id)
  end

The following SQL query is produced by the code above:

SELECT "microposts".* FROM "microposts"
WHERE (
  "microposts"."user_id" IN (
  	SELECT "users"."id" 
  	FROM "users" 
  	INNER JOIN "relationships" 
  	ON "users"."id" = "relationships"."followed_id"
  	WHERE "relationships"."follower_id" = ?
  )
  OR "microposts"."user_id" = ?
)
ORDER BY "microposts"."created_at" DESC

As you can see, just like the solution currently used, the one proposed here also produces a single SQL query with subquery, but:

  • does so in a more idiomatic way, that is, without using strings of plain SQL
  • illustrates how scopes can be used, aside from the default_scope that has been used earlier
  • illustrates the use of SQL operators like OR with ActiveRecord
  • does not explicitly use joins

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions