Polymorphic Models in Ruby on Rails? - ruby-on-rails

For a project I'm working on, the store has two types of products - a real product and a group of products.
For this discussion, let's call them "1 T shirt" and "a box of T shirts". For one t-shirt, I need to store the normal attributes - price, sku, size, color, description, etc. For the box of t-shirts I need to have a price, sku, description, and a list of t-shirts that are included.
So right now, I'm representing this with the Shirt and ShirtCollection models. I can see this causing difficulty down the road when I need to do reporting and order management and making sure SKUs are unique.
So what's the best way of representing this?

You can have a Tshirt table and then self reference it with a has_many :through association.
Tshirt - id, sku, price, size, color, description, is_box
TshirtBox - parent_tshirt (id that references tshirt), child_tshirt (id that references tshirt)
Check out this link for more on self referential has_many :through http://www.aldenta.com/2006/11/10/has_many-through-self-referential-example/

I would have the following models
Tshirt
TshirtBox has_many TshirtItems
TshirtBoxItems (This is basically a join table with an id tshirt_box_id and tshirt_id) belongs_to TshirtBox
TshirtBoxItems is a way to link a Tshirt with a box and potentially other things in the future.

Related

HMT or HABTM for Orders and Items

Fairly new to rails and trying to understand which relationships to use before going forward.
I have two models: orders and items. This is a many to many relationship, but I'm unsure of which relationship to use.
Orders might have delivery time, quantity of items, etc.
Lastly, what would you call the model joining orders and items if using HMT?
If you need to know anything else about the relationship of the item on a particular order, you need HMT.
If your items change price in the future, do you want to know how much they were sold for on orders in the past?
In this type of requirement, I've always had many "LineItem" records for an order, and the line_item instances belong_to to the item and order, and record the pricing and/or quantity for that order.
HMT vs HABTM? There are so few times that all you need is a many-to-many, that I'd almost always go with HMT for the extra ability to add more information to the association.
This seems like a classic case of HABTM, and the example given in the Rails Guides is perfect. The choice comes down to whether you need any other data or logic on the join model itself. If so, then use the HMT, where you will create a third active_record model to serve as the join table. You can name that anything you want. But it seems like HABTM will work for you, and all you need to setup is the join table with the default name (items_orders) in your migration, and rails will take care of everything else for you.
class Order < ActiveRecord::Base
has_and_belongs_to_many :items
end
class Item < ActiveRecord::Base
has_and_belongs_to_many :orders
end

How should I set up a Rails app so that some Objects are linked to others (belong_to) but not all Objects have this relationship?

I'm not sure whether I've accurately reflected my aim in the title, but I'll explain more here.
In my app I have Companies, and Companies has_many Key_Contacts.
Companies also has_many Sales_Opportunities.
I would like the user to be able to select some of the Key_Contacts that belong_to the Company and associate them with a specific Sales_Opportunity. I would also like the user to be able to add a Key_Contact that is not associated with any Sales_Opportunity.
The aim for this is that I can show the specific Key_Contacts that are involved in one Sales_Opportunity view on the Sales_Opportunity page, but not all of them.
Is it as simple as adding a sales_opportunity_id to the Key_Contacts model, but not setting up the "belongs_to" and "has_many" relationships? Or is there a more "official Rails" method to achieve my goal?
If I am reading this right, then all you need to do is add another has_many :key_contacts relation to your SalesOpportunity model (and belongs_to :sales_opportunity in your KeyContacts model). Then relate all contacts belonging to a specific sales opportunity.

Database design for categorized to-do app

