rails has_many multiple single table inheritance - postgresql

I have a couple base models, Post and Comment, with a post having many comments:
class Post < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to: :post
end
I also have single table inheritance on each of these models, with the child classes not having their own database tables. I have type columns in the posts and comments tables.
class ChildPost < Post
has_many :child_comments, class_name: "Comment"
end
class ChildComment < Comment
belongs_to :child_post, class_name: "ChildPost"
end
Now if I create some of these objects
child_comment = ChildComment.create
child_post = ChildPost.create
child_post.child_comments << child_comment
child_post.save
When I do child_post.child_comments I get:
PG::UndefinedColumn: ERROR: column comments.child_post_id does not exist
It's correct that the column child_post_id doesn't exist (it's post_id), but what do I need to do to correct this?
In terms of design, I've set things up this way because the data of a child_comment and a comment are the same, but they have slightly different behavior. I want ChildComment to override only some methods of Comment. And I want a comment and child_comment to be distinguishable database entries.
If there's a better design here, I'm open to it.

You need to specify both :class_name and :foreign_key in your has_many association:
has_many :child_comments, class_name: "Comment", :foreign_key => "post_id"
The :foreign_key option lets you set the name of the foreign key directly. So, if you set that to post_id, then it will work because post_id column is present in the comments table.

Related

Rails model has_many order desc group by only containing model

post.similarities.order("similarity DESC").group_by(:afterscholar_id).first(4).each_with_index
My post has similarities, and I need to be searching exclusively through the ones that contain anything more than 'nil' in the variable afterscholar_id

Cannot use group with has_many through in Rails 5

I have the following associations:
class Student < ApplicationRecord
has_many :people_schools
has_many :schools, through: :people_schools
end
class PeopleSchool < ApplicationRecord
belongs_to :student
belongs_to :school
end
class School < ApplicationRecord
has_many :people_schools
has_many :students, through: :people_schools
end
I am trying to get a list of students organized by their school. I have tried the following:
Student.joins(:schools).all.group('schools.name')
but I get the following error:
ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "students.id" must appear in the GROUP BY clause or be used in an aggregate function
How do I fix this?
When the association fires, it will generate a SQL query like
SELECT students.id, students. ...
FROM students
JOIN schools
ON ...
GROUP BY schools.name
In sql when grouping, a projection (SELECT) can only include columns that are grouped by or aggregations (e.g. MAX, MIN) of columns (regardless of whether they are grouped by). Therefore adding something like the following would turn it into a valid sql:
# column that is grouped by
Student.joins(:schools).group('schools.name').select('schools.name')
# aggregate function
Student.joins(:schools).group('schools.name').select('schools.name, COUNT(students.id)')
But how you want to fix it in your case depends on what you want to get out of the query.
In answer to the comment
Assuming a student is only member of a single school, which requires changing the association to a belongs_to :school (without the join table) or a has_one :school (with join table).
Student.includes(:school).group_by(&:school)
This will issue an SQL statement to get all students and their school (eager loaded for optimization). Only after the models (Student, School) are instantiated ruby objects, is the group_by method evaluated, which will return a Hash where the school is the key referencing an Array of students.

three models with HABTM how to reach the third model from first in one query

I am having a basic problem of HABTM.
I have three models, Singer, Song, Album
Singer <=habtm=> Song <=habtm=> Album
I simply want to know how to find count of albums(distinct) which first singer have.
How do we deal with this single problem.
Can I reduce a query to one liner. If there is some better data model that can be suggested that is also welcome.
Use :through
A has_many :through association is often used to set up a many-to-many
connection with another model. This association indicates that the
declaring model can be matched with zero or more instances of another
model by proceeding through a third model. For example, consider a
medical practice where patients make appointments to see physicians.
The relevant association declarations could look like this:
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, through: :appointments
end
UPDATE 1:
Try some join tables.
class Physician < ActiveRecord::Base
has_many :appointment_physicians
has_many :appointments, through :appointment_physicians
end
class Appointment < ActiveRecord::Base
has_many :physicians, through :appointment_physicians
end
class AppointmentPhysician < ActiveRecord::Base
belongs_to :appointment
belongs_to :physician
end

many to many relationships with mongoid

I'm wondering on how to do a many to many relationship with mongoid. Here is a visual representation of the models, with the small ones being join tables:
!http://i.imgur.com/lJxoRSb.jpg
I have set up my model like this (as an example) using RoR:
class Event
include Mongoid::Document
field :name, type: String
field :place, type: String
field :when, type: String
field :price, type: Integer
field :participants, type: Integer
field :short_description, type: String
has_many :users
#has_many :users, :through => :user_events
end
what would i need to join the event model with user model with interest model (if this is even possible)? I know mongoid isn't the best option for this but i'm stuck with using it.
Thanks in advance!
Try the following:
embeds_many :user_events
See also http://mongoid.org/en/mongoid/v3/relations.html#embeds_many
Do not use join tables in MongoDB, use arrays of embedded objects/references instead. MongoDB has array values, take advantage of them!
With a many-to-many relationship, you have a choice on placing the references on the first collection, or the second collection, or on both. If you put references in both collections, you have to do your own updates for consistency as needed by your application.

Creating a polymorphic association using MySQL Workbench

How do I create a polymorphic relation using the MySQL Workbench tool? I want to be able to handle something like what Rails gives me with:
class Example < ActiveRecord::Base
belongs_to :someone, polymorphic: true
end
class PolyOne < ActiveRecord::Base
has_many :examples, as: :someone
end
class PolyTwo < ActiveRecord::Base
has_many :examples, as: :someone
end
If you utilize the "Place a relationship using existing columns," the icon with the 1:N and dropper, you'll be able to accomplish this task. In the examples table (Rails always pluralizes), make sure you have two columns: someone_id and someone_type. In the polymorphic tables, you should already have an id column. Then, you choose the tool mentioned at first (1:N with dropper) and click on someone_id followed by the id of the polymorphic table. This will create a new 1:N relationship between those two fields without inserting any new fields into the tables. Repeat this process for each connected polymorphic table. It will then represent the polymorphic relationship that Rails uses. If you are trying to mimic this on your own without Rails, you'll need to be sure to set the someone_id and someone_type appropriately so that you can follow the polymorphic relationship properly.