Rails relationship between three models confusing - ruby-on-rails

I know there is a plenty of tutorials explaining how to create a 'has_many through' relationship between models, but I think my question is both technical and conceptual.
The objective is to create an online food ordering website
I created the Order, Item and OrderItem models.
Relationships:
class OrderItem < ActiveRecord::Base
belongs_to :item, conditions: "active = true"
belongs_to :order
end
class Order < ActiveRecord::Base
belongs_to :user
has_many :order_items
has_many :items, through: :order_items
validates :status, inclusion: { in: %w(ordered completed cancelled) }
end
class Item < ActiveRecord::Base
has_and_belongs_to_many :categories, join_table: :items_categories
has_many :order_items
has_many :orders, through: :order_items
validates_presence_of :title, :description
validates :price, numericality: { :greater_than=>0 }
end
Am I doing something wrong? Each order should be able to contain many items and the quantity of them.
I'm not very positive I'm doing the correct architecture for these models, as I can't assign the quantity via << operator, only assign the item.
Thanks for your time.

like this
order = Order.new(user: #user)
order.order_items << OrderItem.new(quantity: 100, item: Item.first)

Related

ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation How can i get this relationshop objects?

As i mentioned on the question..
I know this error and i know how associations work
In my case i have ProductRepository model which belongs_to :category
So of course when i'm trying to delete this category which this ProductRepository object belongs to i should get this error and it's totally fine and i know how to handle this exception
Now let's say that i have a many models which referring to categories like
Product, ProductRepositoy, Post, etc...
My question here, how can i get a list of this objects which belongs to categories, or even get a class name array or whatever
So when i handle this exception i can send a message to ask the user to check and delete the following before deleting this category ?
Example:
Once user delete category... if it has any items which belongs to it
he should get a message saying Please check the following (Posts, Products, etc..)
For who is going to answer, all i need is how to get this objects or even class names only
And i can do the rest
Thanks in advance :)
Here is the file, after removing what isn't necessary for the question
category.rb
class Category < ActiveRecord::Base
has_many :brands, :dependent => :destroy
has_many :products, :dependent => :destroy
end
product_respository.rb
class ProductRepository < ActiveRecord::Base
belongs_to :category
has_many :unity_folders, as: :product, dependent: :destroy
validates :name, :price, :barcode, presence: true
validates :barcode, uniqueness: true
end
product.rb
class Product < ActiveRecord::Base
belongs_to :category
belongs_to :brand
belongs_to :organization
has_many :unity_folders, as: :product, dependent: :destroy
has_one :product3d
belongs_to :shop
end

Create new parent record with has_many :through relationship for existing children

I am working on a Ruby on Rails API (version 4.0) to create and update invoices. The relationship between invoices and products is a has_many trough: relationship. Imagine I have product 1, 2, & 3. I am having trouble creating a new invoice that contains product 1 & 3.. When I run the code below I get the error:
Unknown primary key for table invoices_products in model InvoicesProduct.
This error doesn't really make sense to me since InvoicesProduct is a join table and shouldn't require a primary key.
One tricky part about the design is that it needs to track which employee added which products to the invoice, which is why invoices_product has employee_id. It does not seem to be the cause of the problem at the moment. Here is the DB design of the tables in questions:
InvoicesController
This is the code I currently have in the controller. The error message occurs on the first line of create:
def create
invoice = Invoice.new(create_invoice_params)
invoice.created_by = #current_user
# eventually need to set employee_id on each invoice_product,
# but just need to get it working first
# invoice.invoices_products.map!{|link| link.employee = #current_user }
invoice.save
respond_with invoice
end
def create_invoice_params
params.fetch(:invoice).permit(:customer_id, :status_code, :payment_method_code, product_ids: [])
end
Invoice
# /app/models/invoice.rb
class Invoice < ActiveRecord::Base
validates_presence_of :customer
validates_presence_of :created_by
belongs_to :customer, inverse_of: :invoices
belongs_to :created_by, inverse_of: :invoices, class_name: 'Employee'
has_many :invoices_products, inverse_of: :invoice
has_many :products, through: :invoices_products
end
InvoicesProduct
class InvoicesProduct < ActiveRecord::Base
validates_presence_of :invoice
validates_presence_of :product
validates_presence_of :employee
belongs_to :product, inverse_of: :invoices_products
belongs_to :invoice, inverse_of: :invoices_products
belongs_to :employee, inverse_of: :invoices_products
end
Product
# /app/models/product.rb
class Product < ActiveRecord::Base
validates :name, presence: true, length: { maximum: 100 }
has_many :invoices_products, inverse_of: :product
has_many :invoices, through: :invoices_products
end
Request
This is what I've got in mind for a working request, the solution doesn't need to match this, but its what I've been trying
{
"invoice": {
"customer_id": "1",
"product_ids": ["1", "5", "8"]
}
}
I was able to fix the relationship by adding a primary key to the invoices_products. For some reason I was under the impression that join tables did not require a primary key for has_many :through relationships. However, looking at the example on the Rails guide site, the example join table does have a primary key.
That is because you are using has_many :through. If you don't want id (or any other additional field) in the join table, use has_many_and_belongs_to instead

