【问题标题】:Rails polymorphic relationsRails 多态关系
【发布时间】:2016-10-19 07:36:42
【问题描述】:

我正在尝试使用 rails 5 的多态关系。

我很难弄清楚如何结束我的关系。

我有用户,他们可以预订酒店、餐馆等。

我的目的是在通过 API 调用 /users/{id} 时获取酒店名称和预订信息。

这是我的用户模型:

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 关系和多态性方面犯了基本错误,但我真的不知道我错在哪里。

我想我犯了一个错误。 我假设多态性可用于加载其他模型及其表(例如带有 eloquent / laravel 的“morphTo”),而它只是加载没有数据表示的模型(如本文所述:https://robots.thoughtbot.com/using-polymorphism-to-make-a-better-activity-feed-in-rails

【问题讨论】:

  • 您能否删除在用户和酒店模型中编写的额外关联。请从用户中删除以下内容“has_many :hotels, through::reservations”和从酒店中删除“belongs_to :users, through::reservations”。然后在控制台中运行查询
  • 刚做了,仍然得到“保留负载(0.4ms)选择reservations.* FROM reservations WHERE reservations.reservable_id = 1 AND reservations.reservable_type = '用户' => #<:associations::collectionproxy> "问题。
  • 你能不能也从预订模型中删除这个,belongs_to :users belongs_to :hotels
  • 仍然得到相同的结果。我认为 pb 是我以“错误的方式”使用关系,因为它在预订表中寻找“用户”类型,而我希望它加载酒店预订。
  • 能否请您也添加迁移文件?上述型号?

标签: ruby-on-rails ruby orm ruby-on-rails-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

【讨论】:

  • 好吧,我犯的第一个错误是:用户不可保留。用户通过 user_id 关系而不是“reservable_id”进行了预订。我必须弄清楚用户 -> 酒店的关系才能使其充分发挥作用。
  • 它一直在寻找 "2.2.3 :001 > u = User.find(1) User Load (0.5ms) SELECT users.* FROM users WHERE users.id = 1 LIMIT 1 => # 2.2.3 :002 > u.reservations 预留负载 (0.4ms) SELECT reservations.* FROM reservations WHERE reservations.reservable_id = 1 AND reservations.reservable_type = '用户' => #<: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"> 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多