Custom association for Rails models - ruby-on-rails

I'm trying to define a relation between 2 models Customer and CustomerProduct, linking customer.custom_id on customerproduct.customer_id so that mycustomer.customer_products.create() ends up with customerproduct.customer_id = customer.custom_id instead of customer.id.
This is my Customer model:
class Customer < ActiveRecord::Base
belongs_to :organisation
has_many :customer_products, foreign_key: 'customer_id'
end
And my CustomerProduct model:
class CustomerProduct < ActiveRecord::Base
belongs_to :customer
end
I'm not sure how to define the custom_id bit - I tried adding it as a foreign key in belongs_to :customer but this doesn't seem to do anything - Rails still takes customer.id.
Thanks in advance!

Let's just say the answer was quite obvious so I must have been blind!
has_many :customer_products, primary_key: 'custom_id', foreign_key: 'customer_id'

Related

how to connect two table that has no relation in rails

I have a table called foods and categories, but this table has no relation, I want to connect them through another table called food_category. And I want to make one-to-one relation between food and category maybe the diagram looks like this
class Food < ApplicationRecord
has_one :category
end
class Category < ApplicationRecord
has_one :food
end
class FoodCategory < ApplicationRecord
belongs_to :category
belongs_to :food
end
Is it possible to do this?
Yes, this is possible. You just need to do
has_one :category, through: :food_categories
as discussed in the Rails docs here.
However, this is a long-winded way to go about this kind of association. If it's going to be one-to-one, why not just add a foreign key to Category from Food? And presumably, you would actually want Category to contain many Food records? Seems like the below would make more sense:
class Food < ApplicationRecord
belongs_to :category
end
class Category < ApplicationRecord
has_many :food
end
class Food < ApplicationRecord
has_one :food_category
has_one :category, through: :food_categories
end
In rails console, you can access like this
Food.find(:id).categories

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.

Using foreign_key in rails associations has_many

Could somebody explain me is my code correct.
I'm trying to get foreign_key option in rails associations.
I have 2 models:
Book and Author
Book db schema:
name
user_id
Author db schema:
name
My models:
class Author < ApplicationRecord
has_many :books, foreign_key: :user_id
end
class Book < ApplicationRecord
belongs_to :author, foreign_key: :user_id
end
Here I don't understand why we should define foreign_key in both models. Is it necessarily?
If you have used the table and column names that Rails expects, then you do not need to explicitly define the foreign_key. In your case, if the foreign key column was named author_id, then you could get by quite simply:
class Author < ApplicationRecord
has_many :books
end
class Book < ApplicationRecord
belongs_to :author
end
However, in your case, the foreign key column is not named according to what Rails expects, so you have needed to explicitly define the foreign key column name. That's fine, but it does make a little more work for you.
In cases where you have explicitly defined the foreign key, you should define it for both associations. Your has_many association will not work without it.
In addition, you should define the inverse association:
class Author < ApplicationRecord
has_many :books, foreign_key: :user_id, inverse_of: :author
end
class Book < ApplicationRecord
belongs_to :author, foreign_key: :user_id, inverse_of: :books
end
Defining the inverse_of can cause ActiveRecord to make fewer queries, and gets rid of a few surprise behaviors. For an explanation of inverse_of, see Exploring the :inverse_of Option on Rails Model Associations by Ryan Stenberg

Should I use the foreign_key clause both in has_many as in belongs_to?

I have two models. Office and Employee. Employee has office_id as foreign_key. The tables was generated under a namespace. So, which is the correct?
class MyNamespace::Office < ActiveRecord::Base
has_many :employees, foreign_key: 'office_id'
end
class MyNamespace::Employee < ActiveRecord::Base
belongs_to :office, foreign_key: 'office_id'
end
Or
class MyNamespace::Office < ActiveRecord::Base
has_many :employees
end
class MyNamespace::Employee < ActiveRecord::Base
belongs_to :office, foreign_key: 'office_id'
end
I think the second example is the correct, because to me, doesn't makes sense declare the foreign_key in a has_many relation. A coworker thinks the first example is the correct. But I haven't found too many references to this subject. So, does Anybody know which is the correct example and why?
You can specify prefixes for proper mapping to table names in DB and remove foreign_keys and MyNamespace at all.
class Office < ActiveRecord::Base
self.table_name_prefix = 'namespace_'
has_many :employees
end
class Employee < ActiveRecord::Base
self.table_name_prefix = 'namespace_'
belongs_to :office
end

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