destroy belongs_to leaves FK - ruby-on-rails-3

I have a model:
class Merchant < ActiveRecord::Base
belongs_to :billing_address, class_name: Address, dependent: :destroy
belongs_to :other_address1, class_name: Address, dependent: :destroy
belongs_to :other_address2, class_name: Address, dependent: :destroy
belongs_to :other_address3, class_name: Address, dependent: :destroy
belongs_to :other_address4, class_name: Address, dependent: :destroy
...
end
Address has no associations.
When I do this:
merchant.billing_address.destroy
In the database, the address record is gone, but merchants.billing_address_id keeps a bogus value. This is mysql, so no referential integrity.
What am I doing wrong?
NOTE: I realize this might be better modeled as a has_one association. I might have to go there, but I prefer not to.
UPDATE: Added a little more code to show the multiple Address associations.

If you want merchant.billing_address to be null after you destroy the billing address, then you need to use :dependent => :nullify in the Address model.
Ref http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

It turns out that ActiveRecord does not support one-sided belongs_to associations, unlike other ORMs I've worked with. But you can hack it yourself like so:
before_save :remove_ids_for_nil_associations
def remove_ids_for_nil_associations
self.billing_address_id = nil if is_getting_destroyed? self.billing_address
...
end
def is_getting_destroyed?(ref)
ref.present? && ref.destroyed?
end

Related

Generic many-to-many polymorphic association using through?

Before ask that, I must say that I really searched the web trying to find the answer, but I didn't found any that solved my problem. Answers like that doesn't solve my problem, because I don't want specify source_type, I want a generic thing - you'll understand.
Okay, let's go. I'm using a "many-to-many polymorphic" relationship in my project, but I can't get it to work. Before try to use polymorphic, this was just a "many-to-many" relationship and worked very well, so I want keep the structure, just adding polymorphic.
Structure:
Many-to-many: A user and visitor has many subject, and vice versa. We assume that user and visitor are followers and subject is followed.
Relationship table: This objects have a relationship table called "psrelations" (person-subject relations). This table stores the many-to-many relationship.
Models:
psrelations.rb:
attr_accessible :followed_id, :follower_type, :follower_id
belongs_to :follower, polymorphic: true
belongs_to :followed, class_name: "Subject"
user.rb:
has_many :psrelations, as: :follower, dependent: :destroy
has_many :followed_subjects, through: :psrelations, source: :followed
visitor.rb:
has_many :psrelations, as: :follower, dependent: :destroy
has_many :followed_subjects, through: :psrelations, source: :followed
subject.rb
has_many :psrelations, as: :followed, dependent: :destroy
has_many :followers, through: :psrelations, source: :follower
I want that "followers" return all "visitors" and "users", not just one or other, like specifying source_type.
Everything appears to be okay, but when I try to self.followers.include?(person) (where person can be either user or visitor), I got:
Cannot have a has_many :through association 'Subject#followers' on the polymorphic object 'Follower#follower'.
What am I doing wrong?

Rails: NameError: uninitialized constant on join table

I can't seem to work around the name convention or if I'm joining them incorrectly.
This is the error I'm getting from the user model:
> user.companies
NameError: uninitialized constant User::CompaniesUser
And from the company model:
> company.users
NameError: uninitialized constant Company::CompaniesUser
user.rb
has_many :companies_users
has_many :companies, :through => :companies_users
company.rb
has_many :companies_users
has_many :users, :through => :companies_users
company_user.rb
class CompanyUser < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
I've been looking up through examples but I honestly don't understand why it keeps exploding. If there's any additional information needed, I'll provide it, I appreciate any help given.
Your association companies_users will be mapped to class named CompaniesUser by Rails because "companies_users".classify will give you CompaniesUser. But the class you want to associate is CompanyUser, so the solution in this case would be to modify your associations to include class_name option as follows:
# user.rb
has_many :companies_users, class_name: CompanyUser
has_many :companies, :through => :companies_users
# company.rb
has_many :companies_users, class_name: CompanyUser
has_many :users, :through => :companies_users
Update: This is of course if you want to stick with the association name companies_users, otherwise #Babur has a solution for you.
It should be:
has_many :company_users
has_many :companies, :through => :company_users
Only last word should be pluralized
Because of your has_many :companies_users in your Company model, Rails tried to load a model class for that table, that be convention would be called CompaniesUser. To make your code work, you could either change your has_many declaration to
has_many :company_users
or even get rid of the CompanyUser model completely and use has_and_belongs_to_many instead.
class User
has_and_belongs_to_many :companies
end
class Company
has_and_belongs_to_many :users
end

