Rails nested includes and belongs_to vs. has_one - ruby-on-rails

I am writing an application for a job board. There is a Users table where users can post jobs or request to be awarded jobs. Therefore my Jobs table has a user_id field for the posting user and a relationship to a Job_requests table that has a job_id and a user_id but here the user_id is the requesting user's id.
I am trying to show a job posted by a user:
current_user.jobs.find(params[:id])
including the requests for that job:
current_user.jobs.includes(:job_requests).find(params[:id])
but also including the details for the requesting user:
current_user.jobs.includes(job_requests: :user).find(params[:id])
The first two work but the third crashes with the following error:
SQLException (no such column: users.job_request_id)
I know there is no such column I am looking for the details of the user that posted the request.
Model Association
User
has_many :jobs, dependent: :destroy
has_many :job_requests
Job
belongs_to :user
has_many :job_requests
JobRequest
has_one :user
has_one :job

In job_request.rb add the following association
belongs_to :user
belongs_to :job_request
belongs_to is used when you are storing foreign key of a particular model.
When has_one is used at that time you are not storing foreign key of another table.
Query should be
JobRequest.includes (:user, :job).where ('job_requests.job_id = ? and job_requests.user_id = ? ', params [:id], current_user.id)

For the following associations:
# User
has_many :jobs, dependent: :destroy
has_many :job_requests
# Job
belongs_to :user
has_many :job_requests
# JobRequest
belongs_to :user
belongs_to :job
Your query will be:
current_user.jobs.includes(job_requests: :user).find(params[:id])
belongs_to & has_one :
The only difference is what side of the relationship you are on. If a User has a Profile, then in the User model you need to have has_one :profile and in the Profile model you need to have belongs_to :user.
You can determine who has the other object by looking at where the foreign key is. You can say a User has a Profile because the profiles table has a user_id column. If there is a column called profile_id on the users table, we will say that a Profile has a User.
For further study you can read this article.

Related

How do I use class_name to link two specific columns

I have a model called Company, this model is used for both companies and clients, I know this is not the best approach for companies/clients but the software I'm working on was built that way and to change that, it would take months of job.
class Company < ActiveRecord::Base
has_many :companies
belongs_to :company
has_many :orders, dependent: :destroy
end
My other model is Orders, where the companies are linked by the company_id column and the customers by the customer_id column, that is, an order is linked to a company and a customer of that company.
class Order < ActiveRecord::Base
belongs_to :company
end
Currently, I created a method to get the customer but I would like to call a has_one to get the customer from the order, but I am not able to point the customer_id column of the order to the company id column using the rails class_name.
If I understand your question correctly (in the first para you mentioned clients and in the second you are saying customers so I am assuming clients == customers and customer is also a Company object) you are trying to do this:
class Order < ActiveRecord::Base
belongs_to :company
has_one :customer, class_name: 'Company'
end
which seems incorrect as it should be belongs_to:
class Order < ActiveRecord::Base
belongs_to :company
belongs_to :customer, class_name: 'Company'
end
This should work but you can also specify foreign_key:
belongs_to :customer, class_name: 'Company', foreign_key: :customer_id
From the docs: https://api.rubyonrails.org/v7.0.2.4/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_one
has_one specifies a one-to-one association with another class. This method should only be used if the other class contains the foreign key. If the current class contains the foreign key, then you should use belongs_to instead.

Understanding use of foreign_key and class_name in association

I am new to rails and this is a very basic question. I am trying to understand the need of foreign key and class_name.
has_many :task, foreign_key: "created_by"
has_many :memberships, class_name: "TaskMembership"
Can anyone explain the need of foreign_key & class_name.
Here is the answer of my question
Suppose you have a User model and Post model.And you have to set an association like User has many post
User Model
has_many :posts
Post Model
belongs_to :user
Now suppose your user is some author so we have to set some meaningful name so instead of user we will use author but have to specify which class it is referring
Post Model
belongs_to :author, class_name: 'User'
Now problem will occur because rails will look for author_id column in posts table .So here foreign key will come into picture.We will have to find user_id
Post Model
belongs_to :author, class_name: 'User', foreign_key: 'user_id'
See more better explanation association
has_many association is used for for one-to-many type relationships in rails. For instance, if you have a model User which can has many profiles, your User to Profile association will be has many.
class User < ActiveRecord::Base
has_many :profiles
end
class Profile < ActiveRecord::Base
belongs_to :user
end
If you have a foreign key different than user_id in profiles table, you explicitly specify foreign_key. Same is the case with class name. If your association name is different than actual model name, you explicitly specify class name after association (as you did for memberships).
Hope it helps.
in your model
class First < ActiveRecord::Base
has_many :seconds
end
class Second < ActiveRecord::Base
belongs_to :first
end
and in your second class table,create first_id column

