ruby on rails-hasmany-through,但具有唯一的源代码和多个关联


  • 作为用户,我可以将我最喜欢的书添加到我的书单中
  • 另一个用户将同一本书添加到他们的图书列表中
  • 数据库中应该只有一个图书实例,但有两个用户/图书关联。

    class User
      has_many :bookReferences
      has_many :books, through: :bookReferences
    class Book
      validates_uniqueness_of :title
      has_many :bookReferences
      has_many :users, through: :bookReferences
    class BookReference
      belongs_to :user
      belongs_to :book
    

第一个问题是,如果该书已经在系统中,则不会为第二个用户创建bookReference,因为该书不是唯一的

因此,如果书已经在系统中,我只想在bookReference表中创建关联记录。

第二个问题是,当用户删除一本书时,我只希望它删除对该书的引用,除非他们是唯一引用该书的用户

基本上,这是我试图实现的用法的完整概述:

    user1.books.first
      => id: 1, title: "Moby Dick"
    user2.books.first
      => id: 1, title: "Moby Dick"
    books.all
      => id: 1, title: "Moby Dick"

    user1.books.first.destroy
    user1.books.first
      => nil
    books.all
      => id: 1, title: "Moby Dick"
    user2.books.first
      => id: 1, title: "Moby Dick"
    user2.books.first.destroy
      => nil
    books.all
      => nil

更新

根据这些答案,也许我不是很清楚。让我再试一次。。。书籍控制器,有一个基本的CRUD创建方法:

    def create
      current_user.books.create(name: params[:book][:title])

按照当前设置has_many through关联的方式,只有当图书是唯一的时,才会创建该图书。如果它已经在系统中,它将返回false。我想让它与现有的书建立联系,就好像它是一张新唱片一样。这就是我目前在应用程序中所做的,以实现这一点,但感觉不对:

   def create
     book = Book.where(name: params[:book][:title]).first_or_create!
     BookReference.where(book_id: book.id, user_id: current_user.id).first_or_create!

第二个问题是当用户从他们的帐户中删除一本书时。进行传统的CRUD销毁将从所有帐户中删除:

    def destroy
      book = current_user.books.find(params[:id])
      book.destroy

因此,为了解决这个问题,我目前正在做以下工作。不过,这感觉并不"正确":

    def destroy
      book = current_user.books.find(params[:id])
      # if book was unique to user
      if BookReference.where(book_id: book.id).count == 1
        # remove book from system
        book.destroy  
      else
        # remove book reference but not book
        current_user.books.delete(book)
      end
end  
当您使用has_many through关联时,

rails会自动为您创建图书参考。

在您的用户模型中创建了一个名为:book_ids的"隐藏列">

所以在你的表单中,如果你想"保存"一本书给用户,你会使用

<%= form_for (@user) do |f| %>
.
.
.
<%= f.label :book_ids %>
<%= f.select :book_ids, Book.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %>

您的图书参考应该自动填充,您可以在视图中显示它。编辑和销毁也会自动为您完成。当您删除或编辑时,它将只是图书参考表。

如果你想了解更多关于协会的信息,你可以去

http://api.rubyonrails.org/

并搜索ActiveRecord::Associations

我对rails还是有点陌生,但这就是我想到的。

book = user1.books.first
if book.users.size > 1 
  user1.books.first.destroy
else
  book.destroy 
end
# in order to delete the book's dependency, you will need
class Book
has_many :bookReferences, :dependent => :destroy

希望这能有所帮助。

注意:当您有一个名为BookReference的模型时,您将该模型称为:book_reference在您的情况下,您需要更改为

class User
  has_many :book_references
  has_many :books, through: :book_references
class Book
  validates_uniqueness_of :title
  has_many :book_references
  has_many :users, through: :book_references
class BookReference
  belongs_to :user
  belongs_to :book

更新:

由于您希望新书在数据库中不存在时创建,因此可以利用的rails方法之一是Book.find_or_create()。我不想详细介绍,但我觉得以后你会想要一个自动完成功能来查找书籍。看看这个关于自动完成的railscast。Ryan Bates在设置自动完成并在找不到新条目时创建新条目方面做得很好,这就是你想要的。

此外,如果您需要一种更简单的方法来允许用户添加多本书,这里有另一个railscast,它会教您有关令牌字段

相关内容

  • 没有找到相关文章

最新更新