【问题标题】:Rails ActiveRecord model associationRails ActiveRecord 模型关联
【发布时间】:2013-10-14 19:55:37
【问题描述】:

我有一个User model 和一个product model

User has_many :products, :dependent => :destroy
Product belongs_to :user, :foreign_key => "user_id", touch: true

我想为每个用户创建一个愿望清单。 所以我必须创建一个具有适当关联的wishlist model。 但我不知道如何开始。 我假设愿望清单模型包含iduser_idproduct_id 字段

我必须使用 has_many through association 还是 has_and_belongs_to_many ? 我也希望如果一个用户被销毁来销毁他的愿望清单。

最好的方法是什么? 非常感谢!

【问题讨论】:

    标签: ruby-on-rails activerecord model associations


    【解决方案1】:

    正如@JZ11 指出的那样,您不应该将产品直接链接到用户(除非用户出于某种原因实际上“拥有”产品)。然而,遗漏的是构成愿望清单项目的模型:

    class User < ActiveRecord::Base
      has_many :wishlists       # or has_one, depending on how many lists a User can have...
    end
    
    class Product < ActiveRecord::Base
      has_many :wishlist_items
    end
    
    class Wishlist < ActiveRecord::Base
      belongs_to :user
      has_many :wishlist_items
      has_many :products, :through => :wishlist_items
    end
    
    class WishlistItem < ActiveRecord::Base
      belongs_to :product
      belongs_to :wishlist
    end
    

    当然,您应该在必要时添加:dependent =&gt; :destroy

    【讨论】:

    • 好吧,我在想办法!谢谢。但是如何正确生成 Wishlist 和 WishlistItem 模型?
    • 就我个人而言,我会手动“生成”它,这样我就可以准确地知道创建所有内容的内容、原因和位置。如果要使用模型生成器,可以运行:rails g model Wishlist user_id:integerrails g model WishlistItem wishlist_id:integer product_id:integer。在每个模型上添加您可能需要的任何描述性字段。
    • 最后一件事。我不能在控制台中创建这样的 whislit 是否正常? : User.find(2).wishlist.create 我必须做 : Wishlist.create(user_id: 2)
    • @JonnyxDelavilla:如果您将关联定义为has_many(就像我上面所说的那样),您将使用:User.find(2).wishlists.create(...)。如果您将其更改为使用 has_one :wishlist,您将执行以下操作:User.find(2).create_wishlist(...)。有关更多信息,请参阅docs
    【解决方案2】:

    您不需要User 上的has_many :products 关系。 我认为将UserProduct 链接到Wishlist 之外是没有意义的。

    class Wishlist < ActiveRecord::Base
      has_many :products
      belongs_to :user
    end
    
    class User < ActiveRecord::Base
      has_one :wishlist, dependent: :destroy
    end
    
    class Product < ActiveRecord::Base
      belongs_to :wishlist
    end
    

    【讨论】:

    • 好的,谢谢,这似乎是一个很好的解决方案。这个模型生成对吗? rails g 模型愿望清单 user_id:integer product_id:integer ?
    • 这里有一个问题,产品不应该属于特定用户的愿望清单...当另一个用户想要将产品添加到他们的愿望清单时你会怎么做?
    【解决方案3】:

    要创建连接表,请执行以下操作:

    rails g migration create_products_users_table
    

    完成此操作后,您需要在下面添加一些代码,以在连接表中创建字段。注意:id =&gt; false,因为您确实不需要在连接表中需要一个 id:

    class CreateProductsUsersTable < ActiveRecord::Migration
      def change
        create_table :products_users, :id => false do |t|
          t.references :product
          t.references :user
        end
        add_index :products_users, [:product_id, :user_id]
        add_index :products_users, :user_id
      end
    end
    

    上面的代码还创建了一些索引,并确保即使在数据库级别也没有重复。

    您的模型必须如下所示:

    class Product < ActiveRecord::Base
      has_and_belongs_to_many :users
    end
    
    class User < ActiveRecord::Base
      has_and_belongs_to_many :products
    end
    

    当您正确地销毁用户时,例如user.destroy 而不仅仅是删除它(有区别),那么连接表中的相关行也将被删除。这是 ActiveRecord 内置的。

    但请注意,这样做不会真正让您使用连接表。它将接受user.products = [product1, product2] 等代码和其他好东西,但不会真正使用愿望清单。

    如果您确实想使用愿望清单,则必须使用 has_many :through 以不同的方式创建和使用中间连接表(我没有检查 PinnyM 的答案,但这可能是这样做的方法)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-15
      • 1970-01-01
      相关资源
      最近更新 更多