find_or_create on a has many through relationship

I have a has many through relationship in my app:
Shows has many Bands through => Lineups
Bands are unique by :name
class Show < ActiveRecord::Base
attr_accessible :city_id, :title, :dateonly, :timeonly, :image, :canceled, :venue_attributes, :bands_attributes
belongs_to :city
belongs_to :venue
has_many :lineups
has_many :bands, through: :lineups
has_and_belongs_to_many :users
end
class Lineup < ActiveRecord::Base
belongs_to :show
belongs_to :band
end
class Band < ActiveRecord::Base
attr_accessible :name, :website, :country, :state
has_many :lineups
has_many :shows, through: :lineups
validates :name, presence: true
validates_uniqueness_of :name
before_save :titleize_name
private
def titleize_name
self.name = self.name.titleize
end
end
New Bands are created like this:
(lets say we have a show record already saved called s1)
> s1.bands.new(name: "Wet Food")
> s1.save
Right now this will only save if a band named "Wet Food" doesn't already exist
In which model is the best place to do a Band.find_or_create in this relationship so that an existing band can be used if one with the same name exists?
This is generally the type of call that would go in a Controller (or maybe a service object), but not in a Model. It really depends on the particular user flow that you're trying to accomplish in your app. Basically, where ever you are already using s1.bands.new, you could use this instead :
s1.bands.where(name: 'Wet Food').first_or_create

Accessing rails attributes through deep associations

Here are my relevant models:
class ListItem < ActiveRecord::Base
belongs_to :inventory_item
belongs_to :shopping_list
belongs_to :item
end
class ShoppingList < ActiveRecord::Base
has_many :list_items
belongs_to :user, :foreign_key => :user_id
end
class InventoryItem < ActiveRecord::Base
belongs_to :item, :foreign_key => :item_id
belongs_to :vendor
has_many :list_items
end
I'm trying to access attributes of InventoryItem in my view. Here's what I currently have in my ShoppingListController.
def show
#list_items = ShoppingList.find(params[:id]).list_items
end
Can I do something like #inventory_items = #list_items.inventory_items? That code and variants of it that I've tried haven't worked. What am i missing here? Any tips for accessing attributes through multiple models like this? Thanks in advance!
The most straight forward approach would be to use has_many through on the ShoppingList class:
has_many :inventory_items, through: :list_items

Association through another table "Unknown key: through"(Rails)

I'm creating trips in my rails app and i want to add categories to those trips. The categories are stored in the Categories table in my DB and the user may select which categories are suitable for the trip. So multiple categories a trip can be used.
Although i'm a noob i figured some things out with some help of the RoR guides about this subject. Now, i've got a 3rd table tripcategories which will have to hold the trip_id and the category_id. Right? With that i've got the following models:
trip.rb:
class Trip < ActiveRecord::Base
attr_accessible :description, :title, :user_id, :triplocations_attributes, :photo
has_many :triplocations, :dependent => :destroy
has_many :tripcategories
has_many :categories, :through => :tripcategories
accepts_nested_attributes_for :triplocations, allow_destroy: true
end
category.rb:
class Category < ActiveRecord::Base
attr_accessible :name
has_many :tripcategories
belongs_to :trip, :through => :tripcategories
end
tripcategory.rb:
class Tripcategory < ActiveRecord::Base
attr_accessible :category_id, :trip_id
belongs_to :trip
belongs_to :category
end
When i'm trying it this way and trying to call trip.categories in my trip index it says "Unknown key: through". Am i doing something horribly wrong or am i missing the bigger picture?
Thanks in advance!
class Category < ActiveRecord::Base
attr_accessible :name
has_many :tripcategories
has_many :trips, :through => :tripcategories
end

Resources