Is a has_many :through relationship the right way to model this data?

I have a Client model that needs each client instance to own and create multiple addresses, email_ids, phone_numbers. A simple has_many relationship would not allow me to scale I presume so I thought I should go for a has_many :through relationship
I want to use a has_many :through relationship
class Client < ActiveRecord::Base
has_one :profile
has_many :addresses, :through => :profile
has_many :emails, :through => :profile
has_many :phonenumbers, :through => :profile
end
class Profile < ActiveRecord::Base
belongs_to :client
has_many :addresses
has_many :emailids
has_many :phonenumbers
end
class Address < ActiveRecord::Base
belongs_to :profile
end
class EmailId < ActiveRecord::Base
belongs_to :profile
end
class PhoneNumber < ActiveRecord::Base
belongs_to :profile
end
Will I then be able to execute queries like:
client.phonenumbers client.create_phonenumbers etc?
Or should I just stick to has_many belongs_to and put address, email_id and phone_number in the profile relationship and then say client has_many profiles? That doesn't sound right to me. Are there any benefits to the rich association that I have outlined above?
I think it seems to be fine stick with the has_many :through. Because we don't need to put an extra relationship between client and other tables i.e addresses etc and also an extra column client_id in those tables. only putting profile id will do the same.

How to set up multiple aliased joins between two models?

In a Rails 3.2 app I need to set up two associations between the same two models.
For example
class User
has_many :events
has_many :attendances
has_many :attended_events, through: :attendances
end
class Event
belongs_to :event_organizer, class_name: "User"
has_many :attendances
has_many :attendees, through: :attendances, class_name: "User"
end
class Attendance
belongs_to :attended_event, class_name: "Event"
belongs_to :attendee, class_name: "User"
end
This is the first time I've experimented with aliasing class names, and I'm having trouble getting it to work. I'm not sure if the issue lies with how I've defined the associations, or elsewhere.
Do my associations look OK? Have I overlooked something needed to get this to work?
The problem I'm having is that no user ids are being set in the Attendance model. This may be a stupid question, but given my associations above, should the field name be :user_id or :event_organizer_id?
Really appreciate any suggestions on this. Thanks!
foreign_key to be specified in User and Event
class User
has_many :events
has_many :attendances, foreign_key: :attendee_id
has_many :attended_events, through: :attendances
end
class Event
belongs_to :event_organizer, class_name: "User"
# here it should be event_organizer_id
has_many :attendances, foreign_key: :attended_event_id
has_many :attendees, through: :attendances
end
class Attendance
belongs_to :attended_event, class_name: "Event"
# this should have attended_event_id
belongs_to :attendee, class_name: "User"
# this should have attendee_id because of 1st param to belongs_to here is "attendee"
# and same should be added as foreign_key in User model
# same follows for Event too
end

rails - what is the best/most efficient way to associate these models

In my application I have the following situation:
User belongs_to Group
Group has_many Users
Project belongs_to User
User has_many projects
The following is also true:
- Each Group will have one BaseCase
- Each Project will have multiple Scenarios and one BaseCase(depending on the Group the Project User belongs to)
- Scenario and BaseCase is the same type of object (let's call this Data)
- The default values for each Scenario are the BaseCase values for the Group, but the User can change these default values to create the specific Scenario
I am not sure how to capture all these relationships through associations efficiently, does anyone have any ideas? thanks
If I understand correctly, then something like that
class User
belongs_to :group
has_many :projects
end
class Group
has_many :users
has_many :projects, :through => :users
has_one :base_case
end
class Project
has_many :scenarios
has_one :base_case
belongs_to :user
has_one :group, :through => user
has_one :base_case, :through => :group
end
class Scenario
belongs_to :project
has_one :base_case, :through => :project
before_create do
self.attributes = self.base_case.attributes.except(:group_id, ...)
end
end
class BaseCase
belongs_to :group
end