#ruby-on-rails #ruby #orm #ruby-on-rails-5
#ruby-on-rails #ruby #orm #ruby-on-rails-5
Вопрос:
Я пытаюсь использовать полиморфные отношения с rails 5.
Мне трудно понять, как завершить мои отношения.
У меня есть пользователи, которые могут бронировать отели, рестораны и т.д.
Моя цель — получить название отеля и бронирование при вызове / users / {id} через API.
Вот моя пользовательская модель :
class User < ApplicationRecord
has_many :reservations, as: :reservable
has_many :hotels, through: :reservations
end
Моя модель отеля :
class Hotel < ApplicationRecord
has_many :reservations, as: :reservable
belongs_to :users, through: :reservations
end
Моя модель резервирования :
class Reservation < ApplicationRecord
belongs_to :reservable, polymorphic: true
belongs_to :users
belongs_to :hotels
end
Миграции :
Пользователь :
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :email
t.timestamps
end
end
end
Оговорки :
class CreateReservations < ActiveRecord::Migration[5.0]
def change
create_table :reservations do |t|
t.belongs_to :hotel, index: true
t.belongs_to :user, index: true
t.datetime :date_from
t.datetime :date_to
t.timestamps
end
end
end
class ReservationPolymorphism < ActiveRecord::Migration[5.0]
def change
rename_column :reservations, :hotel_id, :reservable_id
change_column :reservations, :reservable_id, polymorphic: true
add_column :reservations, :reservable_type, :string
end
end
Гостиница :
class CreateHotels < ActiveRecord::Migration[5.0]
def change
create_table :hotels do |t|
t.string :name
t.string :address
t.string :postal_code
t.string :town
t.timestamps
end
end
end
У меня есть только 1 строка в моей таблице резервирования :
mysql> select * from reservations;
---- --------------- ----------------- --------- --------------------- --------------------- --------------------- ---------------------
| id | reservable_id | reservable_type | user_id | date_from | date_to | created_at | updated_at |
---- --------------- ----------------- --------- --------------------- --------------------- --------------------- ---------------------
| 1 | 1 | Hotel | 1 | 2017-01-12 00:00:00 | 2017-01-15 00:00:00 | 2016-10-19 09:18:01 | 2016-10-19 09:18:01 |
---- --------------- ----------------- --------- --------------------- --------------------- --------------------- ---------------------
У меня нет результата при использовании API.
Вот что я получаю, используя консоль Rails :
2.2.3 :001 > thomas = User.find(1)
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
=> #<User id: 1, first_name: "Thomas", last_name: "Dupont", email: "thomas.dupont@yopmail.com", created_at: "2016-10-18 21:12:12", updated_at: "2016-10-18 21:12:12">
2.2.3 :003 > thomas.reservations
Reservation Load (0.3ms) SELECT `reservations`.* FROM `reservations` WHERE `reservations`.`reservable_id` = 1 AND `reservations`.`reservable_type` = 'User'
2.2.3 :005 > thomas.hotels
NameError: uninitialized constant User::Hotels
Итак, я вижу, что совершаю основную ошибку с отношениями rails и полиморфизмом, но я действительно не могу понять, где я ошибаюсь.
Я думаю, что допустил ошибку. Я предположил, что полиморфизм может использоваться для загрузки других моделей и их таблиц (например, «MorphTo» с помощью eloquent / laravel), тогда как это просто для загрузки модели, которая не имеет представления данных (как описано в этом сообщении :https://robots.thoughtbot.com/using-polymorphism-to-make-a-better-activity-feed-in-rails )
Комментарии:
1. Не могли бы вы, пожалуйста, удалить дополнительные ассоциации, написанные в моделях User и Hotel. пожалуйста, удалите следующее: ‘has_many :hotels, через: :reservations’ из User и ‘belongs_to :users, через: :reservations’ из Hotel. а затем запустите запросы в консоли
2. Только что сделал это и все еще получил проблему «Выбор загрузки резервирования (0,4 мс)
reservations
.* ИЗreservations
ГДЕreservations
.reservable_id
= 1 Иreservations
.reservable_type
= ‘User’ => #<ActiveRecord::Associations::CollectionProxy []> «.3. не могли бы вы, пожалуйста, удалить это тоже из модели бронирования, belongs_to:пользователи, belongs_to: отели
4. Все равно получаем тот же результат. Я думаю, что проблема в том, что я использую отношения «неправильным способом», поскольку он ищет тип «Пользователь» в таблице резервирования, тогда как я хочу, чтобы он загружал бронирование отелей.
5. Не могли бы вы также добавить файлы миграции? из вышеупомянутых моделей?
Ответ №1:
Я предполагаю, что при просмотре вашего кода вы написали дополнительные ассоциации поверх полиморфной ассоциации,
Для создания полиморфной ассоциации достаточно просто следующего кода. Нет необходимости передавать дополнительную ассоциацию внутри модели. Пожалуйста, измените свой код следующим образом, модель пользователя
class User < ApplicationRecord
has_many :reservations, as: :reservable
end
Модель отеля :
class Hotel < ApplicationRecord
has_many :reservations, as: :reservable
end
Модель резервирования :
class Reservation < ApplicationRecord
belongs_to :reservable, polymorphic: true
end
И в файле миграции для резервирования добавьте резервируемый, как показано ниже
t.references :reservable, polymorphic: true
Комментарии:
1. Хорошо, я получил первую ошибку, которую я делаю: пользователь не резервируется. Пользователь имеет множество резервирований через отношения user_id, а не «reservable_id». Я должен выяснить отношение user -> hotels, чтобы оно полностью работало.
2. Он продолжает искать «2.2.3:001 > u = User.find (1) Загрузка пользователя (0,5 мс) ВЫБЕРИТЕ
users
.* ИЗusers
ЧЕГОusers
.id
= 1 ОГРАНИЧЕНИЕ 1 => #<Идентификатор пользователя: 1, имя пользователя: «Thomas», фамилия: «Dupont», электронная почта: «thomas.dupont@yopmail.com «, created_at: «2016-10-18 21:12:12», updated_at: «2016-10-18 21:12:12»> 2.2.3 :002 > u.загрузка резервирования (0,4 мс) ВЫБЕРИТЕreservations
.* ИЗreservations
ГДЕreservations
.reservable_id
= 1 Иreservations
.reservable_type
= ‘User’ => #<ActiveRecord::Associations::CollectionProxy []> «. Это не то поведение, которое я ищу.
Ответ №2:
Хорошо, я разобрался с этим :
Это модель резервирования :
class Reservation < ApplicationRecord
belongs_to :reservable, polymorphic: true
end
Это модель отеля :
class Hotel < ApplicationRecord
end
И пользовательская модель :
class User < ApplicationRecord
has_many :reservations
end
И как я получил результаты в консоли rails :
Running via Spring preloader in process 87452
Loading development environment (Rails 5.0.0.1)
2.2.3 :001 > u = User.find(1)
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
=> #<User id: 1, first_name: "Thomas", last_name: "Dupont", email: "thomas.dupont@yopmail.com", created_at: "2016-10-18 21:12:12", updated_at: "2016-10-18 21:12:12">
2.2.3 :002 > u.reservations
Reservation Load (0.3ms) SELECT `reservations`.* FROM `reservations` WHERE `reservations`.`user_id` = 1
=> #<ActiveRecord::Associations::CollectionProxy [#<Reservation id: 1, reservable_id: 1, reservable_type: "Hotel", user_id: 1, date_from: "2017-01-12 00:00:00", date_to: "2017-01-15 00:00:00", created_at: "2016-10-19 09:18:01", updated_at: "2016-10-19 09:18:01">]>
2.2.3 :003 > u.reservations.first.reservable
Hotel Load (0.3ms) SELECT `hotels`.* FROM `hotels` WHERE `hotels`.`id` = 1 LIMIT 1
=> #<Hotel id: 1, name: "HYATT REGENCY HOTEL", address: "3 Place du Général Kœnig", postal_code: "75017", town: "PARIS", created_at: "2016-10-19 08:36:55", updated_at: "2016-10-19 08:36:55">