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 :)
Related
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.
I am trying to figure out the best way to accomplish a relationship and having some trouble. I have come across a few articles that somewhat address what I am looking to do but not quite.
I have a Users model and a Tickets model. Both are joined through a UserTickets model so I am able to assign multiple Users to a ticket. What I would like to do is segment the Users assigned to a Ticket into requesters and agents. The Users model does not have any columns to declare if the user is a requester or agent, rather I have is_admin, is_customer, etc. I think what I need is along the lines of Ruby On Rails - many to many between the same table but not quite.
Ideally, I'd like to have my Tickets table take agent_id's (user_id from User class) and requester_id's (user_id from User class) rather than the general user_id's (user_id from User class which combines all the users into one group). I would assume would still allow me to call #current_user.tickets to pull all the tickets that are assigned to that user.
Here is my Users model:
has_many :user_tickets
has_many :support_tickets, through: :user_tickets
Here is my Tickets model:
has_many :user_tickets
has_many :users, through: :user_tickets
Here is my UserTickets join model:
belongs_to :user
belongs_to :support_ticket
Your help is greatly appreciated!
This is not a duplicate.
#Skylar,
1) If your goal is to assign multiple Users to a ticket? Because this doesn't require a many-to-many relationship. You just need to a one-many relationship and a boolean attribute agent? on User model. You can even create am Agent model that uses User model, if you like this better.
2) However, if you wanted to create a many-to-many relationship check out this. The Rails documentation is better than I write. See section 2.6 The has_and_belongs_to_many Association.
Solution to 1)
Models
class User < ApplicationRecord
has_many :tickets, class_name: :Ticket, foreign_key: :agent_id
def agent?
self.agent
end
end
class Agent < User
default_scope { where(agent: true) }
end
class Ticket < ApplicationRecord
belongs_to :user
belongs_to :agent, class_name: :User
end
Migrations
class CreateTickets < ActiveRecord::Migration[5.0]
def change
create_table :tickets do |t|
t.references :user, index: true
t.references :agent, index: true
t.string :event_name
t.timestamps
end
end
end
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
I need a little help... I have these relationships... Users belong to Department, a Department has a manager, Managers (Users) can have many managed departments.
I'm having one of those days and I can't for the life of me figure out what to put inside the User model to define the `has_many :managed_departments' part of the relationship.
Department
class Department < ActiveRecord::Base
has_many :users
belongs_to :manager, foreign_key: "manager_id", class_name: "User"
end
User
class User < ActiveRecord::Base
belongs_to :department
# has_many :managed_departments
end
This works: Department.last.manager which returns:
=> #<User id: 2, etc...
I'm having a mindblank on what to put in the User model.
Can anyone help?
You can use class_name option same like you used it in Department model
#user.rb
class User < ActiveRecord::Base
belongs_to :department
has_many :managed_departments, class_name: "Department", foreign_key: "manager_id"
end
You are not creating right association. You have many to many relation ship between user and department.
user has_many departments (Can manage multiple department)
department has_many users
As a database standard you should break many to many relationship and introduce a new intermediate table.
So your new table should be users_departments. In this table you can add column user is manager or not.
table should have column :
user_id , department_is, is_manager
class Department < ActiveRecord::Base
has_many :users, :through => :users_departments
end
class User < ActiveRecord::Base
has_many :departments, :through => :users_departments
end
class UsersDepartment < ActiveRecord::Base
belongs_to :user
belongs_to :department
end
Here you can find anything with association. and with simple scope you can find manager of department also.
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.