How to access the tables for has_many through association - ruby-on-rails

Say I have following association.
class Supplier < ActiveRecord::Base
has_one :account
has_one :account_history, through: :account
end
class Account < ActiveRecord::Base
belongs_to :supplier
has_one :account_history
end
class AccountHistory < ActiveRecord::Base
belongs_to :account
end
How can I access account table through supplier model
How can I access supplier table through account model
How can I access join table accounthistory without through other model
How can I add a field by migration to accounthistory and then get value from that field through supplier or account model

Surely this is too simplistic, but this what I'd propose:
1. #supplier.account
#supplier = Supplier.find(id)
#supplier.account #-> brings account data
2. #account.supplier
#account = Account.find(id)
#account.supplier #-> brings supplier data
3. #supplier.account_history
#supplier = Supplier.find(id)
#supplier.account_history #-> brings account_history
4. Migration
def change
add_column :account_histories, :your_column, :type, after: :column
end
You can deal with the join model / table directly (unlike HABTM's), meaning you will be able to create migrations as you wish. The above migration code shows how you can add a column to the table directly
Delegate
To access the data from that model, you're in luck
Because you're using a singular association (has_one / belongs_to), you should be able to delegate the call to another model:
#app/models/supplier.rb
Class Supplier < ActiveRecord::Base
has_one :account
has_one :account_history, through: :account
end
#app/models/account.rb
class Account < ActiveRecord::Base
belongs_to :supplier
has_one :account_history
delegate :extra, :vars, :here, to: :account_history
end
This will allow you to call: #supplier.account.extra etc
Hope this helps? Your question was rather scant on context, so I can fix my answer if you update!

Related

How to create a record when it depends on another record

I have 2 models, each of them depend on another.
class Company < ActiveRecord
belongs_to :user
end
class User < ActiveRecord
belongs_to :company
end
The company has a required user_id column.
The user has a required company_id column.
How can I create a company and user when they both depend on each other?
In your scenarion this relationship is called many to many relationship, You can create middle table between this called users_companies with foreign key of both table
For more details please refer this link Associations
Like example
class Company < ActiveRecord
has_many :users_companies, dependent: :destroy
has_many :users, through: users_companies
end
class User < ActiveRecord
has_many :users_companies, dependent: :destroy
has_many :companies, through: users_companies
end
class UsersCompany < ActiveRecord
belongs_to :user
belongs_to :company
# This model have two foreign key
user_id and company_id
end
Use a dummy value to fake one of the object is valid
company=Company.create(user_id: dummy)
user=User.new
user.company = company
user.save
company.update_attribute(user_id: user.id)

has_many and belongs_to with join table

I have Users and Trucks. I want the ability to say #truck.drivers << #users and #user.truck = #truck.
The solution is simple until I want the relationship to be stored in a join table.
# tables
:users
:id
:truck_drivers
:user_id
:truck_id
:truck
:id
I've gotten it to where I can say #truck.drivers << #user and #user.trucks << #truck, but I would like to limit a user to occupy one truck at a time, for my sanity.
Is it possible? A has_many/belongs_to with a join table? Or should I try a different approach? I'm not using a third model for the join table. It's just a table. Here's what I have so far.
class User < ApplicationRecord
has_and_belongs_to_many :trucks,
join_table: :truck_drivers, # points to the table
class_name: :Truck # looks for the truck model in the table
end
class Truck < ApplicationRecord
belongs_to :company
has_and_belongs_to_many :drivers,
join_table: :truck_drivers,
class_name: :User
end
The reason I need a join table in the first place is because each User can have many Roles: Admin, Manager, Driver, Customer Service, etc. I thought it didn't make sense to add a truck_id to all the users if all the users are not going to be using trucks.
It seems like you ought to be able to do something like:
#user.trucks << #truck unless #user.trucks.any?
Yes this is a standard strategy with rails using the :through keyword.
rails documentation: http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
Make a model called TruckUser with truck_id and user_id
then edit your classes:
class User < ApplicationRecord
has_many :truck_users
has_many :trucks, through: :truck_users
end
class Truck < ApplicationRecord
belongs_to :company
has_many :truck_users
has_many :drivers, through: :truck_users
end
class TruckUser < ApplicationRecord
belongs_to :truck
belongs_to :user
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.

Has_one and has_many relationship

I have two tables, registrations and discounts that hold information on a registration and a discount, respectively. Each registration can have one discount, and each discount can have many registrations.
I'm able to pull all of the registrations for a discount when I do something such as Discount.find(1).registrations, but when I attempt to call Registration.find(1).discount I get the error
Unknown column 'discounts.registration_id' in 'where clause': SELECT `discounts`.* FROM `discounts` WHERE `discounts`.`registration_id` = 1 ORDER BY `discounts`.`id` ASC LIMIT 1`
My models are currently set up as follows:
class Registration < ActiveRecord::Base
has_one :payment
has_one :discount
end
class Discount < ActiveRecord::Base
has_many :registrations
end
Additionally, my registration table has a foreign key discount_id.
I can make the association work if I set up a belongs_to relationship in the registrations model, but registrations don't belong to discounts - they may or may not have one.
How should I set up this relationship? Should I set up another table and use a has_many, through relationship?
Edit: I do not want to use a belongs_to relationship in my registration model, because a registration does not belong to a discount.
If a discount can have many registration then you want to use belongs_to instead of has_one
class Registration < ActiveRecord::Base
has_one :payment
belongs_to :discount
end
class Discount < ActiveRecord::Base
has_many :registrations
end
Check out this explanation of the difference between belongs_to and has_one
You should define your relationship like this:
class Registration < ActiveRecord::Base
has_one :payment
has_one :discountable
has_one :discount, through: :discountable
end
class Discount < ActiveRecord::Base
has_many :registration, through: :discountables
end
class Discountable < ActiveRecord::Base
belongs_to :registration
belongs_to :discount
end
Thanks

Rails ActiveRecord model association

I have a User model and a product model.
User has_many :products, :dependent => :destroy
Product belongs_to :user, :foreign_key => "user_id", touch: true
I want to create a wishlist for every user.
So i have to create a wishlist model with proper association.
But i don't know how to start.
I presume that the wishlist model contain an id, user_id and product_id field
Do i have to use has_many through association or a has_and_belongs_to_many ?
I also want that if a user is destroyed to destroy his wishlist.
What is the best way to do?
Many thanks!
As #JZ11 pointed out, you shouldn't be linking a Product directly to a User (unless a User actually 'owns' a product for some reason). However, what was missed is the model that makes up a Wishlist item:
class User < ActiveRecord::Base
has_many :wishlists # or has_one, depending on how many lists a User can have...
end
class Product < ActiveRecord::Base
has_many :wishlist_items
end
class Wishlist < ActiveRecord::Base
belongs_to :user
has_many :wishlist_items
has_many :products, :through => :wishlist_items
end
class WishlistItem < ActiveRecord::Base
belongs_to :product
belongs_to :wishlist
end
Naturally, you should be adding :dependent => :destroy where necessary.
You don't need the has_many :products relationship on User.
I don't think it makes sense for User and Product to be linked outside of a Wishlist.
class Wishlist < ActiveRecord::Base
has_many :products
belongs_to :user
end
class User < ActiveRecord::Base
has_one :wishlist, dependent: :destroy
end
class Product < ActiveRecord::Base
belongs_to :wishlist
end
To create your join table, do:
rails g migration create_products_users_table
Once you've done that, you need to add some code, below, to create the fields in the join table. Notice the :id => false, because you do not need an id in the join table:
class CreateProductsUsersTable < ActiveRecord::Migration
def change
create_table :products_users, :id => false do |t|
t.references :product
t.references :user
end
add_index :products_users, [:product_id, :user_id]
add_index :products_users, :user_id
end
end
The code above also creates some indexes and ensures that you don't have duplicates even at the database level.
Your models would then have to look like this:
class Product < ActiveRecord::Base
has_and_belongs_to_many :users
end
class User < ActiveRecord::Base
has_and_belongs_to_many :products
end
When you destroy a user correctly, like user.destroy and not just delete it (there is a difference), then the related rows in the join table will be deleted as well. This is built in to ActiveRecord.
Notice though, that doing this will not really let you use the join table. It will accept code like user.products = [product1, product2] etc, and other goodies, but no real use of a wish list.
If you do want to use a wish list, you will have to create and use the middle join table differently, using has_many :through (I didn't check PinnyM's answer but that might be the way to do it).

Resources