more than one entry saved on has_one association rails - ruby-on-rails

I am trying to create a has_one association among two model.
class User < ActiveRecord::Base
has_one :emergency_contact
end
class EmergencyContact < ActiveRecord::Base
belongs_to :user
end
when i try to test it through rails console more than one entries are saved for the emergency contact model for a single user. Although when i retrieve it using User.emergency_contact only the first entry is returned. When saving how can i make it to rollback for more than one entry

You can simply validate uniqueness of user_id column in EmergencyContact:
class EmergencyContact < ActiveRecord::Base
belongs_to :user
validates_uniqueness_of :user_id, allow_nil: true
end

Related

has_one model association not enforcing 'one' in associated model?

I have the following
class User < ApplicationRecord
has_one :physician
end
and
class Physician < ApplicationRecord
belongs_to :user
end
Since a user can only have one physician, I was surprised that multiple physician records can be created with the same user id.
Why is this? And how to I prevent it?
A belongs_to association does not in any way guarantee that the values are unique. It only stipulates that the association is stored in a foreign key on this models table and thus can only have a single value.
has_one doesn't actually provide any guarantees either. It just specifies that this table is referred to on the other table. If there are multiple matching rows on the other table it will chose the last.
If you want to enforce uniqueness per table you need a validation:
class Physician < ApplicationRecord
belongs_to :user
validates_uniqueness_of :user_id
end
And a database index to actually guarantee uniqueness on the database level:
class AddUniqueIndexToPhysicians < ActiveRecord::Migration[6.0]
def change
add_index :physicians, :user_id, unique: true
end
end
Physician probably shouldn't have a user_id associated to it:
class User
belongs_to :physician # has a physician_id column
end
class Physician
has_many :users # has no mention of user_id in its schema
end
belongs_to is required by default for Rails 5 and later. If users can onboard without a physician and you need to disable this:
class User
belongs_to :physician, optional: true
end
And then later, validate the presence of physician only after some condition.

How to validate has_one relationship?

I have these two models
User.rb
has_one :bike
Bike.rb
belongs_to :user
If a user tries to create multiple bikes, then the has_one relation doesn't make sense.
How can I add validation for this condition in the model level?
How can I make sure that the user will be always having one bike?
Create a before_create callback in bike.rb file. Check if the current_user.bike has any record or not. If record exists then add an error and return.
class Bike < ApplicationRecord
# Associations
has_one :user
before_create :user_exists
private
def user_exists
if self.user.bike.present?
errors[:base] << "Add your validation message here"
return false
end
end
end
You can simply add a validates_uniqueness_of call on your Bike model.
class Bike < ApplicationRecord
belongs_to :user
validates_uniqueness_of :user_id
end

Rails, validate has_many through association with attribute value of children

I have three models:
class User < ApplicationRecord
has_many :game_accounts
has_many :favorite_game_accounts, through: :game_account_favorites, source: :game_account
end
class GameAccount < ApplicationRecord
belongs_to :user
has_many :favorite_users, through: :game_account_favorites, source: :user
end
class GameAccountFavorite < ApplicationRecord
belongs_to :user
belongs_to :game_account
validates_presence_of :user, :game_account
validates_uniqueness_of :user, scope: :game_account_id
end
This means that User can have his own GameAccounts and other Users can add them to favorites.
I have added scope in order to prevent one user to have multiple favorites of the same GameAccount. However, there is one problem. User can add to favorite his own GameAccount. How to prevent user adding his own GameAccount to favorites?
I'm not sure that there is any built-in Rails validation for you case, so I'd suggest writing your own custom one.
In your particular case, you can verify on GameAccountFavorite instance, that game_account.user_id isn't equal to user.id.
There's plenty of ways of performing custom validation in Rails

Multiple associations query - DB Modelling

I am planning a rails apps that allows a User to list one/many Vaults, at either their personal address or any other additional address (location) specified against a vault. Before I go ahead and generate the Models I want to make sure I understand what associations need to be set up between the three Models. Here the code representation that I have typed manually to depict what associations are required.
class User < ActiveRecord::Base
has_many :vaults
end
class Vault < ActiveRecord::Base
belongs_to :user
has_one :address
end
class Address < ActiveRecord::Base
belongs_to :user
end
Your database looks okay, few consideration are below :
class User < ActiveRecord::Base
has_many :vaults
has_many :addresses #(optional)if you want to fetch addresses directly
end
class Vault < ActiveRecord::Base
belongs_to :user
has_one :address
end
class Address < ActiveRecord::Base
belongs_to :user #(optional) if you want to fetch user directly
belongs_to :vault
end
Database requirement:
adresses table must contain user_id(optional) and vault_id.
vaults table must contain user_id.

How to access the tables for has_many through association

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!

Resources