has_many nested to many models in Rails - ruby-on-rails

I have 4 different models in rails and there is a has_many and belongs_to association between them. For example:
class Apple < AR::Base
has_many :bananas
end
class Banana < AR::Base
belongs_to :apple
has_many :oranges
end
class Orange < AR::Base
belongs_to :banana
has_many :berries
end
class Berry < AR::Base
belongs_to :orange
end
Now, if I write, like #apple.berries, I should get the list of berries belongs to that Apple. So how should I define this association? One of my friend told me to use inverse polymorphic association. I don't know whether its related to the above issue or not.

What you actually need here is has_many + through relationship. Right now, an Apple object does contain Berry objects, but Apple object doesn't contain them directly. So we need to tell it explicitly like:
class Apple < ActiveRecord::Base
has_many :bananas
has_many :berries, through: :bananas
end
class Banana < ActiveRecord::Base
belongs_to :apple
has_many :oranges
has_many :berries, through: :oranges
end
Now, you can berries directly on an Apple object as well as on a Banana object.

Related

how to connect two table that has no relation in rails

I have a table called foods and categories, but this table has no relation, I want to connect them through another table called food_category. And I want to make one-to-one relation between food and category maybe the diagram looks like this
class Food < ApplicationRecord
has_one :category
end
class Category < ApplicationRecord
has_one :food
end
class FoodCategory < ApplicationRecord
belongs_to :category
belongs_to :food
end
Is it possible to do this?
Yes, this is possible. You just need to do
has_one :category, through: :food_categories
as discussed in the Rails docs here.
However, this is a long-winded way to go about this kind of association. If it's going to be one-to-one, why not just add a foreign key to Category from Food? And presumably, you would actually want Category to contain many Food records? Seems like the below would make more sense:
class Food < ApplicationRecord
belongs_to :category
end
class Category < ApplicationRecord
has_many :food
end
class Food < ApplicationRecord
has_one :food_category
has_one :category, through: :food_categories
end
In rails console, you can access like this
Food.find(:id).categories

Is this database relation schema correct?

I made my first project and got into problem that I couldn't get the right category_information values for specific competitions category through relations. So I started thinking that this could be the wrong schema for this task, so my question - is it actually wrong?
Current Scheme:
Assuming the following relationships between models from your image.
class Competition < ApplicationRecord
has_many :categories
has_many :informations
has_many :category_informations, through: :categories
end
class Category < ApplicationRecord
belongs_to :competetion
has_many :category_informations
has_many :information, through: :category_informations
end
class CategoryInformation
belongs_to :catagory
belongs_to :information
end
class Information < ApplicationRecord
belongs_to :competetion
has_many :category_informations
has_many :catagory, through: :category_information
end
Model can relates with one_to_many_to_many using :through option
It explains a association used to set up a many-to-many connection with another model.
you can get the category_informations from competition like
Competition.first.category_informations
It is all for doing! Pretty good, right?
And you could do get information from category too
Category.first.informations
Actually wrong schema doesn't exist, just there exists some wrong association description.
You can get more usage to use association from docs at 2.3 section and 4.3 section
Assuming the following relationships between tables,
A competition has_many categories,
A competition has_many information,
A category has_many information,
A category has_many competition,
An information has_many category
You can use has_many_through relationships
class Category < ApplicationRecord
has_many :category_competitions
has_many :competitions, through: :category_competition
has_many :category_informations
has_many :informations, through: :category_informations
end
class Information < ApplicationRecord
has_many :category_informations
has_many :categories, through: :category_informations
end
class Competition < ApplicationRecord
has_many :category_competition
has_many :categories, through: :category_competitions
end
class CategoryCompetition < ApplicationRecord
belongs_to :category
belongs_to :information
end
class CategoryInformation < ApplicationRecord
belongs_to :category
belongs_to :information
end
By this way you can access,Categories of a particular competition by #competition.categories
This article might be helpful for you to understand associations better
https://www.sitepoint.com/master-many-to-many-associations-with-activerecord/

How to define a nested has_one association?