User model with relationship table

I have two models User and UserRelation. The case is that User has several related users with himself(recommended by him), but he has only one person related_to(person who recommended him).
I would like to return from User object collection of recommended users and user who recommended him. I have written association for returning users collection and it works but I have no idea how should I write has_one association.
I get this error:
ActiveRecord::HasOneThroughCantAssociateThroughCollection: Cannot have a has_one :through association 'User#relation' where the :through association 'User#user_relations' is a collection. Specify a has_one or belongs_to association in the :through option instead
User model:
class User < ActiveRecord::Base
has_many :user_relations
has_many :related_users, through: :user_relations, source: :related_user
has_one :relation, through: :user_relations, source: :user
end
UserRelation model:
class UserRelation < ActiveRecord::Base
belongs_to :user
belongs_to :related_user, class_name: 'User'
end
UserRelation columns:
user_id
related_user_id
My choice would be to put a foreign key in your User table for the possible related_to field.
If the requirement is that it can only be one (or none) then why not?
You still keep the other "user_relations" for all other types. All the time in rails, we map to the same entity in different ways. It's not uncommon at all

Rails Associations - How to get and Object Instead of Integer

I have two models in Rails. One is for Users and one is for Jobs that can be owned by users. In the User model, I have a has_many association, and in the Jobs object I have a belongs_to association. Jobs have an owner column which is the user id of the owner (associated via a foreign key).
User: (id, name, email)
Class User < ActiveRecord::Base
has_many :jobs, dependent: :destroy, class_name: 'Job', foreign_key: :owner
end
Job: (id, owner, job_code)
Class Job < ActiveRecord::Base
belongs_to :user, class_name: 'User', foreign_key: :owner
end
This works fine in one direction: User.first.jobs will display a list of all of the Jobs that belong to that user. Unfortunately however, if I try to user Job.first.owner, I get simply the user's id integer, not a user object. What a I missing to be able to select the owner without having to re-query the database to get a user by ID?
1st Issue:
Don't use "object" as your model name, this keyword is already reserved.
Let's say you have got user model and job model, one user has got many jobs.
User (id, name, email) Job (id, job_code, owner)
here, the owner column holds the userID to which the job belongs to.
class User < ActiveRecord::Base
has_many :jobs, class_name: 'Job', foreign_key: 'owner'
end
class Job < ActiveRecord::Base
belongs_to :user , class_name: 'User', foreign_key: 'owner'
end
Now:
User.first.jobs #will give you first users jobs.
Job.first.user #will give you the owner info of the job
Hope it helps :)

rails belongs_to has_many please explain

I have following:
User model with columns:
id user_id password created_at updated_at
Store model with columns:
id store_id store_name create_ad updated_at
Basically a user can belong to multiple stores. So I would want to get a query like "get all the stores that the user belongs to"
Relationships I've made are:
class User < ActiveRecord::Base
belongs_to :store, :foreign_key => "store_id"
end
class Store < ActiveRecord::Base
has_many :user, :foreign_key => "store_id"
end
are these correct?
Ultimately I want to find out whether a userid, password and storeid should be able to login.
So how can I use the find_byXXX on this ? so If I get a row back with passed in userid, password and storeId...I would know whether user should be able to login?
I noticed that belongs_to and has_many questions have been asked before but I was not able to understand well from those questions. maybe answers specific to my problem will help...
You're looking for a has_and_belongs_to_many relationship. Your tables and model should be as follows:
User Table:
id password created_at updated_at
Store Table:
id store_name created_at updated_at
Join Table (called stores_users):
store_id user_id
In your models:
class User < ActiveRecord::Base
has_and_belongs_to_many :stores
end
class Store < ActiveRecord::Base
has_and_belongs_to_many :users
end
To get a user's stores:
User.stores
See the rails API for more information.
It seems like you're making a lot of false assumptions about how ActiveRecords works on a basic level, so I would recommend reading the official and very straightforward ActiveRecord Associations guide.
So you've said that a user belongs to many stores. How many users belong to a single store?
If the answer is more than 1, then what you need is has_and_belongs_to_many and a third database table. The table will essentially contain pairs of (store_id, user_id).
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
Although it is not required by Rails, it is recommended that you create a model for this relation and make the relation bidirectional on that model. You will thank yourself later.
class User < ActiveRecord::Base
has_many :userstores
has_many :stores, :through => :userstores
end
class Store < ActiveRecord::Base
has_many :userstores
has_many :users, :through => :userstores
end
class UserStore < ActiveRecord::Base
belongs_to :user
belongs_to :store
end

Resources