Search code examples
ruby-on-rails-4activerecordresponders

Rails 4 respond_with include association with WHERE


I'm using rails respond_with to send a JSON response to the client, and I'm trying to figure out how to use the includes option in respond_with along with a where clause in my association

Here are my models:

class User < ActiveRecord::Base
   has_many :ratings
   has_many :movies, through: :ratings
end

class Rating < ActiveRecord::Base
   belongs_to :user
   belongs_to :movie
end

class Movie < ActiveRecord::Base
   has_many :ratings
   has_many :users, through: :ratings
end

In my controller action, I have:

def create
   movies = Movie.order("RANDOM()").limit(3)
   respond_with(movies, include: :ratings)
   // I'd like to do something like 
   // respond_with(movies, include: :ratings WHERE user: current_user)

end

However, this is responding with ALL the ratings for those three movies. I want to restrict it the ratings of just that particular user


Solution

  • You could do this:

    def create
      movies = Movie.order("RANDOM()").limit(3)
      # EDIT
      # movies = movies.merge(current_user.movies).includes(:ratings)
      movies = movies.joins(:ratings).merge(current_user.ratings).includes(:ratings)
      respond_with(movies)
    end
    

    Although that doesn't make much sense in a create action.

    NOTE

    The movies query above will generate the following SQL (2 commands; note that some of your fields will differ since I'm using bare versions of your models):

    SELECT DISTINCT "movies"."id" FROM "movies" 
    INNER JOIN "ratings" ON "ratings"."movie_id" = "movies"."id"
    WHERE "ratings"."user_id" = ?  ORDER BY RANDOM() LIMIT 3
    
    SELECT "movies"."id" AS t0_r0, "movies"."name" AS t0_r1, "movies"."created_at" AS t0_r2, 
    "movies"."updated_at" AS t0_r3, "ratings"."id" AS t1_r0, "ratings"."user_id" AS t1_r1, 
    "ratings"."movie_id" AS t1_r2, "ratings"."created_at" AS t1_r3, "ratings"."updated_at" AS t1_r4 
    FROM "movies" INNER JOIN "ratings" ON "ratings"."movie_id" = "movies"."id" 
    WHERE "ratings"."user_id" = ? AND "movies"."id" IN (1) ORDER BY RANDOM() [["user_id", 1]]