How make categories relationships with several model? - ruby-on-rails

I have next models: Articles, Announcements, Catalogs and Media.
For item of every model I need to create a subcategory and a category. I will plan to create a relationship table with two columns: parend_id and child_id, and a column for every model with category_id.
How many relationship models I should create?
One for all?
Or one relationship model for every model?

No need to create a relationship model instead just use belongs_to relationship
because you said following i guess belongs_to relations should do it
For item of every model I need create subcategory and category.
So just add subcategory_id and category_id in your tables: Articles, Announcements, Catalogs and Media and establish has_many belongs_to relationship
EDIT But if you insist for relationship model then I would suggest to use one relationship model for every model.
Last EDIT: I really think you should use belongs_to, has_many relation
Class Article < ActiveRecord::Base
belongs_to :category
belongs_to :subcategory
end
class Category < ActiveRecord::Base
has_many :articles
# the same relation(has_many) will be for Announcements, Catalogs and Media
has_many :subcategories
end
class Subcategory < ActiveRecord::Base
has_many :articles
belongs_to :category
end
In this way you can get all articles using category.subcategories.articles
If the category has only one Subcategory then change the relation between them to has_one and your syntax will become category.subcategory.articles

I would personally use a has_many :through relationship with a polymorphic association in a single join table:
#app/models/article.rb
Class Article < ActiveRecord::Base
has_many :categorizable_categories
has_many :categories, through: :categorizable_categories
end
class Article < ActiveRecord::Base
has_many :tags, as: :taggable,dependent: :destroy
has_many :categories, through: :tags
end
class Category < ActiveRecord::Base
has_many :tags, dependent: :destroy
has_many :articles, through: :tags, source: :taggable, source_type: 'Article'
end
class Tag < ActiveRecord::Base
belongs_to :taggable, polymorphic: true
belongs_to :category
end
This will allow you to call the categories for each model with the likes of #article.categories
To achieve the parent & child categories, I'd recommend using something like the Ancestry gem - you'd set up an ancestry column in your join table - basically allowing you to create relations between a model's categories directly

Related

Rails: How to setup multiple relation types to same models

I have a Product and Category model which have a has_and_belongs_to_many relation.
So I can search for Product.categories or Category.products
class Product < ApplicationRecord
has_and_belongs_to_many :categories
end
class Category < ApplicationRecord
has_and_belongs_to_many :products
end
Now I wanna add a new relation to the Product:
It should called main_category which only should be a has_one relation from the Product to the Category. So a Product only can have one MainCategory. But the Category of course should return all MainCategory products.
Must I create a SubClass of Category? Normally I would like to not create an extra class
How can I solve that to simply call Product.main_category or Category.main_products?
How to place indexes properly?
How does the migration should look like?
You can simply do it like this i guess
class Product < ApplicationRecord
has_and_belongs_to_many :categories
belongs_to :main_category, class_name: 'Category', foreign_key: :main_category_id
end
class Category < ApplicationRecord
has_and_belongs_to_many :categories
has_many :main_products, class_name: 'Product', foreign_key: :main_category_id
end
You will have to add an column to products table called main_category_id
Source https://guides.rubyonrails.org/association_basics.html#bi-directional-associations

has_many :through Association working with one-to-many

rails 4.2
ruby 2.1
I have two very basic models (product and tag) with has_many association through another model (taggings).
I have another model (category) with one-to-many connection with the aforementioned model (product).
Question:
How to show in view the tag list of products with a specific product's category?
In other words: Is it possible to list all tags from a particular category of product?
Models:
class Product < ActiveRecord::Base
has_many :taggings
has_many :tags, through: :taggings
belongs_to :category, counter_cache: true
end
class Tag < ActiveRecord::Base
has_many :taggings
has_many :products, through: :taggings
end
class Tagging < ActiveRecord::Base
belongs_to :product
belongs_to :tag, counter_cache: :products_count
end
class Category < ActiveRecord::Base
has_many :products
end
Quickest way is category_object.products.map(&:tags).flatten . Can be improved. :)
category has many products and product has many tags. Mapping tags method on each product. Flatten to remove duplicates.
You can add a product_tags association to the Category class:
class Category < ActiveRecord::Base
has_many :products
has_many :product_tags, -> { uniq }, through: :products
end
When you access the product_tags association, Rails will use a SELECT DISTINCT query so you won't end up with duplicate tags and the DB will eliminate duplicates.
If the above doesn't feel natural for your model, then you can also use the following (assuming c is a Category instance):
Tag.joins(:products).where(products: { category: c})
The DB query will be very similar to the other example.

