【问题标题】:How to set an instance of a model as an attribute of another model in Rails?如何在 Rails 中将模型的实例设置为另一个模型的属性?
【发布时间】:2021-07-06 08:55:12
【问题描述】:

我是 Rails 的新手,正在开发一个应用程序,该应用程序允许用户创建一个 List,其中包含他们在某个类别中排名前 5 位的 Items。我遇到的主要问题是如何跟踪List 订单(应该允许更改,并且每个User 都会有所不同)?

我的Items 可以属于许多Lists,我的Lists 应该有许多Items 所以,截至目前,我使用has_and_belongs_to_many 关联我的ItemList 模特。

我现在跟踪列表顺序的想法是让我的@list 有 5 个属性:列表中的每个排名都有一个(即:first, :second, :third, :fourth, :fifth),我正在尝试关联@item 实例到@list 属性(即@list.first = @item1, @list.second = @item2 等...)。现在我将@list 属性保存到@item ID (@list.first = 1),但我更希望能够调用方法.first.second 等并直接在特定@ 987654341@实例。

这是我当前的 listsitems 架构和 has_and_belongs_to_many 关联所需的连接表 list_nominations - 我很确定我没有正确使用(:points 中的属性items 将成为跟踪 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

这是我的ListItem 模型中的代码:

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 的多个实例?

【问题讨论】:

  • 你好,你能分享一下模型里面的代码和他们的架构吗?
  • 刚刚添加了模型和架构。

标签: ruby-on-rails activerecord associations instance


【解决方案1】:

恐怕你的表不适合任何已知的方法,你可以实现你想要的,但这不是一个完美的也不是推荐的解决方案,你可以在许多 has_one 上指定主键lists 中的关联,但在 items 中,不可能将所有 lists 都放在一个关联中,但您可以有一个实例方法来查询 lists 并返回匹配的那些

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(您的表需要一个字段才能正确指向彼此)

我建议遵循many-to-many through 关系指南(单传递关联):

您将需要 1 个额外的表,因为您要跟踪订单(第一、第二等)

数据库:

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

您可以通过这里https://guides.rubyonrails.org/association_basics.html#the-has-many-through-associationhttps://guides.rubyonrails.org/association_basics.html#the-has-many-through-association阅读更多关于多对多的信息。

这里有两种方法的区别https://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many

【讨论】:

  • 这很棒。谢谢!能够重构以合并您推荐的方式,并且它更清洁并且按照我需要的方式工作。我的 list#create 操作似乎有点臃肿,因为我不确定是否有一种简单的方法可以同时将item 及其ranklist 关联起来。但现在,我会接受它。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-09
  • 2016-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-21
  • 1970-01-01
相关资源
最近更新 更多