如何在 Rails 中将一个模型的实例设置为另一个模型的属性?
How to set an instance of a model as an attribute of another model in Rails?
我是 Rails 的新手,正在开发一款允许用户制作 List
的应用程序,其中包含他们在某个类别中排名前 5 的 Item
。我遇到的主要问题是如何跟踪 List
订单(应该允许更改并且每个 User
都不同)?
我的 Item
可以属于很多 List
而我的 List
应该有很多 Item
所以,截至目前,我正在使用 has_and_belongs_to_many
我的 Item
和 List
模型的关联。
我现在跟踪列表顺序的想法是让我的 @list
有 5 个属性:一个对应列表中的每个排名(即 :first, :second, :third, :fourth, :fifth
),我正在尝试将 @item
实例关联到 @list 属性(即 @list.first = @item1, @list.second = @item2
等)。现在我将 @list
属性保存到 @item
ID (@list.first = 1
),但我希望能够调用方法 .first
或 .second
等等,并直接指向特定的 Item
实例。
这是我当前的 lists
、items
架构以及 has_and_belongs_to_many
关联所需的连接 table list_nominations
- 我是很确定我没有正确使用(items
中的 :points
属性将是跟踪 item
:
流行度的一种方式
create_table "lists", force: :cascade do |t|
t.integer "user_id"
t.integer "category_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "first"
t.string "second"
t.string "third"
t.string "fourth"
t.string "fifth"
end
create_table "items", force: :cascade do |t|
t.string "name"
t.integer "category_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "points", default: 0
end
这是目前在我的 List
和 Item
模型中的代码:
class List < ApplicationRecord
belongs_to :user
belongs_to :category
has_and_belongs_to_many :items
end
class Item < ApplicationRecord
belongs_to :category
has_and_belongs_to_many :lists
end
有没有办法做到这一点,或者有什么建议可以更好地跟踪 List
订单,而无需创建相同 Item
的多个实例?
恐怕你的 table 不适合任何已知的方法,你可以实现你想要的,但这不是一个完美的 也不是推荐的 解决方案,您可以在 lists
内的许多 has_one 关联上指定主键,但在 items
中不太可能在一个关联中拥有所有 lists
但您可以使用实例方法哪个查询 lists
和 returns 匹配的
hacky 解决方案:
class List < ApplicationRecord
belongs_to :user
belongs_to :category
has_one :first_item, primary_key: :first, class_name: "Item"
has_one :second_item, primary_key: :second, class_name: "Item"
has_one :third_item, primary_key: :third, class_name: "Item"
has_one :fourth_item, primary_key: :fourth, class_name: "Item"
has_one :fifth_item, primary_key: :fifth, class_name: "Item"
end
class Item < ApplicationRecord
belongs_to :category
def lists
List.where(
"first = ? OR second = ? OR third = ? OR fourth = ? OR fifth = ?", self.id, self.id, self.id, self.id, self.id
)
end
end
您可以在此处阅读有关如何通过 has_and_belongs_to_many
关联创建多对多关系的信息:https://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association(您的 table 需要一个字段来正确指向每个其他)
我建议您遵循 many-to-many through
关系指南(单传递关联):
您将需要 1 个额外的 table 因为您要跟踪订单(第一、第二等)
数据库:
create_table "lists", force: :cascade do |t|
.. all your other fields without first,second, etc..
end
create_table "items", force: :cascade do |t|
.. all your other fields
end
create_table "lists_items", force: :cascade do |t|
t.integer "list_id"
t.integer "item_id"
t.integer "rank" there is where you will store your order (first, second ..) bas as an integer
end
型号:
class ListsItem < ApplicationRecord
belongs_to :list
belongs_to :item
end
class List < ApplicationRecord
belongs_to :user
belongs_to :category
has_many :lists_items, -> { order(:rank) }, limit: 5
has_many :items, through: :lists_items
end
class Item < ApplicationRecord
belongs_to :category
has_many :lists_items
has_many :lists, through: :lists_items
end
您可以通过 has_many 通过此处 https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
阅读更多关于多对多的信息
我是 Rails 的新手,正在开发一款允许用户制作 List
的应用程序,其中包含他们在某个类别中排名前 5 的 Item
。我遇到的主要问题是如何跟踪 List
订单(应该允许更改并且每个 User
都不同)?
我的 Item
可以属于很多 List
而我的 List
应该有很多 Item
所以,截至目前,我正在使用 has_and_belongs_to_many
我的 Item
和 List
模型的关联。
我现在跟踪列表顺序的想法是让我的 @list
有 5 个属性:一个对应列表中的每个排名(即 :first, :second, :third, :fourth, :fifth
),我正在尝试将 @item
实例关联到 @list 属性(即 @list.first = @item1, @list.second = @item2
等)。现在我将 @list
属性保存到 @item
ID (@list.first = 1
),但我希望能够调用方法 .first
或 .second
等等,并直接指向特定的 Item
实例。
这是我当前的 lists
、items
架构以及 has_and_belongs_to_many
关联所需的连接 table list_nominations
- 我是很确定我没有正确使用(items
中的 :points
属性将是跟踪 item
:
create_table "lists", force: :cascade do |t|
t.integer "user_id"
t.integer "category_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "first"
t.string "second"
t.string "third"
t.string "fourth"
t.string "fifth"
end
create_table "items", force: :cascade do |t|
t.string "name"
t.integer "category_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "points", default: 0
end
这是目前在我的 List
和 Item
模型中的代码:
class List < ApplicationRecord
belongs_to :user
belongs_to :category
has_and_belongs_to_many :items
end
class Item < ApplicationRecord
belongs_to :category
has_and_belongs_to_many :lists
end
有没有办法做到这一点,或者有什么建议可以更好地跟踪 List
订单,而无需创建相同 Item
的多个实例?
恐怕你的 table 不适合任何已知的方法,你可以实现你想要的,但这不是一个完美的 也不是推荐的 解决方案,您可以在 lists
内的许多 has_one 关联上指定主键,但在 items
中不太可能在一个关联中拥有所有 lists
但您可以使用实例方法哪个查询 lists
和 returns 匹配的
hacky 解决方案:
class List < ApplicationRecord
belongs_to :user
belongs_to :category
has_one :first_item, primary_key: :first, class_name: "Item"
has_one :second_item, primary_key: :second, class_name: "Item"
has_one :third_item, primary_key: :third, class_name: "Item"
has_one :fourth_item, primary_key: :fourth, class_name: "Item"
has_one :fifth_item, primary_key: :fifth, class_name: "Item"
end
class Item < ApplicationRecord
belongs_to :category
def lists
List.where(
"first = ? OR second = ? OR third = ? OR fourth = ? OR fifth = ?", self.id, self.id, self.id, self.id, self.id
)
end
end
您可以在此处阅读有关如何通过 has_and_belongs_to_many
关联创建多对多关系的信息:https://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association(您的 table 需要一个字段来正确指向每个其他)
我建议您遵循 many-to-many through
关系指南(单传递关联):
您将需要 1 个额外的 table 因为您要跟踪订单(第一、第二等)
数据库:
create_table "lists", force: :cascade do |t|
.. all your other fields without first,second, etc..
end
create_table "items", force: :cascade do |t|
.. all your other fields
end
create_table "lists_items", force: :cascade do |t|
t.integer "list_id"
t.integer "item_id"
t.integer "rank" there is where you will store your order (first, second ..) bas as an integer
end
型号:
class ListsItem < ApplicationRecord
belongs_to :list
belongs_to :item
end
class List < ApplicationRecord
belongs_to :user
belongs_to :category
has_many :lists_items, -> { order(:rank) }, limit: 5
has_many :items, through: :lists_items
end
class Item < ApplicationRecord
belongs_to :category
has_many :lists_items
has_many :lists, through: :lists_items
end
您可以通过 has_many 通过此处 https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
阅读更多关于多对多的信息