Check Before Destroy or Destroy all Associated? Rails 4 - validation

I currently have a Vendor Model which acts as sort of a router for my users. This Vendor Model links up to locations that the vendor owns and campaigns as well.
Once a user is created, it is given a Vendor association which basically unlocks the locations and campaigns that pertain to that given Vendor.
Now, my question is, is there a way that when a Vendor is "Destroyed" that is can destroy all associated locations, campaigns and users linked to it? If not, is there a way to run a validation that if a Vendor is being destroyed to check the database for associations and not allow the action of destroy if it finds records?
The reason I ask is because if I destroy the Vendor, it leaves the users without locations and campaigns without an associated Vendor which basically crashes my application.
User Model
belongs_to :vendor #user can only have one vendor
has_many :locations, :through => :vendor
has_many :clients, :through => :vendor
has_many :campaigns, :through => :vendor
Location Model
belongs_to :vendor
has_many :campaigns
Campaign Model
belongs_to :location
belongs_to :user
belongs_to :vendor
has_one :client
Vendor Model
has_many :locations #vendor can own many locations
has_many :clients #vendor can have many clients. Allows multiple employees to see client list
has_many :campaigns #vendor can have many campaigns. Allows multiple employees to see campaigns

In short you can do something like this by using the dependent option on your assoication. Can use either:
:destroy - destroys every associated object calling their destroy method.
:delete_all - deletes every associated object without calling their destroy method.
Update
Taking your models into consideration you should do the following:
class Vendor < ActiveRecord::Base
has_many :locations, dependent: :destroy
has_many :clients, dependent: :destroy
has_many :campaigns, dependent: :destroy
end
As stated above using the destroy option will destroy every associated object with that vendor.

Related

Reify only one has_many :through association with PaperTrail?

I'm using the paper_trail-association_tracking gem to save PaperTrail versions for AR associations. I have a model, let's call it User, that has many Groups and has many Skills. Both of these associations have join tables (user_groups and user_skills). So my User model has two has_many :through associations. All of the models (User, Group, Skill, UserSkill, UserGroup) have PaperTrail enabled on them.
class User < ApplicationRecord
has_paper_trail
has_many :groups, through: user_groups
has_many :user_groups
has_many :skills, through: user_skills
has_many :user_skills
end
Say I want to reify an earlier version of the User model, along with their Skills (user_skills records), but not revert to an earlier version of the user's Groups (user_groups). The code looks something like this:
me = User.find(1)
older_me = me.versions.last.reify(has_many: true)
older_me.save
This will reify both UserGroups and UserSkills for this User, but I want it to reify just UserSkills. It seems the gem will reify all associations automatically, based on this source code I looked through.
So is there a way to specify which association I want to be reified? Or is it not best practices to do this? For my use case, I can't see a problem with this unless the user itself was actually deleted or something like that.
Sorry my models here sound kinda weird, I tried to use something generic and simplified, my real use case and models are a bit complex but this question demonstrates the bottom line of my issue.

has_many or HABTM

This question has been asked numerous times but I can't project any of the answers to my specific situation, so here goes.
I have an events, options and a templates table. There is also a join table called events_templates with the fields:
option_id
template_id
event_id
An event has one template per option. But obviously can have many templates because there are multiple options.
Currently my event model has the method
has_many :templates, class_name: "EventsTemplate"
Question is, is this the right setup or should I use HABTM?
THANKS so much in advance!
I think you should set this up a bit different, based on the requirements you specified.
has_many :templates, class_name: "EventsTemplate"
This won't work the way you want it to. It will give event an association templates, but calling that association will return EventTemplates instead.
You probably want to set this up using a through association.
class EventTemplate < ActiveRecord::Base
belongs_to :option
belongs_to :template
belongs_to :event
end
class Event
has_many :event_templates
has_many :templates, through: :event_templates
end

Rails acts_as_paranoid and has_many :through

