Rails 4: has_many :through errors - ruby-on-rails

Here is my join model:
class CompanyUser < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
My User model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
ROLES = %w[admin requestor requestor_limited shipping_vendor].freeze
attr_accessor :temp_password
has_many :companies_users
...
end
If I run this in the console:
u = User.first
u.companies
This is the error I am getting:
NameError: uninitialized constant User::CompaniesUser

has_many through relationships should be like this:
In app/models/company.rb file,
has_many :company_users
has_many :users, :through => :company_users
In app/models/user.rb file,
has_many :company_users
has_many :companies, :through => :company_users
In app/models/company_user.rb file,
belongs_to :company
belongs_to :user
If you want to delete the dependent records in company_users table when deleting companies/users,
Add, , :dependent => :destroy at the end of has_many relations in Company and User model.
Hope this helps you..
Thanks.!!

it must be
has_many :company_users
"CompanyUser".tableize => "company_users"

The model shall be either:
class CompaniesUser < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
Or has_many declaration sheel be defined explicitly as:
class User < ActiveRecord::Base
has_many :company_users
end

Related

Querying for values from several models

I have a Course and Lesson models. Course has several lessons. I want to find all the lessons for currently logged in student to generate kind of timetable.
I have a method that returns all the courses that this student is studying. Now I want to get all lessons from all those courses in #courses into #lessons, something like:
def index
#courses = current_student.find_courses
#lessons = #courses.lessons
end
Is it possible to do it somehow simple on one line?
The find_courses method is implemented as following:
def find_courses
Course.where("id IN (?)", StudentAssignment.select("course_id").where('student_id == (?)', self.id))
end
The Models:
class Student < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :student_assignments
has_many :courses, :through => :student_assignments
....
class Lesson < ApplicationRecord
belongs_to :room
belongs_to :teacher
belongs_to :course
....
class Course < ApplicationRecord
has_many :lessons, dependent: :destroy
has_many :teacher_assignments
has_many :teachers, :through => :teacher_assignments
has_many :student_assignments
has_many :students, :through => :student_assignments
...
class Student < ApplicationRecord
has_many :courses
def active_lessions
Lession.joins(course: :students).where(students: {id: self.id})
end
end
In this way you can directly get all active lesssions for current_user
current_student.active_lessions
Try:
#lessons = #courses.flat_map(&:lessons)
It takes each course in #courses list and gets the list of lessons for that course.

User has_many association not working (error:Could not find the association :user_categories in model Category)

I have three models and here they are when I try to create a has_many. I basically want my users (using devise) to have many categories. And categories to have many users.
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable
has_many :user_categories
has_many :categories, through: :user_categories
acts_as_messageable
def mailboxer_email(object)
email
end
end
userCategory.rb
class UserCategory < ActiveRecord::Base
belongs_to :user
belongs_to :category
accepts_nested_attributes_for :categories
end
Category.rb
class Category < ActiveRecord::Base
has_many :user_categories
has_many :user, through: :user_categories
validates :name, presence: true, length: {minimum: 3, maximum: 25}
validates_uniqueness_of :name
end
when I run category.users << user I get this error:
ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :user_categories in model Category
I can't say for sure what the problem could be, but a few things I could point out:
UserCategory's accepts_nested_attributes_for, does that mean the you want to be able to dynamically create categories?
Category has_many :users, through: :user_categories, not user
You need to follow the Rails file naming conventions, user.rb, user_category.rb and category.rb
These may not be the problem/solution, but I believe they're in the way of resolving the problem.

Audited-activerecord gem not working properly for polymorphic associations

I want to make audits for nested associations like I have
User has_many addresses i.e either
HomeAddress or OfficeAddress
Now if I have just one table Address and I have used type and id for differentiating them.In this case if I use associated_audits for User then it will make just one audit record and whenever I update the record again ,its just replacing the previous audit with the last one.
Here is the models association:
class Patient < ActiveRecord::Base
devise :database_authenticatable, :registerable, :recoverable, :rememberable,
:trackable, :validatable, :confirmable, request_keys: [:subdomain]
has_one :home_address,-> { where(addr_type: 'home') },class_name: 'Address'
has_one :office_address,-> { where(addr_type: 'office') }, class_name: 'Address'
has_associated_audits
accepts_nested_attributes_for :home_address, allow_destroy: true
accepts_nested_attributes_for :office_address, allow_destroy: true
end
class Address < ActiveRecord::Base
belongs_to :patient
audited
end
class Address < ActiveRecord::Base
belongs_to :patient
audited associated_with: :patient
end
class Patient < ActiveRecord::Base
has_many :addresses
has_associated_audits
end

2 references to same model without has_and_belongs_to_many

class Message < ActiveRecord::Base
belongs_to :conversation
belongs_to :user
end
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :conversations
has_many :conversations, class_name: "Conversation", foreign_key: :user2_id
end
class Conversation < ActiveRecord::Base
belongs_to :user
belongs_to :user2, class_name: "User", foreign_key: :user2_id
has_many :messages
end
spec:
require 'rails_helper'
RSpec.describe Message, type: :model do
it "should be available to 2 users" do
u = User.create(email: 'x#y.com', password: '8888888888')
u2 = User.create(email: 'z#w.com', password: '8888888888')
c = Conversation.create(user_id: u.id, user2_id: u2.id)
expect(u2.conversations.count).to eq 1
expect(u.conversations.count).to eq 1
end
end
It's this line:
expect(u.conversations.count).to eq 1
that fails.
Presumably because of my second has_many
But if I remove it, then expect(u2.conversations.count).to eq 1 fails.
Yes, I explicitly want only 2 users in a conversation. I was trying to avoid doing HABTM.
How do I make this work?
has_many :conversations
has_many :conversations, class_name: "Conversation", foreign_key: :user2_id
You can only have 1 has_many of a set name. Your first has_many is being overwritten by the second as the ruby class loads. I can't think of a better name but you should name one of them different, maybe something to demonstrate the person initiating the conversation.
You could use a has_many :through with a join model. Here is an explanation of how to set that up: http://www.tweetegy.com/2011/02/setting-join-table-attribute-has_many-through-association-in-rails-activerecord/.

What is <ActiveRecord::Associations::CollectionProxy []>?

I have these models:
class Item < ActiveRecord::Base
has_many :item_categoryships
has_many :categories, class_name: 'ItemCategoryship', foreign_key: 'category_id', :through => :item_categoryships
belongs_to :user
validates :title, presence: true
end
class Category < ActiveRecord::Base
has_many :item_categoryships
has_many :items, :through => :item_categoryships
belongs_to :user
validates :name, presence: true
end
class ItemCategoryship < ActiveRecord::Base
belongs_to :item
belongs_to :category
validates :item_id, presence: true
validates :category_id, presence: true
end
class User < ActiveRecord::Base
has_many :items
has_many :categories, class_name: 'Category'
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable, :async
end
But I found when I call item.categories will get a empty array !!! I have checked database, there is a record here.
When I test in the rails console, I didn't get any record back, just saw 'ActiveRecord::Associations::CollectionProxy []'.
What is this? I am using Rails 4.0.2.
Thanks you all.
ActiveRecord::Associations::CollectionProxy is ActiveRecord class for collection associations. Now, your code should work if you change line in Item class describing categories association to:
has_many :categories, through: :item_categoryships

Resources