rails model association problem - ruby-on-rails

im working on this model association class assignment. the basic association works, but im having issue with the "category"-page view.
Category Page Output should be (/categories/1)
Dish-ID
Dish-Title
Restaurant-Title <= HOW DO I GET THIS VALUE?
rules:
- dish belongs to one category
- same dish can be in multiple restaurants
class Category < ActiveRecord::Base
has_many :dishes
end
class Dish < ActiveRecord::Base
belongs_to :category
end
class Restaurant < ActiveRecord::Base
has_and_belongs_to_many :dishes
end
class DishRestaurant < ActiveRecord::Base
has_many :restaurants
has_many :dishes
end
Category Controller
def show
#category = Category.find(params[:id])
#dishes = #category.dishes
// RESTAURANT TITLE ??
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #category }
end
Category View:
<%= debug #dishes %>
any hint would be helpful.
thanks
pete

Define you models properly:
class Dish < ActiveRecord::Base
belongs_to :category
has_and_belongs_to_many :restaurants
end
class Restaurant < ActiveRecord::Base
has_and_belongs_to_many :dishes
end
This would use the implicit join table names "dishes_restaurants". You only need a join model is you store some join specific information, like price of the dish in the restaurant. In which case you models should be like:
class Dish < ActiveRecord::Base
belongs_to :category
has_many :dish_restaurants
has_many :restaurants, through => :dish_restaurants
end
class Restaurant < ActiveRecord::Base
has_many :dish_restaurants
has_many :dishes, through => :dish_restaurants
end
class DishRestaurant < ActiveRecord::Base
belongs_to :restaurant
belongs_to :dish
end
Whatever approach you follow, you can do dish.restaurants to retrieve the list of the restaurants which serve the dish.

Related

How to use foreign keys in Ruby on the Rails query?

I have three models; events, users and entries. I would like on my users page for to be able to retrieve information relating to the events associated with the event associated with the user.
def show
#user = User.find(params[:id])
#entry = #user.entries.paginate(page: params[:page])
end
It is more than happy with #user.entries.count but I would like to link up in a table something like this:
Event Name - Event Location - Course
My models are bellow:
class Event < ApplicationRecord
has_many :entries, dependent: :destroy
class User < ApplicationRecord
has_many :entries, dependent: :destroy
class Entry < ApplicationRecord
belongs_to :user
belongs_to :event
If they're related as:
class User < ApplicationRecord
has_many :events
end
class Event < ApplicationRecord
has_many :entries
belongs_to :user
end
class Entry < ApplicationRecord
belongs_to :event
end
Then you can use joins starting from Entry, up to User and check events where the user id is the one what you need:
Entry.joins(event: :user).where(users: { id: user_id })

How to apply association rules

