Joe Marion
Joe Marion

Reputation: 406

Two separate has_many tables

I am having trouble pulling the data I need using two separate many to many associated tables.

   class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_many :meals
  has_many :lists
end

class Meal < ActiveRecord::Base
  belongs_to :user
  has_many :meal_lists
  has_many :lists, through: :meal_lists
  has_many :meal_ingredients
  has_many :ingredients, through: :meal_ingredients
end

class List < ActiveRecord::Base
  has_many :meal_lists
  has_many :meals, through: :meal_lists
  belongs_to :user
end

class MealList < ActiveRecord::Base
  belongs_to :meal
  belongs_to :list
end

My end result is to be able to pull out all the meals that are both associated with the list_id and the user_id.

So far I have tried

@list = @user.lists.create("name: "users list")
list.meals.create(name:"List name", user_id: user.id)
list.meals.where(user_id: user.id)

I can not seem to figure out how to pull out the meals that are both associated with the user_id and the list_id.

EDIT: After reading the first answer here is how I interpreted how to implement it. Keep in mind I am still at the beginning of learning rails and I've been staring at this problem for hours and the more I stare the more obscure it seems.

I created a method within the model:

Class List < ActiveRecord::Base

  def self.find_user_meals(user, list)
    meal = Meal.joins(:meal_lists)
    user_meal = meal.where(user: user)
    list_meal = user_meal.where(meal_lists: { list: list } )
    return list_meal.distinct
  end
end

and within my controller:

def edit
    @list = List.find(params[:id])
    user = current_user
    @meals = Meal.all
    @all_user_meals = List.find_user_meals(user, @list)
  end

And in the view I just iterate over @all_user_meals. I read a little bit into joins and includes after the first answer and seemed to get something to work somewhat within the console. This is not quite working in the app, and I am just trying to wrap my head around it a little bit better.

DOUBLE EDIT:

So I guess I was just tired and overthinking the problem. What I didn't realize was that the lists are created by one user so I was able to solve this fairly simply.

def edit
    @list = List.find(params[:id])
    user = current_user
    @meals = Meal.all.where(user_id: user.id)
    @listed_meals = @list.meals
  end

I can't believe how much time I spent on this. Thanks for spending the time looking at this. Sometimes associations confuse me, other times they seem straightforward.

Upvotes: 1

Views: 36

Answers (1)

Baldrick
Baldrick

Reputation: 24340

You can do it using a join between Meal and MealList

Meal.joins(:meal_lists)
    .where(user: @user)
    .where(meal_lists: { list: @list })
    .distinct  # because the joins may return duplicate meals if they belong to several lists

Upvotes: 2

Related Questions