Skip to content

User.feed enhancement suggestion (Chapter 14) #63

@slawagn

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

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