Ruby on Rails 4. Uni-directional associations - ruby-on-rails

I need to solve two tasks in my rails app and i need some advice:
I have Person model and Car Model. One person can have only one car. it means that Car always has driver = person, but not each person has a car. So i need uni-directional One to One here. Is it possible to implement with rails? Actually i need has_one on Car and i don't need belongs_to on Person
I have Order and Load models. In my system there are many orders and when i am ready to deliver these orders I construct new Load object and put all orders which i want to deliver there. So every Load has_many orders but not each order belongs_to Load. It is uni-directional one-to-many... Also i don't need something like order.load, i need only load.orders
So how can I implement it with rails?

class Person < ActiveRecord::Base
has_one :car
end
class Load < ActiveRecord::Base
has_many :orders
end
Then you can call person_instance.car or load_instance.orders. You will have to have load_id on the orders and person_id on the cars

Related

Get all associated data for all records of a model type in Rails?

How do I meld together getting all of the associated data for all of the records of a given model?
I have the following models:
User --N:1--> Reservation <--1:N-- Concert
So pseudo-code:
Reservation belongs_to User
Reservation belongs_to Concert
User has_many Reservations
User has_many Concerts through Reservations
Concert has_many Reservations
Concert has_many Users through Reservations
How do I make a single big array of everything?
I can get all my Reservations via Reservation.all
I can get the User for a particular Reservation via Reservation.find(25).user
I can get the Concert for a particular Reservation via Reservation.find(25).concert
But how do I get it for all of them? If I do
Reservation.all.each do |res|
res.user.name+","+res.concert.name+","+res.concert.date # etc.
end
Then it will do two new database queries for each reservation as it loops through. For 10 records, it might not matter, but for thousands, it can be very painful. Add to it other associations (e.g. Concert belongs_to venue, User has_one email, etc.)...
Is there any way to say, "Get all of the reservations and the following attached info" so it loads in a single SQL query?
What you're trying to accomplish is called eager loading, and can be done using includes in ActiveRecord. See below:
N + 1 queries problem
Active Record lets you specify in advance all the associations that are going to be loaded. This is possible by specifying the includes method of the Model.find call. With includes, Active Record ensures that all of the specified associations are loaded using the minimum possible number of queries.
http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations
In your example you could use the following:
Reservation.all.includes(:user, :concert)
It is also a good idea to specify the :inverse_of option for your :belongs_to relations. This optimizes object loading and makes sure that cross-referencing a model will point back to the same object in memory, i.e.:
#user == #user.reservations.first.user # true
More information available here:
If you are using a belongs_to on the join model, it is a good idea to set the :inverse_of option on the belongs_to ...
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
In your example:
# app/models/reservation.rb
belongs_to :user, :inverse_of => :reservations
belongs_to :concert, :inverse_of => :reservations

Database organization for separating two different types of the same model

So I want my User model to have_many Skills. I want there to be two different categories for the skills: a wanted skill, and a possessed skill.
For example, a user can add a skill to their profile that they possess, such as HTML. They can also add a skill to their profile that they wish to learn, such as Ruby on Rails. On their profile it'll list their current skills and wanted ones, separately.
From a high level, what's the best way to architect this? I just want there to be 1 Skill model with no duplicates, but I want there to be a way for users to have the 2 separate groups of skills in the database.
You can use single table inheritance
class Skill < ActiveRecord::Base
end
class WantedSkill < Skill
belongs_to :user
end
class PossessesSkill < Skill
belongs_to :user
end
Your skills table should have a column called type where the type of the skill will be stored.
WantedSkill.create(:name => "html")
Above will save the record in the skills table with type 'WantedSkill'. You can retrieve it by
WantedSkill.where(:name => "html").first
your user associations can be like
class User < ActiveRecord::Base
has_many :wanted_skills
has_many :possessed_skills
end
You can read documentation here
A way to achieve this, you need two skill fields like: wanted_skill and possessed_skill
So, in Ruby on Rails you can have many references (with different names) to the same model, you only need to declare which class corresponds using class_name in the references, e.g.:
class User < ActiveRecord::Base
belongs_to :wanted_skill, class_name: 'Skill'
belongs_to :possessed_skill, class_name: 'Skill'
end

How to logically layout the relationship for models in a typical Marketplace platform?

