Let's say customer is adding multiple products to cart.
Add car, apartment, tour, some coupons.
Products belong to categories.
Category has name attribute.
But how to give different attributes to car, apartment, tour, coupon?
I can't definitely create everything from product model.
So should I create different models for each category and connect through has many ro products model?
Or am I going to wrong direction?
Thanks
Having a Category for individual product seems to be a good approach here. Since your Category differs according to attributes. What you can do is create One more model, let's say: MasterCategory which has many Category and Category belongs to MasterCategory, which means for your MasterCategory Cars you'll have Audi, BMW, Nissan etc etc. categories and then link your products to their respective vendors in a table products_categories which will have product_id, category_id.
In my opinion, schema could go like this:
ProductsCategory:
product_id, category_id
MasterCategory:
id, name, created_at, updated_at
Category:
id, master_category_id, parent_id, name, position, name, permalink
For e.g. - A car MasterCategory will look like this:
#<MasterCategory id: 1, name: "cars", created_at: "2012-02-14 13:03:45", updated_at: "2012-02-14 13:03:45">
and its categories will be:
[#<Category id: 1, master_category_id: 1, parent_id: nil, position: 0, name: "cars", created_at: "2012-02-14 13:03:45", updated_at: "2012-02-14 13:03:45", permalink: "cars">, #<Category id: 2, master_category_id: 1, parent_id: 1, position: 0, name: "Audi", created_at: "2012-02-14 13:03:45", updated_at: "2012-02-14 13:32:51", permalink: "cars/audi">]
Now you can have two methods parent and children in your Category Model using parent_id attribute to locate and traverse master and sub categories easily. And you can use permalink attribute to easily locate a category which is under another category with one query: Category.find_by_permalink(params[:permalink]) and can display all the products related with this particular category. In future when you'll scale, I can bet you, you'll require this position attribute to manage position of your categories to display on your page. And in last master_category_id will give you an ease in life with:
car = MasterCategory.find(1)
car.categories.where("parent_id IS NOT NULL")
All the best!! :)
Related
Use case: on this site, users will be able to go on and select rental property for a specific amount of days. Users will be often be selling the same type of rental property.
Problem: Because multiple "sellers" will be renting out the same exact item, the "property detail page" will have many listings created by many different sellers (or in some case, a seller will have multiple properties available falling into the same "property detail page"). Each of these "listings" objects will have many pricing objects which contain a date, a price, and an availability boolean.
Current models are broken down below:
property.rb
has_many :listings
has_many :prices, :through => :listings
listing.rb
belongs_to :user
belongs_to :property
has_many :prices
price.rb
belongs_to :listing
What I have tried:
If for example, I wanted to obtain the MINIMUM sum of pricing for a specific property, I had jotted down this:
# property.rb
# minimum price for a pricing set out of all of the price objects
def minimum_price(start_date, end_date)
# this would sum up each days pricing to give the rental period a final price
prices = self.prices.where("day <= ?", end_date).where("day >= ?", start_date).sum(:price)
end
When I do it like this however, it simply combines every single users prices giving nothing of use.
Any help would be greatly appreciated! Of course I could loop through a properties listings until I found a minimum price set for a given date range, but that seems as though it would take an unnecessary amount of time and be largely inefficient.
EDIT
An example of data that should be outputted is a set of price objects that are the cheapest ones in a specific date range from ONE particular listing. It can not just combine all of the best priced dates from all of the users and add them as the buyer will be renting from ONE seller.
This is an actual example of desired output, as you can see these prices are ALL from the same listing ID.
[#<Price id: 156, day: "2020-12-01", listing_id: 7, price: 5.0, available: true, created_at: "2020-12-17 14:22:46", updated_at: "2020-12-17 14:22:46">, #<Price id: 157, day: "2020-12-02", listing_id: 7, price: 5.0, available: true, created_at: "2020-12-17 14:22:46", updated_at: "2020-12-17 14:22:46">, #<Price id: 158, day: "2020-12-03", listing_id: 7, price: 5.0, available: true, created_at: "2020-12-17 14:22:46", updated_at: "2020-12-17 14:22:46">, #<Price id: 159, day: "2020-12-04", listing_id: 7, price: 5.0, available: true, created_at: "2020-12-17 14:22:46", updated_at: "2020-12-17 14:22:46">]
So it sounds like you are calling this on a property so:
prices = self.prices.where("prices.day >= ? AND prices.day <= ?", start_date, end_date).sum(:price).group_by {|price| price.listing_id}
There is probably a SQL based way that you can use AR relations to do this. But this will give you a hash with a key for each listing_id and the value of that key should be the sum. I say "should" because this is a bit abstract for me to do without a system to test it on.
I have two models:-
Customer and Account.
Customer has_one account and account belongs_to customer
I want to join the tables and fetch only some fields. My code:-
Customer.joins(:account).select("customers.id, customers.name, accounts.opening_balance")
It gives me Customer::ActiveRecord_Relation in result like this:-
[#<Customer:0x00000005be0870 id: 1774, name: "James TEA">,
#<Customer:0x00000005be0730 id: 1777, name: "Joseph STORE">,
#<Customer:0x00000005be0578 id: 1835, name: "John CONFECTIONARY">,
#<Customer:0x00000005be03e8 id: 1836, name: "Jerry PAN SHOP">]
No matter what I do, I am not able to get fields from right table(account in this case). Any help?
Try:
customers = Customer.joins(:account).select("customers.id, customers.name, accounts.opening_balance as opening_balance")
customers.first.opening_balance
I have an a Groups table with an array of JSON objects representing different filters to be applied to a SQL query
Example group:
id: 1,
name: "my group",
filters: [
{field: "sessions", type: "greater_than", value: 5},
{field: "email", type: "contains", value: "#example.com}
]
An example record of the filtered table Visitors
id: 1, email: "example#gmail.com", sessions: 5, more_meta_data..
What I'd like to get is something like:
id: 1, matching_groups: ["my group"], email: "example#gmail.com", sessions: 5 more_meta_data..
Note that a visitor can be in many groups at the same time.
When querying a Visitor, I'd like to append the name of all the Groups for which all the filters match the attributes on the Visitior record.
I am kind of lost on this one, and apologise if I haven't explained it clearly enough. Does Postgres allow for this to be done at the DB level?
Any help is much appreciated, thanks
I am having a bit of trouble with what the best schema would be in mongo for some golf data that I have.
Tables:
ClubManufacturer (id, name, descr) -- ex: 1, Titleist
ClubType (id, name) -- ex: 1, Driver
Club (id, id_clubType, id_clubManufacturer, name, url) -- ex: 1, 1, 1, 913D2, link
Should I just store each club manufacturer as a document with club (and type) as properties of the document? I am at a loss because I'll be needing to access the data such that I need to show, all Drivers, or, all clubs by manufacturer.
I am also new to mongodb so any insight is much appreciated.
Thanks!
If your manufacturers have large descriptions then you might want to keep them separate to reduce the redundancy. As an extension of Asya Kamsky's answer:
Manufacturer Collection:
{
_id: "Manufacturer Name",
description: "Long ... Description"
}
Club Collection:
{
_id: Auto_Generated_Hash,
manufacturer: "Name/ID",
type: "Driver",
name: "Club Name",
url: "http://www.url.com/"
}
I used the manufacturer's name as the _id so that if you don't need the description you still know what the manufacturer is without doing a "join".
Unless your Manufacturer and Type tables are actually much larger than what you listed here, it seems simple to just have each document in Club collection look something like:
{ _id: 1,
manufacturer: 'Titleist',
type: 'Driver',
name: '913D2',
url: 'http://blah.blah.blah/'
}
Now you can index manufacturer and type fields to support fast queries by either of the attributes.
I have my Rails models in an online store I making setup with a cart that has line items. Every time a product is clicked on, a line item is generated that has a unique cart id, matching carts I make for user sessions (this example comes from the book Agile Web Development with rails.)
I want to count the number of items in a users cart, what's the best way to do this.
here's an example of what
li.each do |line|
puts li.to_yaml
end
outputs ....
- !ruby/object:LineItem
attributes:
id: 14
product_id: 81
cart_id: 11
created_at: 2012-06-27 14:10:09.060706000Z
updated_at: 2012-06-27 14:10:09.060706000Z
quantity: 1
---
- !ruby/object:LineItem
attributes:
id: 1
product_id: 2
cart_id: 6
created_at: 2012-06-25 18:29:20.726280000Z
updated_at: 2012-06-25 18:56:08.690670000Z
quantity: 2
- !ruby/object:LineItem
attributes:
id: 2
product_id: 4
cart_id: 6
created_at: 2012-06-25 18:56:10.014333000Z
updated_at: 2012-06-25 18:56:10.014333000Z
quantity: 1
So, I'd want the user with cart_id of 6 to know they have 3 items. Thanks.
Yes there is a better way. How are your models set up? Basically you'd want users to have a cart and a cart belongs_to a user. Also, since a line_item has a cart_id, you can have line_item belongs_to cart and cart has_many line_items.
With these associations, you can easily get what you need like:
cart.line_items.count
user.cart
user.cart.line_items
etc.
You can read up on rails associations here:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
I figured it out using the console
After choosing a cart so that #cart.id = 6 (current_cart = Cart.find(6) since the console didn't set the cart using a browser session)
#count = 0
LineItem.all.each do |item|
if (item.cart_id == #cart.id)
#count += item.quantity
end
end
There must be a better, more railsy way, though...
current_cart.line_items.size
Provided you have the following in cart.rb
has_many :line_items
-edit-
Ops, sorry, you wanted the sum of quantity.
current_cart.line_items.sum('quantity')