Rails Nested Json (Jbuilder) - ruby-on-rails

I have these models:
- Category
- SubCategory
- SubSubCategory
I'm sending a category_list.json.jbuilder with the tree and have categories-->subcategories-->subsubcategories.
Thing is that the "subsubcategy" is showing inside the "subcategory" even if don't has. For example:
I just have one "subsubcategory1" that belongs to "subcatgory1" but appears in "subcategory1" are showing "subsubcategory1, subsubcategor2, etc".
Category model:
has_many :sub_categories
has_many :sub_sub_categories
SubCategory model.
belongs_to :category
belongs_to :sub_category
belongs_to :category
has_many :sub_sub_category, through: :categories
SubSubCategory model:
This in my code:
json.categories #categories do |category|
json.name category.name
json.description category.description
json.category_id category.id
json.sub_categories category.sub_categories do |subcategory|
json.name subcategory.name
json.description subcategory.description
json.sub_category_id subcategory.id
json.sub_sub_categories category.sub_sub_categories do |subsubcategory|
json.name subsubcategory.name
json.description subsubcategory.description
json.sub_sub_category_id subsubcategory.id
end
end
end

I just have one "subsubcategory1" that belongs to "subcatgory1" but appears in "subcategory1" are showing "subsubcategory1, subsubcategor2, etc".
According to your model relations code, your SubSubCategories belong to Categories, and not SubCategories. So, it means that if a category has a subsubcategory, all categories within that category will have that subsubcategory.
I think you want something like this:
class Category < ActiveRecord::Base
has_many :sub_categories
has_many :sub_sub_categories, through: :sub_categories
end
class SubCategory < ActiveRecord::Base
belongs_to :category
has_many :sub_sub_categories
end
class SubSubCategory < ActiveRecord::Base
belongs_to :sub_category
end

Related

Get objects from a has_many association through a self_join association in Rails 5.1

I have two models, product and variation. The product model has a has_many relationship with the variation model. I also have a match model that has a self join relationship with the product model.
What I am trying to do is get an object from the variation model that has a relationship with a matched product.
product.rb
class Product < ApplicationRecord
...
has_many :variations, -> { order(:order) }, dependent: :destroy
has_and_belongs_to_many :categories
has_and_belongs_to_many :tags
has_many :matches
has_many :matched_products, through: :matches
...
end
variation.rb
class Variation < ApplicationRecord
...
VARIATION_ORDER = %w[1 2 3 4 5 6 7 8 9 10]
validates :product_id, presence: true
has_and_belongs_to_many :categories
has_and_belongs_to_many :tags
has_many :products
belongs_to :product
...
end
match.rb
class Match < ActiveRecord::Base
belongs_to :product
belongs_to :matched_product, class_name: 'Product'
end
products/show.html.erb
This gives me the name object of the matched product, but I would also like to get the name of the variation associated to the matched product
...
<% #product.matches.each do |c| %>
<li><%= link_to "#{c.matched_product.name}", product_path(c.matched_product) %></li>
<% end %>
...
In order to get the names of variation's images, you can do like this:
c.matched_product.variations.pluck(:image).join(', ')
Don't forget to use includes(:variations) to avoid N+1 queries, ie: #product.matches.includes(:variations)

Show specific entries on a many-to-many relationship in Ruby on Rails

I have three tables: illnesses, symptoms and a third table to map the relationship between the first two, called symptom_illness.
This third table has symptom_id, illness_id and its own id
I need a way to show, for example, all symptoms of a given "Common Cold" illness. In this example, "Common Cold" has an id of 1 and its symptoms have ids of 1 through 5.
This means that symptom_illness has 5 entries, where:
symptom_illness.illness_id = 1, symptom_id = 1
symptom_illness.illness_id = 1, symptom_id = 2
symptom_illness.illness_id = 1, symptom_id = 3
And so on. I need a way to display, in a single page, all the symptoms that have the same illness_id but I can't seem to find a way how to.
EDIT 1: My classes are related as such:
Symptom:
has_many :symptom_illness
has_many :illnesses, through: :symptom_illness
And similar for Illness.
Illness_symptom has belongs_to :symptom and belongs_to :illness
You have three models
class Symptom
has_many :symptom_illnesses
has_many :illnesses, through: :symptom_illnesses
end
class SymptomIllness
belongs_to :illness
belongs_to :symptom
end
class Illness
has_many :symptom_illnesses
has_many :symptoms, through: :symptom_illnesses
end
You can easily access al illness symptoms with something like that:
Illness.find(1).symptoms.each do |symptom|
# do something with this symptom
end
What do you want to show in the page?
If the symptom has a name attribute you can initialize a
#symptoms = Illness.find(1).symptoms
array in controlller and in the page you do something like
<% #symptomps.each do |symptom| %>
<% = symptom.name %>
<% end %>
You should use a has_many through: relationship.
class Illness < ActiveRecord::Base
has_many :symptom_illness
has_many :symptom, through: :symptom_illness
end
class SymptomIllness < ActiveRecord::Base
belongs_to :symptom
belongs_to :illness
end
class Symptom < ActiveRecord::Base
has_many :symptom_illness
has_many :illness, through: :symptom_illness
end
http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
Class Symptom < ActiveRecord::Base
belongs_to :symptom_illness
has_many :ilnesses, through: symptom_illness
end
class SymptomIllness < ActiveRecord::Base
belongs_to :symptom
belongs_to :illness
scope :ilness, ->(*i) {
where(ilness_id: i.flatten.compact.uniq
}
end
class Illness < ActiveRecord::Base
belongs_to :symptom_illness
has_many :symptoms, through: :symptom_illness
end
Ilness.find(1).symptoms

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)

accepts_nested_attributes_for - belongs_to, has_many, fields_for

Is there any possible way to use nested_attributes_for in the way show below?
Basically I want to create a person, one or more cars and add details to each car. This is just a mock up, not a very realistic example. I get snagged when trying to build the details for the car as it hasn't been created yet.
Models:
class Person < ActiveRecord::Base
has_many :cars
accepts_nested_attributes_for :car
end
class Car < ActiveRecord::Base
belongs_to :person
has_many :details
accepts_nested_attributes_for :details
end
class Detail < ActiveRecord::Base
belongs_to :car
end
Form:
form_for #person do |f|
#fields
f.fields_for :car do |car|
#fields
car.fields_for :details |detail|
=detail.text_field :content
end
end
end
Have a look at that http://railscasts.com/episodes/196-nested-model-form-part-1?view=asciicast

rails model association problem

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.

Resources