How do I use class_name to link two specific columns - ruby-on-rails

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.

Related

Rails - Has many on model with multiple references

I have a model CompanyIntro which has two references to a Company:
class CompanyIntro < ApplicationRecord
belongs_to :company_one, class_name: "Company", foreign_key: "company_one_id"
belongs_to :company_two, class_name: "Company", foreign_key: "company_two_id"
...
I would like to do something like:
class Company < ApplicationRecord
has_many :company_intros, class_name: 'CompanyIntro', foreign_key: 'company_one_id'
has_many :company_intros, class_name: 'CompanyIntro', foreign_key: 'company_two_id'
...
But this is not valid
In my Company model, how to I create a has_many for both foreign keys? I am using Rails 6 which dos not allow custom sql for has_many (afaik). I also do not want to write a custom company_intros method on the Company model as I'm using another gem which looks for my has_many relationships.
You can't define has_many assocations where the foreign key is one of two columns. Its just not supported by ActiveRecord as the feature would add tons of complexity.
Using the same name for two assocations also just overwrites the previous assocation. If you want to have a single assocation here you need to add a join table.
class Company < ApplicationRecord
has_many :company_intro_participations
has_many :company_intros, through: :company_intro_participations
end
# for lack of a better name
class CompanyIntroParticipation < ApplicationRecord
belongs_to :company
belongs_to :company_intro
end
class CompanyIntro < ApplicationRecord
has_many :company_intro_participations
has_many :companies, through: :company_intro_participations
end
The alternative is creating a method which joins on company_one_id = companies.id OR company_two_id = companies.id but you will not be able to use that in the same way as an association when it comes to stuff like eager loading.

Rails Populate Existing Join Table

So I have two tables, a Customers table and a Companies table. I have also created an empty Employees table that I would like to use as a join table.
These are the associations I have: (I want customers to be associated with their respective company)
class Company < ApplicationRecord
has_many :employees
has_many :customers, :through => :employees
end
class Customer < ApplicationRecord
belongs_to :employees
end
class Employee < ApplicationRecord
belongs_to :customer
belongs_to :company
end
Where would be the best way to do this? In my Customer#new method in the controller? I read that I need to use <<, but I don't know how to approach that.
You need to use the concept of Inverse association here:
class Customer has_many :companies, :through => :employees
You could just try delegating the company call on customers to their employee:
customer.rb
delegate :company, to: :employee
Now whenever you ask a customer its company, it will ask its employee to handle it.

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

Rails belongs_to and has_many foreign_key relationship

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.

How to create a Rent in Rails

I am tryng to develop a rent system where a user can login, create products, and his products can be rented by other users.
My problem is, I don't know how to create a rent that retrieves the product_id and customer_id. I made the relations but it isn't working.
I also create the CRUD for each one, even the rent. How can I store the information and pass to the Rent?
I have 4 models:
User
Product
Rent
Category
I created a new column in Rent called customer_id, and I've passed the class "User":
class Product < ActiveRecord::Base
belongs_to :user
belongs_to :category
belongs_to :rents
class User < ActiveRecord::Base
has_many :products
has_many :rents
has_many :customer_id, :through => :rent
class Rent < ActiveRecord::Base
belongs_to :user
belongs_to :product
belongs_to :customer, :class_name => "User"
end
I think I need to create a button that retrieves the information that I need. I searched through the documentation but I couldn't find it.
This line: has_many :customer_id, :through => :rent would never make sense this way in Rails. If you say has_many :customer_id, you are making two mistakes:
Whatever you write after has_many, it should be plural.
If what you write after has_many doesn't correspond directly to a model name as this the case with you, you have to explicit mention the class_name.
Same mistake you are repeating when you say:
class Product < ActiveRecord::Base
belongs_to :rents # it should be rent.
end
And now coming to what you are actually trying to implement:
class Rent < ActiveRecord::Base
belongs_to :user
has_one :product
has_one :customer
end
And in Product and Customer tables, you need to define rent_id as a foreign key. And you should also mention that each of them belongs_to Rent.

Resources