rails polymorphic many-to-many association - ruby-on-rails

I have these models:
class Company < ActiveRecord::Base
has_many :categorizings, as: :categorizable
has_many :categories, :through => :categorizings
class Categorizing < ActiveRecord::Base
belongs_to :category
belongs_to :categorizable, polymorphic: true
class Category < ActiveRecord::Base
has_many :categorizings
has_many :categorizables, through: :categorizings
How can I get all the companies having a specific category?
I tried
Category.find_by_name("fff").companies
plus a lot of other solutions but couldn't get it working
Thx!

You could do the following
Category.first.categorizables.where(categorizable_type: 'Company')
that would select all the Companies associated with Category using your relationship schema.
Also read some about has_many :through association because I think you don't quite get it http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

Related

Is this database relation schema correct?

I made my first project and got into problem that I couldn't get the right category_information values for specific competitions category through relations. So I started thinking that this could be the wrong schema for this task, so my question - is it actually wrong?
Current Scheme:
Assuming the following relationships between models from your image.
class Competition < ApplicationRecord
has_many :categories
has_many :informations
has_many :category_informations, through: :categories
end
class Category < ApplicationRecord
belongs_to :competetion
has_many :category_informations
has_many :information, through: :category_informations
end
class CategoryInformation
belongs_to :catagory
belongs_to :information
end
class Information < ApplicationRecord
belongs_to :competetion
has_many :category_informations
has_many :catagory, through: :category_information
end
Model can relates with one_to_many_to_many using :through option
It explains a association used to set up a many-to-many connection with another model.
you can get the category_informations from competition like
Competition.first.category_informations
It is all for doing! Pretty good, right?
And you could do get information from category too
Category.first.informations
Actually wrong schema doesn't exist, just there exists some wrong association description.
You can get more usage to use association from docs at 2.3 section and 4.3 section
Assuming the following relationships between tables,
A competition has_many categories,
A competition has_many information,
A category has_many information,
A category has_many competition,
An information has_many category
You can use has_many_through relationships
class Category < ApplicationRecord
has_many :category_competitions
has_many :competitions, through: :category_competition
has_many :category_informations
has_many :informations, through: :category_informations
end
class Information < ApplicationRecord
has_many :category_informations
has_many :categories, through: :category_informations
end
class Competition < ApplicationRecord
has_many :category_competition
has_many :categories, through: :category_competitions
end
class CategoryCompetition < ApplicationRecord
belongs_to :category
belongs_to :information
end
class CategoryInformation < ApplicationRecord
belongs_to :category
belongs_to :information
end
By this way you can access,Categories of a particular competition by #competition.categories
This article might be helpful for you to understand associations better
https://www.sitepoint.com/master-many-to-many-associations-with-activerecord/

Can the joins table created by a has_many :through relation also have a has_many relation?

The model created by the has_many through relation would look like this:
class MerchantOrder < ActiveRecord::Base
belongs_to :order
belongs_to :user
has_many :products
end
But I am not sure if this is possible. Any reason why this wouldn't work?

Rails 4 has_many :through association with :source