I'm confusing about association.
I tried to write code below but rails was returned me "undefined method `subs'".
def show
#product = Product.find(params[:id])
#materials = #product.materials.subs
respond_to do |format|
format.json { render json: [ #product,#materials ]}
end
end
I want Product model relates to Sub model and I get Sub model record.
If someone knows about this problem to solve please tell me.
class Product < ActiveRecord::Base
has_many :product_materials
has_many :materials, :through => :product_materials
end
class ProductMaterial < ActiveRecord::Base
belongs_to :product
belongs_to :material
end
class Material < ActiveRecord::Base
has_many :product_materials
has_many :products, :through => :product_materials
has_many :material_subs
has_many :subs, :through => :material_subs
end
class MaterialSub < ActiveRecord::Base
belongs_to :material
belongs_to :sub
end
class Sub < ActiveRecord::Base
has_many :material_subs
has_many :materials, :through => :material_subs
end
#product.materials is an array and you cannot chain a association on an array
#product = Product.includes(materials: :subs).find(params[:id])
#materials = #product.materials.flat_map(&:subs)
this will loop over the materials and will return subs for each material

Unable to nest JSON Rails

I'm having trouble nesting my objects that have a has_many through relationships via rails.
My models look like this:
class SessionDetail < ActiveRecord::Base
has_many :session_enrollments, dependent: :destroy
has_many :customers, through: :session_enrollments
end
class SessionEnrollment < ActiveRecord::Base
belongs_to :customers //column name is "customers_id"
belongs_to :session_details //column name is "sessiondetails_id"
end
class Customer < ActiveRecord::Base
has_many :session_enrollments
has_many :session_details, through: :session_enrollments
end
I'm trying to nest a json object to return an array of session details, with a sub array of customers and a subarray (one object) of session_enrollments
My controller current looks like this:
def return_trainers_sessions
#trainer_requests = SessionDetail.where(trainers_id: params[:trainers_id], state: "PENDING")
unless (!#trainer_requests.any?)
respond_to do |format|
msg = {:status => "SUCCESS", :messages => "Requests Found", :requests => #trainer_requests.as_json(:includes => {:customers => {:include =>:session_enrollments}})}
format.json { render :json => msg } # don't do msg.to_json
end
I've also tried making a class method, but am only able to get as far as nesting the customers.
I end up returning no customers or session_enrollments, so my json just looks like I never added the includes to the right hand of .as_json
Watch your pluralization.
class SessionDetail < ActiveRecord::Base
has_many :session_enrollments, dependent: :destroy
has_many :customers, through: :session_enrollments
end
# a session enrollment belongs to a single customer, and a single session detail. Similarly
# the foreign key fields should be singular, customer_id, session_detail_id
class SessionEnrollment < ActiveRecord::Base
belongs_to :customer
belongs_to :session_detail
end
class Customer < ActiveRecord::Base
has_many :session_enrollments
has_many :session_details, through: :session_enrollments
end

Rails: Querying through 2 join table associations

I have a quite complicated relation between models and are now frustrated by a SQL Query to retrieve some objects.
given a Product model connected to a category model via a has_many :through association and a joint table categorization.
Also a User model connected to this category model via a has_many :through association and a joint table *category_friendship*.
I am now facing the problem to retrieve all products, which are within the categories of the array user.category_ids. However, I can't just not manage to write the WHERE statement properly.
I tried this:
u = User.first
uc = u.category_ids
Product.where("category_id IN (?)", uc)
However this won't work, as it doesn't have a category_id in the product table directly. But how can I change this to use the joint table categorizations?
I'm giving you the model details, maybe you find it helpful for answering my question:
Product.rb
class Product < ActiveRecord::Base
belongs_to :category
def self.from_users_or_categories_followed_by(user)
cf = user.category_ids
uf = user.friend_ids
where("user_id IN (?)", uf) # Products out of friend_ids (uf) works fine, but how to extend to categories (cf) with an OR clause?
end
Category.rb
class Category < ActiveRecord::Base
has_many :categorizations
has_many :products, through: :categorizations
has_many :category_friendships
has_many :users, through: :category_friendships
Categorization.rb
class Categorization < ActiveRecord::Base
belongs_to :category
belongs_to :product
Category_friendship.rb
class CategoryFriendship < ActiveRecord::Base
belongs_to :user
belongs_to :category
User.rb
class User < ActiveRecord::Base
has_many :category_friendships
has_many :categories, through: :category_friendships
def feed
Product.from_users_or_categories_followed_by(self) #this should aggregate the Products
end
If you need more details to answer, please feel free to ask!
Looking at the associations you have defined and simplifying things. Doing a bit refactoring in what we have to achieve.
Product.rb
class Product < ActiveRecord::Base
belongs_to :category
end
User.rb
class User < ActiveRecord::Base
has_many :categories, through: :category_friendships
scope :all_data , includes(:categories => [:products])
def get_categories
categories
end
def feed
all_products = Array.new
get_categories.collect {|category| category.get_products }.uniq
end
end
Category.rb
class Category < ActiveRecord::Base
has_many :users, through: :category_friendships
has_many :products
def get_products
products
end
end
NO NEED OF CREATING CATEGORY_FRIENDSHIP MODEL ONLY A JOIN TABLE IS NEEDED WITH NAME CATEGORIES_FRIENSHIPS WHICH WILL JUST HAVE USER_ID AND CATEGORY_ID
USAGE: UPDATED
Controller
class UserController < ApplicationController
def index
#all_user_data = User.all_data
end
end
view index.html.erb
<% for user in #all_user_data %>
<% for products in user.feed %>
<% for product in products %>
<%= product.name %>
end
end
end
I've upvoted Ankits answer but I realized there is a more elegant way of handeling this:
given:
u = User.first
uc = u.category_ids
then I can retrieve the products out of the categories by using:
products = Product.joins(:categories).where('category_id IN (?)', uc)

rails3 nested includes?

Is there a proper way to write this, or am I approaching this wrong? I need to do a nested include. I found This Link but it doesn't seem to work.
def show
#showring = Ring.includes(:stones => :upcharges, :variations).find(params[:id])
end
I have 3 tables...
Rings which has_many stones
Stones which has_many upcharges
Models:
class Ring < ActiveRecord::Base
has_many :stones
end
class Stone < ActiveRecord::Base
has_many :upcharges
belongs_to :ring
end
class Upcharge < ActiveRecord::Base
belongs_to :stone
end
def show
#showring = Ring.includes([{:stones => :upcharges}, :variations]).find(params[:id])
end
Added some brackets :)
Getting all upcharges :
#showring.stones.each do |s|
s.upcharges #Do whatever you need with it
end
Option 2 : Declare a has_many :through
class Ring < ActiveRecord::Base
has_many :stones
has_many :upcharges, :through => :stones
end
Then in the view :
<%= #showring.upcharges.to_json.html_safe %>

Resources