Suppose we have this contrived model structure
class Apple < ActiveRecord::Base
belongs_to :fruit
has_one :tree, through: :fruit
has_one :organism, through: :tree
end
class Fruit < ActiveRecord::Base
belongs_to :tree
has_many :apples
end
class Tree < ActiveRecord::Base
belongs_to :organism
has_many :fruits
end
class Organism < ActiveRecord::Base
has_many :trees
end
To avoid having to call #apple.fruit.tree.organism, I have definded the two has_one-through directives in Apple, and expect #apple.organism to work, but it does not. #apple.tree.organism does work.
Am I doing something wrong? Should I just define a getter method for :organism on Apple instances and be done with it?
Your has_one technically performs the characteristic of belongs_to: think Organism has_many apples through trees and not the other way around. "belongs_to :through" does not work in Rails, so I suggest using delegate in your models.
class Apple < ActiveRecord::Base
delegate :organism, to: :fruit
end
class Fruit < ActiveRecord::Base
delegate :organism, to :tree
end

How do I scope through a model that's somewhat part of the association?

I can't comprehend how I would scope through a child using a model that isn't fully associated with it. The main model being Kid and the other being Favorite. In the app, a user can have Favorite moms and a Kid belongs to a mom and a dad. Mom and Dad don't belong to anything:
class Favorite < ActiveRecord::Base
belongs_to :user
belongs_to :mom
end
class Kid < ActiveRecord::Base
belongs_to :user
belongs_to :dad
belongs_to :mom
end
class User < ActiveRecord::Base
has_many :kids
has_many :favorites
end
As you can see, a Favorite doesn't have any association to Kid. I'm guessing it would if I made it go through each other like favorite.kids or kid.favorites but the latter doesn't make sense to me because of what I want to do with it.
What I want to do is create a scope that list a dads' kids but only for the ones that are a user's favorite moms. So something like:
#dad = Dad.find(params[:dad_id])
#kids = #dad.kids.current_users_favorite_moms
But which model what I start on Favorites? Dad? Mom? I'm not sure. Could you help me?
First of all I don't understand the relation between the Kid and the User so I'm gonna drop it.
I think it would be easier if you used has_many :through
class User < ActiveRecord::Base
has_many :favorite_moms, through: :favorites, class_name: :mom
end
Class Kid < ActiveRecord::Base
belongs_to :mom
belongs_to :dad
end
class Favorite < ActiveRecord::Base
belongs_to :user
belongs_to :mom
end
Then we'd do this
#dad = Dad.find(id)
#kids = Kid.where(dad: #dad, mom: current_user.favorite_moms)
Try it and tell me if it works.

Setting up a Has_Many :through Association

On the application I'm currently working on, I'm stuck on setting up the associations between 3 models to ensure referential integrity. I have an Event model, Building model, and a Room model. The association in real life is pretty intuitive. An Event can only be in one Building and one Room. A Building clearly can have multiple rooms.
Here's what I have set up now. However, how can Events specify their room if they belong to Buildings, and the foreign key for the Room is in the Events table? Is this where you use a has_many :through relationship? Is it good practice to store both the Building and Room foreign keys in the Event table, as Rooms are owned by Buildings? What about the conditional relationship that requires a building to be specified before allowing a room to be specified (some buildings have 2 rooms, others have 20, for example)
Sorry I'm so unclear on this. Thanks in advance for the help!
class Event < ActiveRecord::Base
belongs_to :building
end
class Building < ActiveRecord::Base
has_many :events
has_many :rooms
end
class Room < ActiveRecord::Base
belongs_to :building
end
I think the best way to handle this is to do something like the following:
class Event < ActiveRecord::Base
belongs_to :room
has_one :building, :through => :room
end
class Building < ActiveRecord::Base
has_many :events
has_many :rooms
end
class Room < ActiveRecord::Base
belongs_to :building
end
So you can use has_one :through to specify that an event owns a hotel
I would recommend the following:
class Event < ActiveRecord::Base
belongs_to :room
has_one :building, through: :room
end
class Building < ActiveRecord::Base
has_many :events, through: :rooms
has_many :rooms
end
class Room < ActiveRecord::Base
belongs_to :building
has_many :events
end
This way you can do #room.events, #event.building, #building.events

Resources