I am new to Rails, ORM and database building. I am currently building a 2 sided marketplace platform like AirBnb, but I am not quite sure how to lay out the relationships between the models properly for this type of platform, like one_to_many rel or such.
Here is what I wish to achieve.
Customer can signup, create an account/login/profile -> User Table
Customer can generate a request/order, such as, food order, cleaning order, etc -->??
the other gets displayed to service workers, who fits the criteria for the order, if the worker is a cook, then he/she gets to see all of the orders related to food order, sorted by cost, requirement, etc.
I am not really sure how to map out the association of these 3 models... Can anyone help me?
class User < ActiveRecord::Base
has_many :orders
end
class Worker < ActiveRecord::Base
has_many :orders
end
class Order < ActiveRecord::Base
belongs_to :user
belongs_to :worker
scope :for_cook, where("category == cook")
scope :for_cleaner, where("category == cleaner")
end
Then when you want the list of all orders that a cook can fulfill:
available_cook_orders = Order.for_cook
And you'd add additional logic to handle the other criteria you mentioned (cost, etc.)

Rails - delete one side of a one-to-many relationship

Quick question:
If I have a one-to-many relationship, such as this:
class SalesPerson < ActiveRecord::Base
has_many :deals
end
class Deal < ActiveRecord::Base
belongs_to :sales_person
end
how can I delete a Sales Person, without negatively impacting the deals associated with them? The use-case for this would be if someone left the organization. We still need a record of the deals in the database, but that sales person record is no longer needed.
Would it just be better to have an active/inactive flag on the sales person instead?
Thanks.
For this kind of situations I've use acts_as_paranoid, basically It adds a new timestamps column: deleted_at and overrides some of your AR finders.

RoR: "belongs_to_many"? Association headache

I can't seem to wrap my head around this, so I thought I'd post and see if anyone could help me out (please pardon the question if it's insultingly simple: it's complicated to me right now!)
I have these models:
order
service
customer
I think they speak for themselves: a service is what the customer buys when they place an order.
Ok.
So, naturally, I setup these relationships:
# a customer can have many orders
class Customer
has_many :orders
end
# an order belongs to a single customer and can have many services
class Order
belongs_to :customer
has_many :services
end
... but here's where I trip up:
# a service can belong to many orders
class Service
# belongs_to :order ???
end
Because my understanding of belongs_to is that--if I put it there--a service could only belong to one order (it would have only one value in the order_id key field--currently not present--tying it to only one order, where it needs to be able to belong to many orders).
What am I missing here?
There are two ways to handle this. The first is a rails-managed many-to-many relationship. In this case, you use a "has_and_belongs_to_many" relationship in both the Order and Service models. Rails will automatically create a join table which manages the relationships. The relationships look like this:
class Order
has_and_belongs_to_many :services
end
class Service
has_and_belongs_to_many :orders
end
The second way is to manage the join table yourself through an intermediate model. In this case, you might have another model called "LineItem" that represents a Service in the context of an Order. The relationships look like this:
class LineItem
belongs_to :order
belongs_to :service
end
class Order
has_many :line_items
end
class Service
has_many :line_items
end
I prefer the second myself. It's probably just me, but I don't get as confused about what's going on when it's explicit. Plus if I ever want to add some attributes to the relationship itself (like perhaps a quantity in your case) I'm already prepared to do that.
class Customer
has_many :orders
end
class Service
has_many :orders
end
class Order
belongs_to :customer
belongs_to :service
end
The Order should have customer_id and service_id, because it is in a many-to-one relationship with both.
I think this Railscast will help you out - basically you have 2 options. You can use has_and_belongs_to_many or has_many :through.
You will also find that has_and_belongs_to_many has been deprecated in favor of has_many :though => model_name which gives the same (and more) functionality.
I think you have realized this but your order is really a composite domain model, sometimes called an aggregate in DDD speak.
Your Service is a really a listing of some product/service that someone can order. Your order aggregate records what someone ordered.
The aggregate as someone else said is made up of a header, the Order, which includes things like who ordered, the date, does it include taxes, shipping charge, etc. And the Order has_many OrderLineItem's. The OrderLineItem belongs_to Service and contains things like the quantity ordered, belongs_to the product/service, etc.
class Customer < ActiveRecord::Base
has_many :orders
end
class Order < ActiveRecord::Base
belongs_to :customer
end
class OrderLineItem < ActiveRecord::Base
belongs_to :Order
end
I personally use the OrderLineItem model name in deference to LineItem because in a system that needs to ship real products, as opposed to services, you might have allocations that link orders to inventory which would have line items and shipments that get the allocated product to the client, which also have line items. So the line item term can become very overloaded. This likely is not the case in your model because you're only doing services.

Resources