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

    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

更新

基于这些答案,也许我不是很清楚。让我再试一次... book 控制器有一个基本的 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  
4

2 回答 2

0

当您通过关联使用 has_many 时,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 %>

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

如果您想了解有关协会的更多信息,可以访问

http://api.rubyonrails.org/

并搜索 ActiveRecord::Associations

于 2012-12-31T19:43:15.737 回答
0

我对 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

希望这可以帮助。

注意:当您有一个名为 like 的模型时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(). 我不会详细介绍,但我觉得稍后你会想要一个自动完成功能来查找书籍。看看这个关于Autocomplete的 railscast 。Ryan Bates 在设置自动完成并在未找到时创建新条目方面做得很好,这正是您所寻找的。

此外,如果您需要一种更简单的方法来允许用户添加多本书籍,这里还有一个 railscast 可以教您有关Token Fields的知识

于 2012-12-31T03:09:39.483 回答