rails one to-many two sided relation - ruby-on-rails

I wonder how to do the following in Rails in the right way.
I have class Order
class Order < ActiveRecord::Base
has_many :bids, :dependent => :destroy
belongs_to :user
end
and class Bid
class Bid < ActiveRecord::Base
belongs_to :order
end
The following works perfectly fine,
order = Order.find(1)
order.bids
However sometimes I want to get order by bid
order = bid.order
And of course backwards it doesn't work
In addition I want the following to be OK
bid.order.user.username
What the best way to do in Rails?

The order = bid.order should work. Not sure why it happens.
bid.order.user.username
To call this,
you can probably try
class Bid < ActiveRecord::Base
belongs_to :order
has_one :user, :through => :order
end
and call
bid.user.username

Related

Rails table join with extra details doesn't work

I have these 2 models, and I'm trying to add an association between them so I can add some extra details later:
class Ticket < ActiveRecord::Base
belongs_to :user
has_many :event_tickets
has_many :events, :through => :event_tickets
end
class Event < ActiveRecord::Base
has_many :event_tickets
has_many :tickets, :through => :event_tickets
end
class EventTicket < ActiveRecord::Base
belongs_to :event
belongs_to :ticket
end
I've tried adding an association like this, just to see it's working:
event_ticket = EventTicket.new(:ticket => ticket, :event => Event.all[0])
event_ticket.save!
This gives me:
can't write unknown attribute `ticket_id`
The ticket and event exist and are working fine, but can't get the event_ticket object working.
What am I doing wrong?
It sounds like you don't have an event_tickets table, or at least it doesn't have a ticket_id column. Are you sure you wrote the migration and ran it?

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

Rails - Query with has_many association

I am currently trying to create a custom method on a model, where the conditions used are those of a has_many association. The method I have so far is:
class Dealer < ActiveRecord::Base
has_many :purchases
def inventory
inventory = Vehicle.where(:purchases => self.purchases)
return inventory
end
end
This is not working, due to the fact that Vehicle has_many :purchases (thus there is no column "purchases" on the vehicle model). How can I use the vehicle.purchases array as a condition in this kind of query?
To complicate matters, the has_many is also polymorphic, so I can not simply use a .join(:purchases) element on the query, as there is no VehiclePurchase model.
EDIT: For clarity, the relevant parts of my purchase model and vehicle models are below:
class Purchase < ActiveRecord::Base
attr_accessible :dealer_id, :purchase_type_id
belongs_to :purchase_item_type, :polymorphic => true
end
class Vehicle < ActiveRecord::Base
has_many :purchases, :as => :purchase_item_type
end
class Dealer < ActiveRecord::Base
def inventory
Vehicle.where(:id => purchases.where(:purchase_item_type_type => "Vehicle").map(&:purchase_item_type_id))
end
end
Or:
def inventory
purchases.includes(:purchase_item_type).where(:purchase_item_type_type => "Vehicle").map(&:purchase_item_type)
end
I was able to do this using the :source and :source_type options on the Vehicle model, which allows polymorphic parents to be associated.

rails 3.1, how to calculate answers number using foreign key?

I have the following tables:
class FinalExam < ActiveRecord::Base
belongs_to :course
has_many :pages, :as => :course_unit, :dependent => :destroy
end
class Page < ActiveRecord::Base
belongs_to :course_unit, :polymorphic => true
has_one :quiz
has_one :slide
end
class Quiz < ActiveRecord::Base
belongs_to :page
end
class Answers < ActiveRecord::Base
belongs_to :quiz
end
So, we have Answer.Quiz.Page.FinalExam
Given the FianlExam id, what is the fastest way to find all Answers count ? how to get it ?
I can re-design the DB to have belongs_to :final_exam in Answers
class Answers < ActiveRecord::Base
belongs_to :quiz
belongs_to :final_exam
end
this way, I can say Answers.where(:final_exam_id=> params[:id]).count
Do I have to change the DB design ? or its a matter of a query ?
I need an expert advice please.
First of all I'm guessing that Quiz should read:
class Quiz < ActiveRecord::Base
belongs_to :page
has_many :answers
end
If so you can add these lines to your FinalExam model:
has_many :quizzes, :through => :pages
has_many :answers, :through => :quizzes
Allowing you to then call
FinalExam.first.answer.count
(Note: if you're on a version of Rails < 3.1, you'll need this plugin)
The drawback to this approach is that it becomes slow with a lot of data. In this case, you'd want to set up a counter cache in the FinalExam that updates every time an answer is added. It'd a little more complicated because of the many-layered relationships you have; see this post for more info:
counter_cache has_many_through sql optimisation, reduce number of sql queries

rails advanced find

I have three models:
class Address < ActiveRecord::Base
has_many :jobs
end
class Category < ActiveRecord::Base
has_many :jobs, :dependent => :destroy
end
class Job < ActiveRecord::Base
belongs_to :category
belongs_to :address
end
I'm trying to get all categories that the jobs has address_id != NULL
I'm almost there doing:
categories = Category.find(:all,:joins=>:jobs,:conditions=>'jobs.address_id is not null')
the problem is that i have a lot of repeated categories. I can solve it doing a:
categories.uniq!
but is not exactly the best solution.. Any idea?
Do you mean you have different categories with the same category name? If so you can try this:
categories = Category.find(:all,:joins=>:jobs,
:conditions=>'jobs.address_id is not null', :group => "category.name")
Note: If there are several categories with the same name you will get one of them. You have no control over the specific row returned to you.

Resources