Not simple cart need expert answer - ruby-on-rails

I am so surprised of getting -1 for my questions. They are not simple, they are complex.
My line_items table have product_id cart_id order_id
Whenever customer clicks on product, it is added to the cart.
But my apartment, cars, tour package are not products. Whoever is thinking that somehow I can connect to products my cars, apartments tell me. They have fundamentally different attributes. When customers clicks on apartments and chooses 2 bedroom lets say how I can add to line_items my apartment_id or car_id or tour_id. Please I don't need theory on STI or multiple inheritance. I need exactly answer. Thanks for rails expert.

First of all you should format your question regarding to the SO guidelines, that's maybe because you're getting downvotes...
Anyway, I think you're looking for polymorphic associations.
Assuming that Product is meant to be a product available in your shop and LineItem represents a product in an order:
class LineItem < ActiveRecord::Base
has_one :product # ONE LineItem references ONE product in the shop
belongs_to :cart # respectively belongs_to :order
end
class Cart < ActiveRecord::Base
has_many :line_items # ONE Cart HAS MANY LineItems
end
class Product < ActiveRecord::Base
belongs_to :buyable, :polymorphic => true
# here you would have general attributes representing a product, e.g. 'name'
end
class Car < ActiveRecord::Base
has_one :product, :as => :buyable
# here you would have specific attributes in addition to the general attributes in
# product, e.g. 'brand'
end
class Apartment < ActiveRecord::Base
has_one :product, :as => :buyable
# here you would have specific attributes in addition to the general attributes in
# product, e.g. 'address'
end
To make that work your products table must have the two columns
buyable_type (string)
buyable_id (integer)
So in your code you can check what exactly your Product is by doing
#product = Product.find(params[:id])
if #product.buyable.is_a? Car
puts #product.buyable.brand
elsif #product.buyable.is_a? Apartment
puts #product.buyable.address
end

Related

How to get sum of invoices across join table in Ruby on Rails?

I have these models in my Rails 4 app:
class Invoice < ActiveRecord::Base
has_many :allocations
has_many :payments, :through => :allocations
end
class Allocation < ActiveRecord::Base
belongs_to :invoice
belongs_to :payment
end
class Payment < ActiveRecord::Base
has_many :allocations
has_many :invoices, :through => :allocations
end
Obviously, it is possible that one payment belongs to many invoices.
In the Payment model I have this function that sums the total of all the invoices that one specific payment relates to:
def invoice_total_of_siblings
invoice_ids = Allocation.where(:payment_id => id).map(&:invoice_id)
invoices = Invoice.where(:id => invoice_ids)
invoices.to_a.sum(&:total)
end
However, this function feels cumbersome and I wonder how it could be made more concise.
Thanks for any help.
Using your set of associations (payment has many invoices through allocations), you could simply do this:
def invoice_total_of_siblings
invoices.sum(:total)
end
EDIT:
This solution works as-is for database fields, provided that the given set is an ActiveRecord association.
In this speicific case, however, as it is produced from the comments, total is a calculated field. Hence, the given set will not be an ActiveRecord association, but an Array. Then, you will need to map the field in order to sum it. The correct syntax in this case will be:
def invoice_total_of_siblings
invoices.sum(&:total)
end

How do I handle using 1 model to belong_to 2 different models at different times?

I am creating a Shopping Cart.
So I will have a model called LineItem.
Each instance of a cart will have 1+ line items. As will a completed transaction - which becomes an 'order'.
So, in theory, a LineItem belongs_to Cart and also belongs_to Order.
But, what would the DB table look like? a cart_id and order_id in my LineItems table?
That would mean that for every valid cart record, there will be an order_id that is nil (or empty). Likewise, for every valid order, there will be an empty cart_id.
This seems like a non-Railsy way to do this.
What is the best way to do this? A polymorphic association? What would that look like if I should do that?
The line item model can have two belongs_to associations
class LineItem < ActiveRecord::Base
belongs_to :cart
belongs_to :order
end
But this can get messy if it needs to belong to several different classes. The solution is polymorphic association which allows a model to belong to more than one model on a SINGLE association, which in the example below is :line_itemable. It will add two attributes, line_itemable_id and line_itemable_type to the LineItem model.
class LineItem < ActiveRecord::Base
belongs_to :line_itemable, :polymorphic => true
end
class Order < ActiveRecord::Base
has_many :line_items, :as => :line_itemable
end
class Cart < ActiveRecord::Base
has_many :line_items, :as => :line_itemable
end
If cart and order share similar attributes such as cost, then another option is to eliminate the order class and simply add a :paid flag on the cart.
I would suggest polymorphic association.
class LineItem < ActiveRecord::Base
belongs_to :owner, :polymorphic => true
end
class Order < ActiveRecord::Base
has_many :line_items, :as => :owner
end
class Cart < ActiveRecord::Base
has_many :line_items, :as => :owner
end
you will need to add owner_type and owner_id to line_items table.
Refer this