I was following the answer laid out at the link below to set up a many_to_many relationships on my Rails 4 app. (New to rails, here.)
Implement "Add to favorites" in Rails 3 & 4
I have Users and Exercises, and I want users to be able to have Favorite Exercises. I created a join table called FavoriteExercise with user_id and exercise_id as columns. I've got it populating, and it seems to be working fine, but I'm not able to use it to call directly to my favorites. 
Meaning, I want to type:
user.favorite = #list of exercises that have been favorited
I get this error when I try to load that list in my browser:
SQLite3::SQLException: no such column: exercises.favorite_exercise_id:
SELECT "exercises".* FROM "exercises" INNER JOIN "favorite_exercises"
ON "exercises"."favorite_exercise_id" = "favorite_exercises"."id"
WHERE > "favorite_exercises"."user_id" = ?
My models:
class User < ActiveRecord::Base
has_many :workouts
has_many :exercises
has_many :favorite_exercises
has_many :favorites, through: :favorite_exercises, source: :exercises
class Exercise < ActiveRecord::Base
belongs_to :user
has_many :workouts, :through => :exercises_workouts
has_many :favorites
has_many :favorited_by, through: :favorite_exercises, source: :exercises
class FavoriteExercise < ActiveRecord::Base
has_many :exercises
has_many :users
I just tried switching FavoriteExercise to 'belongs_to' instead of 'has_many, because it seems maybe that's the way that should go? but then I get this error:
uninitialized constant User::Exercises
Just trying to figure out how to set up the tables and associations so I can call .favorites on a user and get all their favorites.
If you want the list of exercises of the user and at the same, the list of favorite exercise of the user, then I think your join table should just be users_exercises wherein it will list all the exercises by the users. To list the favorite exercises, just add a boolean field indicating if the exercise is a user favorite and add a :scope to get all the favorite exercises.
So in your migration file:
users_exercises should have user_id, exercise_id, is_favorite
Then in your model:
class User < ActiveRecord::Base
has_many :workouts
has_many :users_exercises
has_many :exercises, through: :users_exercises
scope :favorite_exercises, -> {
joins(:users_exercises).
where("users_exercises.is_favorite = ?", true)
}
class Exercise < ActiveRecord::Base
has_many :workouts, :through => :exercises_workouts
has_many :users_exercises
has_many :users, through: :users_exercises
class UsersExercise < ActiveRecord::Base
belongs_to :exercise
belongs_to :user
You just need to simplify your model logic as follow:
class User < ActiveRecord::Base
has_many :workouts
has_many :exercises
has_many :favorite_exercises
has_many :favorites, through: :favorite_exercises, class_name: "Exercise"
class Exercise < ActiveRecord::Base
belongs_to :user
has_many :workouts, :through => :exercises_workouts
has_many :favorite_exercises
has_many :favorited_by, through: :favorite_exercises, class_name: "User"
class FavoriteExercise < ActiveRecord::Base
belongs_to :favorited_by
belongs_to :favorite
Then you can call user.excercises or excercise.users in your User/Excercise instance.
user.excercises = #list of exercises that have been favorited
Is that the many-to-many relationship you want?

How to set up associations in Ruby on Rails?

I'm building a sample app for practice and am having trouble determining the best way to organize my models and associations. So let's just say I have 3 models:
Schools
Classes
Students
I want:
schools to have many classes
classes to have many students
classes to belong to a school
students to be enrolled in many classes in many different schools
The associations are making me dizzy, I'm not sure which ones to use. Help would be greatly appreciated.
Renamed class to course, as the class name Class is already taken. A join class such as enrollments would handle your many to many course <=> student relationship.
class School
has_many :courses
end
class Course
belongs_to :school
has_many :enrollments
has_many :students, :through => :enrollments
end
class Student
has_many :enrollments
has_many :courses, :through => :enrollments
end
class Enrollment
belongs_to :course
belongs_to :student
end
Your models should looks like this:
class School < ActiveRecord::Base
has_many :classes
has_many :students, :through => :classes
end
class Class < ActiveRecord::Base
belongs_to :school
has_and_belongs_to_many :students
end
class Student < ActiveRecord::Base
has_and_belongs_to_many :classes
end
Make sure your Student and Class tables have class_id and school_id columns respectively.
Also, Class is a reserved word in Rails, so it might cause problems (you might have to use a different name)
Though on first blush it would seem students should belong directly to class, class isn't really a true "has_and_belongs_to_many" replacement. For that I would use "enrollment". (Note with rails 3.1 you can now do nested :through calls.)
Here's a slightly more advanced implementation than the previous commenter's:
class School << ActiveRecord::Base
has_many :academic_classes
has_many :enrollments, :through => :academic_classes
has_many :students, :through => :enrollments, :uniq => true
end
class AcademicClass << ActiveRecord::Base
belongs_to :school
has_many :enrollments
end
class Enrollment << ActiveRecord::Base
belongs_to :academic_class
belongs_to :student
end
class Student << ActiveRecord::Base
has_many :enrollments
has_many :academic_classes, :through => :enrollments
has_many :schools, :through => :academic_classes, :uniq => true
end

rails3 has_and_belongs_to_many customization

Book has_and_belongs_to_many Students
Student has_and_belongs_to_many Books
In BooksStudents model I want to add "status" field to store if it is rented, bought ..etc. and be able to select for example #student.books.rented or #student.books.where(:books_students=>{:status=>2})
Can I do that with HABTM?
AFAIK no, you will need a has_many :through setup..
class Book < ActiveRecord::Base
has_many :books_students
has_many :students, :through => :books_students
end
class BooksStudent < ActiveRecord::Base
belongs_to :book
belongs_to :student
end
classStudent < ActiveRecord::Base
has_many :books_students
has_many :books, :through => :books_students
end
so you can do something like #student.books or #student.student_books.where(:status =>2)

Resources