So I'm using the rails3_acts_as_paranoid gem, and having some problems controlling scope with has_many :through associations.
For example
# User.rb
acts_as_paranoid
has_many :folders
has_many :files, :through => :folders
-
# Folder.rb
acts_as_paranoid
belongs_to :user
has_many :files, :dependent => :destroy
-
# File.rb
acts_as_paranoid
belongs_to :files
Now lets just say somewhere in the users_controller.rb i want to query all files belonging to a user, whether they are deleted, and/or belong to folders that have been deleted. So naturally I would assume to do something like the following
current_user.files.with_deleted
with_deleted method does it's job at removing the files.deleted_at IS NULL
...BUT... it doesnt remove the default_scope for folders which is used kind of behind the curtain. So we still have a folders.deleted_at IS NULL condition, preventing me from retrieving the files that belong to those folders where deleted_at is not null.
I want to keep using acts_as_paranoid, as it is incredibly useful in all other places of my app, and am trying not to do something like manual filtering and popping out elements of the .where_values array. But I don't know too much about handling complex scopes or what methods are available.
Well my question got down-voted, not sure why. But I found the answer:
When on a has_many through, the problem I was having was an inability to control the scope of the through model (Folders in this case).
Turns out you can just do this
#myvar = Folder.unscoped { current_user.files.with_deleted }
To whoever downvoted it - I'd like to know why, so I can ask better questions next time. Thanks!

Rails 3.2 association methods crashes server & console

I am trying to upgrade a Rails 2.3.5 application to Rails 3.2.1. I know I should have done 3.0 and 3.1 first. However...
I'm experiencing a very strange problem when I try to access an associated model through an auto generated accessor method. For instance, I have User and Member models where User has one member and Member belongs to User. Calling User.first.member will crash the webrick server with no error message. The same happens in the console with the following output.
irb(main):003:0> User.first.member
←[1m←[36mUser Load (0.0ms)←[0m ←[1mSELECT `users`.* FROM `users` LIMIT 1←[0m
C:\git\web_benebridge\website>rails c
Both objects do exist in the database and are linked correctly and this works fine in Rails 2.3.5.
The User model is defined thus:
class User < ActiveRecord::Base
require 'digest/sha2'
belongs_to :association
has_one :member
...
And the Member model like this:
class Member < ActiveRecord::Base
belongs_to :user
belongs_to :association
...
The Association model shown above starts its definition like:
class Association < ActiveRecord::Base
has_many :association_benefits
has_many :association_kases
has_many :benefits
has_many :contacts
has_many :content_items
has_many :members
has_many :users
...
I've tried various other models that have associations and some of the association accessor methods work but others do not. It's really bothersome that there is no error thrown at all, the environment just exits.
One concern I have is that having a model named Association may be confusing things. Has anyone else run into a problem with this in the later versions of Rails?
Any help resolving this will be greatly appreciated.

Uninitialized constant error: Can't get this has_many :through correct

I have been around and around with this. Have seen similar questions here but it seems I have an extra complicating factor; what worked for them doesn't work for me.
I have models and tables for User, Group, GroupMember. A group is owned by a user, but each group can have an arbitrary number of group members, i.e., other users. Here are my associations:
In User,
has_many :groups
In Group,
belongs_to :user
has_many :group_members
has_many :members, :class_name => "User", :through=>:group_members
In GroupMember,
belongs_to :member, :class_name=>"User"
belongs_to :group
To get at the members of a group, then, in groups_controller.rb I do this:
#groupmembers = #group.group_members.all
However, that generates the following error:
NameError in GroupsController#show
uninitialized constant Group::GroupMember
Like I say, I have been around and around with this... where have I gone wrong? Thanks in advance for looking...
I finally got this working on my own. The part I was missing was in the User class; since User is the underlying class of Member, I needed this:
belongs_to :groupmember, :foreign_key=>"member_id"
Once that was in place, Rails was able to find everything as it should, e.g,
Group.find(1).members now finds all users who belong to the group with an ID of 1.
Assuming you have a model called GroupMembers (which you should given this is a has_many through association), your non-through association should look like this on both the Group and Member models:
has_many :group_members, :class_name => "GroupMembers"
For some reason rails isn't pluralizing the second model in the association, so just do it yourself.
Sometimes it can also be as simple as the belongs_to :model needs to be singular instead of plural. I made this mistake on my relationship today.

Resources