has_many with foreign key in own table as an array?

I'm trying to do a "ecommerce like" solution. When a product is defined, there are many option_values, e.g. whip cream => yes.
When I'm creating a line_item, my associations are like this.
class LineItem < ActiveRecord::Base
belongs_to :cart
belongs_to :order
belongs_to :product
belongs_to :shop
...
When a user chooses a product, he chooses options_values and a line_item must be created to store this.
Currently I'm not sure what is a good way to model the option_values in a line item.
My gut instinct is that a line_item has_many option_values, but it would seem weird to store foreign keys in option_values. The other thought is that line_item habtm option_values.
What would be a good way to model this line_item has_many option_values relationship, ideally storing the reference in the line_items table?
If your option_values are always boolean (whip cream => yes) you should have an OptionValues model with all available option_values and do habtm between LineItem and OptionValues.
If your option values are not always boolean (sugar => 2.spoons) then you must store this value (2.spoons) in the join model, so you should do something like this:
class LineItem < ActiveRecord::Base
has_many :line_item_option_values
...
end
class LineItemOptionValue < ActiveRecord::Base
belongs_to :line_item
belongs_to :option_value
end
class OptionValue < ActiveRecord::Base
has_many :line_item_option_values
end
And have the table for LineItemOptionValue a field for the value of the option.

Rails database design for a model which can be used by one of many models

I have a model named feedback with attributes, rating and review. A product may have a feedback, a appointment may have a feedback, a user may have a feedback.
I could add individual fields, like user_id, product_id, appointment_id in the feedbacks table, but that does not seem to be a very good scalable solution. The other option in my mind is to use a generalized, reference_id field, and a reference_model field which can be populated with the model name converted to string, and then I could manually interpret if the id entered in reference_id belongs to a user, product or an appointment.
What would be the best way of going about associating each feedback with any one of the 3 models, at a given time?
You should read about Polymorphic Associations.
class Picture < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
end
class Employee < ActiveRecord::Base
has_many :pictures, :as => :imageable
end
class Product < ActiveRecord::Base
has_many :pictures, :as => :imageable
end
There's even a nice RailsCast.

Ruby on Rails Model / Database Associations

I have a user model, farmer model, doctor model, and education model.
A farmer has a user and many educations.
A doctor has a user and many educations.
How do I setup the database for the education model?
Should it have a farmer_id AND a doctor_id?
But a education cannot belong to a farmer AND and doctor at the same time. It's one or the other.
So my education database entry would either have a farmer_id OR a doctor_id filled in, but not both.
Is there a way to guarantee that only one of the ids could be filled in at a time?
Or is there a better way to associate these models?
Your help would be appreciated!
Oh, and don't worry about the names of the models (farmer, doctor, etc.). It's just an example.
I see two possible solutions for this scenario.
The first one is to make use of polymorphic associations for education. That could look like this:
class Farmer < ActiveRecord::Base
belongs_to :user
has_many :educations, :as => :profession
end
class Doctor < ActiveRecord::Base
belongs_to :user
has_many :educations, :as => :profession
end
class Education < ActiveRecord::Base
belongs_to :profession, :polymorphic => true
end
So instead of education having a doctor_id or a farmer_id it has one profession_id and one profession_type.
The second solution would be to make use of Single Table Inheritance. And in your scenrio, that could be accomplished by letting a Doctor be a User instead of belonging to a User. And of course the same thing for a Farmer. That could look like this:
class User < ActiveRecord::Base
has_many :educations
end
class Farmer < User
end
class Doctor < User
end
class Education < ActiveRecord::Base
belongs_to :user
end
And in this scenario you would add a type column to the User model to store what type of class it is and then only having a user_id in the Education model
I think its appropriate to have the relations this way based on roles.
Class User
has_one :role
has_many :educations
end
Class Role
#What ever roles you have.
#Farmer or Doctor
belongs_to :user
end
class Education
belongs_to :user
end
This way you will store the user_id in the education object, which solves your problem.

Resources