I'm trying to figure out what the best (most logical) way of designing this database for an app that will allow a user to CRUD to-do tasks (more or less), however, they're organized into hard-coded categories.
So let's say you're about to go to your favorite department store. You need to hit up the Women's floor and pick up your girlfriend the shoes she ordered, and the matching dress (which is on the completely other side of the store, but on the same floor.) Then, you need to go to the Boy's department for your little brother, and pick up two different pairs of shorts, one pair of pants, and a new pair of shoes.
The Women's Floor and Boy's Department are two examples of categories that the shopping list items will fall into.
So it looks like this:
* Women's Floor
1 Pair Shoes
1 Dress
* Boy's Department
2 Shorts
1 Pant
1 Pair Shoes
So my database design could look like so...
Categories: id, title
ListIndex: id, user_id
ShoppingList: id, listindex_id, category_id, item_id, order, active
Items: id, name, category_id
Categories would be Boy's Department, Women's Floor, etc. Users would not be able to create new categories, but instead, we would predefine the categories
ListIndex would provide a master relation to the shopping list as a whole.
ShoppingList would be the actual shopping list (active would be 0/1, so the user could have a way to remind themselves that they bought the item / put it in their cart.)
Items would have a list of items that are available to put into the to-do tasks. We would categorize these ourselves on the back-end.
Is this the right way of doing it?
Hopefully i understood the description of the problem correctly but i was thinking here's one way you could lay your database and models out. I also don't think you need the ListIndex:
Database Tables
Categories: id, title
ShoppingLists: id, user_id, order, active
Items: id, title
ShoppingListItems: id, item_id, shopping_list_id, quantity
CategorizedItems: id, category_id, item_id
Users: id, name
Models
User:
has_many shopping_lists
ShoppingList:
belongs_to user
has_many shopping_list_items
has_many items, through shopping_list_items
Items:
has_many categorized_items
has_many categories, through categorized_items
(optional: you could query an item for the shopping lists that it is on)
has_many shopping_list_items
has_many shopping_lists, through shopping_list_items
Categories:
has_many categorized_items
has_many items, through categorized_items
My thinking is this --
Individual categories are basically static, that's pretty straight forward.
Shopping lists represent a User's (via the user_id) list of items that will be purchased. The link between an item and a shopping list could take place in a join table called ShoppingListItems where each row links together the relationship between a list, an item, and the quantity.
Items are interesting because in your example an item is something that can actually be in multiple categories. i.e. "pants" can be in boys/girls/men/women and probably pets :(. To support that I think you can use another join table called CategorizedItems that basically lets you query for "items in a particular category" or "categories an item is in".

Adding categories to a Ruby on Rails application

I've had some issues with this before when creating applications and I think I'm starting to run into it again, hence I'm asking this on StackOverflow to save me a lot of time.
I've spent the last few weeks setting up a perfected product model for my system. The model performs exactly as I want it to and has several complex features (such as search via sunspot). I wanted to setup the category to product structure before I started this heavy development - however struggling with this kind of thing was just putting me off creating the application so I got straight into the product structure.
Now I've got the product model setup - what would be the easiest way to add a category ownership to encompass the products? (All products have a category_id column which store their father category id)
My plan is to have the category index to be a list of all the categories, the category show to be a list of the products inside that category and the product show being the view of the actual product. This would eliminate the product index and so I'll have to come up with a way to port the search feature (sunspot) from my index view to the category show somehow.
As for the actual listing of the products - I assume I'll have to do some kind of partial? (I don't know a lot about it).
Most basically, my relationships are planned to be:
category:
has_many :products
product:
has_one :category
My products then have a category_id column to store the ID of it's parent category.
Any tips on how to accomplish the relationships (category show to list the products etc)?
Best Regards,
Joe
Relationships like the one you're wanting are built into ActiveRecord support. Understanding the model relationships in Rails is critical to doing anything in Rails that's non-trivial, so study up.
Also, the relationship you're looking for is something like:
product:
belongs_to :category
category:
has_many :products

How to model "products" in an online store application

I'm building an online store to sell products like "Green Extra-large, T-shirts". I.e., the same shirt can have many sizes / colors, different combination can be sold out, different combination might have different prices, etc.
My question is how I should model these products in my Rails application (or really how to do it in any application).
My current thinking is:
Class Product
has_many :variants, :through => :characteristics
has_many :characteristics
end
Class Characteristic
belongs_to :product
belongs_to :variants
end
Class Variant
has_many :products, :through => :characteristics
belongs_to :characteristic
end
So each product will have one or more characteristics (e.g., "Color", "Size", etc), and each characteristic will then have one or more variants (e.g., "Red", "Blue", etc).
The problem with this method is where do I store price and inventory? I.e., a given product's price and inventory are determined by the variants its characteristics take. (Green might be more expensive than red, large might be out of stock, etc).
One thought I had was to give products a "base_price", and let variants modify it, but this seems overly complex (and might not work).
I have seen two solutions to this kind of dilemma. The first is to try to use characteristics to define subordinate products to the "main" product. The challenge here is that in addition to your thoughts for far, in most cases the product will evolve with new manufacturers that bring new aspects to the table. For example, one manufacturer may make a cheaper product, but have a different application method for the logo or stitching that may be significant enough to track.
I think that carrying a non significant product number for each product and then attaching the characteristics as attributes works out the best. It is easily searched and extensible. If a group of products are strongly related, a ProductGroup that the individual products attach to works well.
In tables:
ProductGroup
--------------------
ProductGroupID
ProductGroupName
ProductGroupDescription
Product
--------------------
ProductID
ProductGroupID
QtyOnHand
BasePrice
ProductColorID
ProductSizeID
ProductColor
------------
ProductColorID
ProductColorName
ProductSize
--------------
ProductSizeID
ProductSizeName
...more attributes...
The advantages here are that you can easily query for specific attributes, attributes are "flexible" in that more can be added (and old ones adjusted: if you started with "Red" but then added another "Red" to the color pool, you can change them to "Maroon" and "Bright Red".
You can control price and inventory are at the detail product level (although more tables may be required to account for sourcing costs).
This all assumes that your characteristics are universally shared. If they are not, your characteristic subtable approach can work by creating a join table between characteristics and the product detail tables and populate as needed. This will require more business logic .to ensure each product category gets all characteristics necessary. In this latter case I would use "prototype" products in the base product table (with Qty and Cost of 0) that I would clone the characteristics from and then adjust as each new product is entered. As you move forward, when a new variation appears, having a "clone this product" function that allows you to just adjust the differences from the base product would be valuable.
Finally, as far as managing the inventory and pricing, this is going to happen at the UI layer. Being able to generate queries for related products (product groups) and manage all the pricing for related products will go a long way to making this livable.
Just a quick-note. You can always try and take a look at the sourcecode of some other e-commerce products like Spree and Substruct they probably already answered that question for you.

Resources