Database creation/saving with a many-to-many relationship

I have two tables, item and category, and a joined table named Items_Categories. The one restriction I have is that an item HAS to have a category.
In my Item Model, I have this code:
class Item < ActiveRecord::Base
has_many :items_categories
has_many :categories, through: :items_categories
has_many :item_orders
has_many :orders, through: :item_orders
even though categories is not a column in my Items database.
Here's my ItemsCategory model:
class ItemsCategory < ActiveRecord::Base
belongs_to :item
belongs_to :category
end
Here's my Category Model:
class Category < ActiveRecord::Base
has_many :items_categories
has_many :items, through: :items_categories
end
In my test, I have this issue:
test 'it is valid' do
category = Category.create(name: "hot beverages")
item = category.items.create(title: "fjdkasf", description: "fjakdsf", price: 20901290)
assert item.valid?
end
Basically, this test fails because I cannot create an item until it item.categories is not nill. But the validation doesn't pass until I create the item in item_categories. So... what do I do? Basically I can't pass the validation when I create the item because the item doesn't yet have a category. But I want to make sure that every time I create an item, it has an associated item. So what do I do?
Validation with has_many :through relations can be tricky sometimes, there's a hint in the has_many :through documentation that you should define the inverse_of attribute on your join model:
If you are going to modify the association (rather than just read from
it), then it is a good idea to set the :inverse_of option on the
source association on the join model. This allows associated records
to be built which will automatically create the appropriate join model
records when they are saved. (See the 'Association Join Models'
section above.)
class ItemsCategory < ActiveRecord::Base
belongs_to :item, inverse_of: :items_categories
belongs_to :category, inverse_of: :items_categories
end
To be honest, I'm not 100% sure this will fix it, but give it a try and report back.

Can't show select box

I have 3 models:
Lending
Equipment
Category
Lending belongs_to equipment
Equipment belongs_to :category
Equipment has_many :lendings
Category has_many :equipments
I want to show a selectbox in lending's form with the categories.But there's not any association between Lending and Category models.I can't see an association between these two models(Lending and Category) but with Equipment and Category yes.
How do I do that? Ah I'm using simple form!
Excuse my english!
you have generated a textbook example of has_many :through:
http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
A has_many :through association is often used to set up a many-to-many connection with another model. This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding through a third model. For example, consider a medical practice where patients make appointments to see physicians. The relevant association declarations could look like this:
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, through: :appointments
end
You should be using delegation in this case. Add this line to your lending.rb file.
delegate :category, to: :equipment
This will return the concerned category.

One to many relationships in Rails

I'm having a hard time setting up the basic structure of my databases.
I have products (about 50). Each products is related to one or more place(s).
The basic schema would be this (no relation yet)
Products
id:integer
name:string
Places
id:integer
name:string
content:string
I first tought I could connect places and products by adding place_id to products and has_many belong_to in the controllers, but since a product can have more than one place, I don't know how.
If a Product has_many Places and a Place has_many Products your association needs to be many-to-many.
There are two ways to do this in Rails, the most recommended is a join model. You explicitly label the relationship between Products and Places. You could call it ProductLocation or Shop or similar, it would look like this:
product_locations:
product_id
place_id
class ProductLocation < ActiveRecord::Base
belongs_to :product
belongs_to :place
end
class Place < ActiveRecord::Base
has_many :product_locations
has_many :products, :through => :product_locations
end
class Product < ActiveRecord::Base
has_many :product_locations
has_many :places, :through => :product_locations
end
See http://guides.rubyonrails.org/association_basics.html#choosing-between-has_many-through-and-has_and_belongs_to_many
Just use through connection
ProductsPlaces (new table)
product_id
place_id
And in models
class Product < ActiveRecord::Base
has_many :places, :through => :products_places
end
class Place < ActiveRecord::Base
has_many :products, :through => :products_places
end
Also there is has_and_belongs_to_many which do in fact the same (with ProductsPlaces table)
class Product < ActiveRecord::Base
has_and_belongs_to_many :places
end
class Place < ActiveRecord::Base
has_and_belongs_to_many :products
end
But better use through, because has_and_belongs_to_many will be deprecated.
It sounds like you want to add product_id to places.
Product has_many Places
Place belongs_to Product

Resources