#mysql #ruby-on-rails #activerecord #join #ruby-on-rails-4
#mysql #ruby-on-rails #activerecord #Присоединиться #ruby-on-rails-4
Вопрос:
У меня немного сложный дизайн модели со многими ассоциациями между собой. Вот дизайн модели
Пользовательская модель
class User < ActiveRecord::Base
has_many :records
has_many :sources
has_many :record_type_student
has_many :record_type_employee
has_many :record_type_other
validates :email, presence: true
end
Модель Souces
class Source < ActiveRecord::Base
belongs_to :user
has_many :records
has_many :record_type_student
has_many :record_type_employee
has_many :record_type_other
end
Модель записи
class Record < ActiveRecord::Base
belongs_to :user
belongs_to :source
has_many :record_type_student
has_many :record_type_employee
has_many :record_type_other
end
Модель RecordTypeStudent
class RecordTypeStudent < ActiveRecord::Base
belongs_to :record
belongs_to :user
belongs_to :source
end
Аналогичная модель для двух других RecordTypeOther и RecordTypeEmployee
Я могу правильно сохранять данные, и я проверил, что каждая recordtype*
таблица содержит в ней record_id, и теперь я пытаюсь получить доступ к данным с помощью includes
. Вот что я пытаюсь запросить
@records = Record.includes(:record_type_stduents, :record_type_others, :record_type_employees).where(User.find_by_email(params[:user].to_s).id).all;
но я получаю только поля записей взамен, а не данные после присоединения
Здесь генерируется запрос
Record Load (1.9ms) SELECT `records`.* FROM `records` WHERE `records`.`user_id` = 1 RecordTypeStudent Load (7.9ms) SELECT `record_type_students`.* FROM `record_type_students` WHERE `record_type_students`.`record_id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25) RecordTypeOther Load (2.4ms) SELECT `record_type_others`.* FROM `record_type_students` WHERE `record_type_students`.`record_id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25) RecordTypeEmployee Load (2.0ms) SELECT `record_type_employees`.* FROM `record_type_employees` WHERE `record_type_employees`.`recordt_id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
Вот когда я пытаюсь извлечь из пользовательской модели
DEPRECATION WARNING: Relation#all is deprecated. If you want to eager-load a relation, you can call #load (e.g. `Post.where(published: true).load`). If you want to get an array of records from a relation, you can call #to_a (e.g. `Post.where(published: true).to_a`). (called from irb_binding at (irb):15)
User Load (3.4ms) SELECT `users`.* FROM `users` INNER JOIN `records` ON `records`.`user_id` = `users`.`id` WHERE `users`.`user_id` = 1
Mysql :: Ошибка: неизвестный столбец ‘users.user_id’ в ‘предложении where’: ВЫБЕРИТЕ users
.* ИЗ users
ВНУТРЕННЕГО СОЕДИНЕНИЯ records
НА records
. user_id
= users
. id
WHERE users
. user_id
= 1 ActiveRecord::StatementInvalid: Mysql :: Ошибка: неизвестный столбец ‘users.user_id’ в ‘предложении where’: ВЫБЕРИТЕ users
.* ИЗ users
ВНУТРЕННЕГО СОЕДИНЕНИЯ . = . WHERE . = 1 ActiveRecord::StatementInvalid:ПРИСОЕДИНИТЬСЯ records
К records
. user_id
= users
. id
WHERE users
. user_id
= 1
Комментарии:
1.
among themselves
— вы имели в видуself referential
объединения?2. нет, ассоциации, подобные тем, о которых я упоминал в каждой модели, не содержат ссылок на себя
3. но вы получили проблему в коде или я недостаточно хорошо объяснил здесь…
4. Просто ищу тебя сейчас!
5. я думаю, что проблема в запросе. не могли бы вы вставить сгенерированный SQL-запрос?
Ответ №1:
Я думаю, вам лучше всего использовать STI (наследование одной таблицы):
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :students, class: "User::Student"
has_many :employees, class: "User::Employee"
has_many :other, class: "User::Other"
end
#app/models/users/student.rb
Class Student < Record
end
#app/models/record.rb
Class Record < ActiveRecord::Base
belongs_to :user
end
Это даст вам следующие поля:
#users
id | user | attributes | created_at | updated_at
#records
id | type | user_id | other | record | attributes | created_at | updated_at
Это позволит вам вызвать:
user = User.find params[:id]
user.students # -> pulls records with type == "Student"
Комментарии:
1. Большое спасибо, я попробую это и сообщу вам, как это работает, но у одного ученика, у другой модели etc не будет никакой ассоциации, определенной в них
2. Я не думаю, что им это понадобится (хотя я могу ошибаться). STI в основном наследуется от родительских моделей; это означает, что вы должны иметь возможность сохранять центральную ассоциацию; хотя я могу ошибаться в этом
3. Один вопрос, я читал о STI, но не мог понять, как создавать модели, такие как Student, которые наследуются от Record … любая команда или как я бы добавил поля в модель student
4. Извините, я обновлю свой ответ для вас! Здесь есть отличный учебник: rails-bestpractices.com/posts /…